开发语言主要采用go语言,因为程序的入口为main函数,所以先从main函数开始讲起吧,main函数的实现代码如下
package main
import (
"context"
"distributed/log"
"distributed/service"
"fmt"
stlog "log"
)
func main() {
log.Run("./distributed.log")
host,port:="localhost","4000"
ctx,err:= service.Start(
context.Background(),
"Log Service",
host,
port,
log.RegisterHandlers,
)
if err!=nil{
stlog.Fatalln(err)
}
<-ctx.Done()
fmt.Println("shutting down log service.")
}
其中log.Run的调用主要是在当前目录下创建并记录程序所发的内容。
func Run(destination string){
log = stlog.New(fileLog(destination),"go: ",stlog.LstdFlags)
}
通过New方法创建日志对象,其中第一个参数为存储的文件名称,第二个参数为记录信息的前缀,最后是记录的标识。记录内容样式如下
go: 2022/01/22 14:34:34 这个内容需要记录下来
go: 2022/01/22 21:06:56 这个内容需要记录下来
go: 2022/01/22 21:09:04 这个内容需要记录下来
该函数主要用于告知系统日志文件的存储位置,存储格式。
host和port主要表示访问的地址和端口号
service.Start函数,其中参数列表依次为上下文对象(系统定义),服务名,主机号,端口号,注册服务参数(其类型为函数类型)返回类型为上下文对象,和错误对象。
func Start(ctx context.Context,serviceName,host,port string,
registerHandlersFunc func())(context context.Context,err error) {
registerHandlersFunc()
ctx = satrtService(ctx,serviceName,host,port)
return ctx,nil
}
RegisterHandlers()主要用于注册web服务
func RegisterHandlers() {
http.HandleFunc("/log", func(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodPost:
msg,err:=ioutil.ReadAll(r.Body)
if err!=nil||len(msg)==0{
w.WriteHeader(http.StatusBadRequest)
return
}
write(string(msg))
default:
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
})
}
func write(message string){
log.Printf("%v\n",message)
}
在其中调用了registerHandlersFunc函数,完成注册,又调用startService函数,其主要作用是对启动web服务和取消注册web服务
func satrtService(ctx context.Context,serviceName,host,
port string)context.Context {
ctx,cancel := context.WithCancel(ctx)
var srv http.Server
srv.Addr = ":"+ port
go func(){
fmt.Printf("第一个gorouting开始执行了")
log.Println(srv.ListenAndServe())
fmt.Printf("能不能到这里?")
cancel()//取消上下文
fmt.Printf("取消了上下文")
}()
go func() {
fmt.Printf("%v started. Press any key to stop",serviceName)
var s string
fmt.Scanln(&s)
srv.Shutdown(ctx)
cancel()
}()
return ctx
}
完整的项目文件目录