源码已经上传,有需要可在资源下载。在分布式day01的基础上,本节的新增内容主要是注册服务并独立运行,
首先在distributed文件夹下创建registry文件夹并在其下分别创建client.go,registration.go和server.go文件。
1、client.go
package registry import ( "bytes" "encoding/json" "fmt" "net/http" ) func RegisterService(r Registration)error { buf := new(bytes.Buffer) enc := json.NewEncoder(buf) err :=enc.Encode(r) if err!=nil{ return err } res,err := http.Post(ServiceURL,"application/json",buf) if err !=nil{ return err } if res.StatusCode!=http.StatusOK{ return fmt.Errorf("Failed to register") } return nil }
主要用于客户端的注册服务,其中创建Post请求向注册地址即ServiceURL请求注册服务
2、registration.go
package registry type Registration struct { ServiceName ServiceName ServiceURL string } type ServiceName string const( LogService = ServiceName("LogService") )
创建注册信息结构体包括服务名服务地址
3、server.go
package registry import ( "encoding/json" "log" "net/http" "sync" ) const ServerPort =":3000" const ServiceURL = "http://localhost"+ServerPort+"/services" type registry struct { registrations []Registration//已经注册的服务 mutex *sync.Mutex//因为集合动态变化且可能并发访问为保证线程安全则加互斥锁 } func (r *registry)add(reg Registration)error { r.mutex.Lock() r.registrations = append(r.registrations,reg) r.mutex.Unlock() return nil } //注册的服务集群 var reg = registry{ registrations: make([]Registration,0), mutex: new(sync.Mutex), } type RegistryService struct {}//让其成为一个Handle func (s RegistryService)ServeHTTP(w http.ResponseWriter,r *http.Request) { log.Println("Request received") switch r.Method { case http.MethodPost: dec := json.NewDecoder(r.Body) var r Registration err := dec.Decode(&r) if err!=nil{ log.Println(err) w.WriteHeader(http.StatusBadRequest) return } log.Printf("Add service:%v with URL %vn",r.ServiceName,r.ServiceURL) err = reg.add(r) if err!=nil{ log.Println(err) w.WriteHeader(http.StatusBadRequest) return } default: w.WriteHeader(http.StatusMethodNotAllowed) } }
用于将请求注册的服务加入注册服务集群中,此时的RegistryService因为实现了ServeHTTP接口,故成为了一个Handle,当请求为 //访问该地址后,启动RegistryService使其成为一个handle,如下,当请求为/services时,RegistryService便会将服务信息添加到注册集群中
http.Handle("/services",®istry.RegistryService{})
在cmd包下创建如下目录
main.go的内容如下
package main import ( "context" "distributed/registry" "fmt" "log" "net/http" ) //注册服务 func main() { //访问该地址后,启动RegistryService使其称为一个handle http.Handle("/services",®istry.RegistryService{}) //创建上下文和取消上下文 ctx,cancle :=context.WithCancel(context.Background()) //创建http.Server变量 var srv http.Server //服务端口 srv.Addr = registry.ServerPort go func() { //启动服务是否成功,日志记录 log.Println(srv.ListenAndServe()) //结束线程 cancle() }() go func(){ fmt.Println("Registry service started.Press any key to stop.") var s string fmt.Scanln(&s) srv.Shutdown(ctx) cancle() }() <-ctx.Done() fmt.Println("shutting down registy service") }
其中ctx的作用,个人认为是退出服务的条件,即让<-ctx.Done不再阻塞,即可退出。
参数做如下修改
其中先执行注册服务,再执行日志服务
测试工具Postman
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)