go-kit 微服务 服务注册与发现 (etcd 实现 )

etcd

简介

服务注册

  • 使用go-kit初始化一个etcdV3客户端
options := etcdv3.ClientOptions{
	DialTimeout:   ttl,
	DialKeepAlive: ttl,
}
etcdClient, err := etcdv3.NewClient(context.Background(), etcdAddrs, options)
if err != nil {
	utils.GetLogger().Error("[user_agent]  NewClient", zap.Error(err))
	return
}
Registar := etcdv3.NewRegistrar(etcdClient, etcdv3.Service{
	Key:   fmt.Sprintf("%s/%s",serName,grpcAddr),
	Value: grpcAddr,
}, log.NewNopLogger())
  • 将节点注册到服务器
Registar.Register()
  • 将节点注销
Registar.Deregister()

服务发现与负载均衡

  • 在基于《go-kit 微服务 使用Grpc(并传递请求ID)》 我们已经实现了一个grpc客户端,现在我们只需要为这个客户端添加服务发现,与负载均衡等相关操作

  • 创建一个UserAgent结构体,里面包含一个 etcdv3.Instancer 对象和一个 log.Logger对象

type UserAgent struct {
	instancerm *etcdv3.Instancer
	logger     log.Logger
}
  • 初始化UserAgent

    • 服务发现:通过etcd去查询对应服务的服务地址
    func NewUserAgentClient(addr []string, logger log.Logger) (*UserAgent, error) {
      var (
      	etcdAddrs = addr
      	serName   = "svc.user.agent"
      	ttl       = 5 * time.Second
      )
      options := etcdv3.ClientOptions{
      	DialTimeout:   ttl,
      	DialKeepAlive: ttl,
      }
      etcdClient, err := etcdv3.NewClient(context.Background(), etcdAddrs, options)
      if err != nil {
      	return nil, err
      }
      instancerm, err := etcdv3.NewInstancer(etcdClient, serName, logger)
      if err != nil {
      	return nil, err
      }
      return &UserAgent{
      	instancerm: instancerm,
      	logger:     logger,
      }, err
    

}

+ 负载均衡:把取到的服务地址按照自己需求进行处理(Random,RoundRobin等)
 
```base
func (u *UserAgent) UserAgentClient() (src.Service, error) {
  var (
  	retryMax     = 3
  	retryTimeout = 500 * time.Millisecond
  )
  var (
  	endpoints src.EndPointServer
  )
  {
  	factory := u.factoryFor(src.MakeLoginEndPoint)
  	endpointer := sd.NewEndpointer(u.instancerm, factory, u.logger)
  	balancer := lb.NewRandom(endpointer, time.Now().UnixNano())
  	retry := lb.Retry(retryMax, retryTimeout, balancer)
  	endpoints.LoginEndPoint = retry
  }
  return endpoints, nil
}

func (u *UserAgent) factoryFor(makeEndpoint func(src.Service) endpoint.Endpoint) sd.Factory {
  return func(instance string) (endpoint.Endpoint, io.Closer, error) {
  	conn, err := grpc.Dial(instance, grpc.WithInsecure())
  	if err != nil {
  		return nil, nil, err
  	}
  	srv := u.NewGRPCClient(conn)
  	endpoints := makeEndpoint(srv)
  	return endpoints, conn, err
  }
}

运行日志

  • 我们启动3个服务地址分别为(127.0.0.1:8881,127.0.0.1:8882,127.0.0.1:8883)
./user_agent -g 127.0.0.1:8881
2020-01-08 16:28:45     INFO    logtool/log.go:89       [NewLogger] success
2020-01-08 16:28:45     INFO    user_agent/main.go:75   [user_agent] run 127.0.0.1:8881


./user_agent -g 127.0.0.1:8882
2020-01-08 16:28:45     INFO    logtool/log.go:89       [NewLogger] success
2020-01-08 16:28:45     INFO    user_agent/main.go:75   [user_agent] run 127.0.0.1:8882


./user_agent -g 127.0.0.1:8883
2020-01-08 16:28:45     INFO    logtool/log.go:89       [NewLogger] success
2020-01-08 16:28:45     INFO    user_agent/main.go:75   [user_agent] run 127.0.0.1:8883
  • 运行 TestNewUserAgentClient 方法 查选3个服务器的日志输入
./user_agent -g 127.0.0.1:8881
2020-01-08 16:28:36     INFO    logtool/log.go:89       [NewLogger] success
2020-01-08 16:28:36     INFO    user_agent/main.go:75   [user_agent] run 127.0.0.1:8881
2020-01-08 16:30:00     DEBUG   src/middleware_server.go:31     [ee92f353-5e8f-526e-b0b4-970d7507e5f6]  {"调用 Login logMiddlewareServer": "Login", "req": "Account:\"hwholiday\" Password:\"123456\" ", "res": "Token:\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJO1lIjoiaHdob2xpZGF5IiwiRGNJZCI6MSwiZXhwIjoxNTc4NDcyMjMwLCJpYXQiOjE1Nzg0NzIyMDAsImlzcyI6ImtpdF92NCIsIm5iZiI6MTU3ODQ3MjIwMCwic3ViIjoibG9naW4ifQ.q6lveFqZbgl-10VcaPm4dRrwA4m9FN4i7Fqc82inclY\" ", "time": "272.061µs", "err": null}
2020-01-08 16:30:02     DEBUG   src/middleware_server.go:31     [63f4ddb2-dc6b-503a-85aa-bdf99027f91e]  {"调用 Login logMiddlewareServer": "Login", "req": "Account:\"hwholiday\" Password:\"123456\" ", "res": "Token:\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJO1lIjoiaHdob2xpZGF5IiwiRGNJZCI6MSwiZXhwIjoxNTc4NDcyMjMyLCJpYXQiOjE1Nzg0NzIyMDIsImlzcyI6ImtpdF92NCIsIm5iZiI6MTU3ODQ3MjIwMiwic3ViIjoibG9naW4ifQ.Td_pBMlkGpK-RjpIOikn1N4BF9q0nID1munt7SvN-0E\" ", "time": "105.5µs", "err": null}
2020-01-08 16:30:03     DEBUG   src/middleware_server.go:31     [fe1a7185-cf9b-5bff-91c7-58271f9eecc8]  {"调用 Login logMiddlewareServer": "Login", "req": "Account:\"hwholiday\" Password:\"123456\" ", "res": "Token:\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJO1lIjoiaHdob2xpZGF5IiwiRGNJZCI6MSwiZXhwIjoxNTc4NDcyMjMzLCJpYXQiOjE1Nzg0NzIyMDMsImlzcyI6ImtpdF92NCIsIm5iZiI6MTU3ODQ3MjIwMywic3ViIjoibG9naW4ifQ.d7yyFAH70CJvMpK1hIU-rBya0bjwNapP89j_-43liSQ\" ", "time": "40.564µs", "err": null}
2020-01-08 16:30:31     DEBUG   src/middleware_server.go:31     [eed06439-bc47-5f17-9329-9fdb3dfbce5f]  {"调用 Login logMiddlewareServer": "Login", "req": "Account:\"hwholiday\" Password:\"123456\" ", "res": "Token:\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJO1lIjoiaHdob2xpZGF5IiwiRGNJZCI6MSwiZXhwIjoxNTc4NDcyMjYxLCJpYXQiOjE1Nzg0NzIyMzEsImlzcyI6ImtpdF92NCIsIm5iZiI6MTU3ODQ3MjIzMSwic3ViIjoibG9naW4ifQ.jAbaiEPM5QZKY_bHHVb8a_WyflKHKn34l2MPHIarly4\" ", "time": "111.298µs", "err": null}
2020-01-08 16:30:33     DEBUG   src/middleware_server.go:31     [21deba8a-2de6-5c44-bd01-633225e652c2]  {"调用 Login logMiddlewareServer": "Login", "req": "Account:\"hwholiday\" Password:\"123456\" ", "res": "Token:\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJO1lIjoiaHdob2xpZGF5IiwiRGNJZCI6MSwiZXhwIjoxNTc4NDcyMjYzLCJpYXQiOjE1Nzg0NzIyMzMsImlzcyI6ImtpdF92NCIsIm5iZiI6MTU3ODQ3MjIzMywic3ViIjoibG9naW4ifQ.wJWduZ42o99DTUF6Nkhr9h4ddVCiY7G4jZtuhoHIqwE\" ", "time": "59.499µs", "err": null}
2020-01-08 16:30:36     DEBUG   src/middleware_server.go:31     [02e304ff-8ef1-5f9a-8ed6-cdd64814ea52]  {"调用 Login logMiddlewareServer": "Login", "req": "Account:\"hwholiday\" Password:\"123456\" ", "res": "Token:\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJO1lIjoiaHdob2xpZGF5IiwiRGNJZCI6MSwiZXhwIjoxNTc4NDcyMjY2LCJpYXQiOjE1Nzg0NzIyMzYsImlzcyI6ImtpdF92NCIsIm5iZiI6MTU3ODQ3MjIzNiwic3ViIjoibG9naW4ifQ._Rvw4NwSeDrSFIKkzbSVcx0k6YvFVZqGPt3bYFmJUjg\" ", "time": "71.755µs", "err": null}

./user_agent -g 127.0.0.1:8882
2020-01-08 16:28:42     INFO    logtool/log.go:89       [NewLogger] success
2020-01-08 16:28:42     INFO    user_agent/main.go:75   [user_agent] run 127.0.0.1:8882
2020-01-08 16:30:32     DEBUG   src/middleware_server.go:31     [759c5214-ec26-5788-840d-1387f6cce9be]  {"调用 Login logMiddlewareServer": "Login", "req": "Account:\"hwholiday\" Password:\"123456\" ", "res": "Token:\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJO1lIjoiaHdob2xpZGF5IiwiRGNJZCI6MSwiZXhwIjoxNTc4NDcyMjYyLCJpYXQiOjE1Nzg0NzIyMzIsImlzcyI6ImtpdF92NCIsIm5iZiI6MTU3ODQ3MjIzMiwic3ViIjoibG9naW4ifQ.QQyA9Pt3eDVRBAXc764eIX7MBZYoW8Wr-Tlvw8boyxI\" ", "time": "196.996µs", "err": null}
2020-01-08 16:30:35     DEBUG   src/middleware_server.go:31     [ec3826e3-09e6-55f6-9998-baff941a8042]  {"调用 Login logMiddlewareServer": "Login", "req": "Account:\"hwholiday\" Password:\"123456\" ", "res": "Token:\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJO1lIjoiaHdob2xpZGF5IiwiRGNJZCI6MSwiZXhwIjoxNTc4NDcyMjY1LCJpYXQiOjE1Nzg0NzIyMzUsImlzcyI6ImtpdF92NCIsIm5iZiI6MTU3ODQ3MjIzNSwic3ViIjoibG9naW4ifQ.ZljiQVypRaBrmPgzGK_aKpBbQueJdAPRAKdkzvhi0Yk\" ", "time": "858.642µs", "err": null}

./user_agent -g 127.0.0.1:8883
2020-01-08 16:28:45     INFO    logtool/log.go:89       [NewLogger] success
2020-01-08 16:28:45     INFO    user_agent/main.go:75   [user_agent] run 127.0.0.1:8883
2020-01-08 16:30:01     DEBUG   src/middleware_server.go:31     [e68ec443-5f38-58de-a874-e8ff8ed127c0]  {"调用 Login logMiddlewareServer": "Login", "req": "Account:\"hwholiday\" Password:\"123456\" ", "res": "Token:\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJO1lIjoiaHdob2xpZGF5IiwiRGNJZCI6MSwiZXhwIjoxNTc4NDcyMjMxLCJpYXQiOjE1Nzg0NzIyMDEsImlzcyI6ImtpdF92NCIsIm5iZiI6MTU3ODQ3MjIwMSwic3ViIjoibG9naW4ifQ.taUS3LxS8uTAA3loIGEeBfHuYVMgImBBNUnYvgygnVE\" ", "time": "271.665µs", "err": null}
2020-01-08 16:30:34     DEBUG   src/middleware_server.go:31     [cabaf11b-4b34-5a4c-98ca-6cc6e31b6da9]  {"调用 Login logMiddlewareServer": "Login", "req": "Account:\"hwholiday\" Password:\"123456\" ", "res": "Token:\"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJO1lIjoiaHdob2xpZGF5IiwiRGNJZCI6MSwiZXhwIjoxNTc4NDcyMjY0LCJpYXQiOjE1Nzg0NzIyMzQsImlzcyI6ImtpdF92NCIsIm5iZiI6MTU3ODQ3MjIzNCwic3ViIjoibG9naW4ifQ.yE1Lb51Ov6z-NmJRSrMAMHR1rdReflH5ngslbEttTmo\" ", "time": "114.162µs", "err": null}

结语

  • 观察日志看到client请求地址平均分布在3台服务器上,现在已经基本实现了服务注册,发现,负载均衡
  • 欢迎添加QQ一起讨论

完整代码地址

联系 QQ: 3355168235