【四】golang实战之服务注册

添加一个微服务实例的时候,微服务就会将自己的 ip 与 port 发送到注册中心,在注册中心里面记录起来。当 API gateway 需要访问某些微服务的时候,就会去注册中心取到相应的 ip 与 port,从而实现自动化操作。

技术选型

名称 优点 缺点 接口 一致性算法
zookeeper 1.功能强大,不仅仅只是服务发现 2.提供 watcher 机制能实时获取服务提供者的状态 3.dubbo 等框架支持 1.没有健康检查 2.需在服务中集成 sdk,复杂度高 3.不支持多数据中心 sdk Paxos
consul 1.简单易用,不需要集成 sdk 2.自带健康检查 3.支持多数据中心 4.提供 web 管理界面 1.不能实时获取服务信息的变化通知 http/dns Raft
etcd 1.简单易用,不需要集成 sdk 2.可配置性强 1.没有健康检查 2.需配合第三方工具一起完成服务发现 3.不支持多数据中心 http Raft

consul安装

docker run -d -p 8500:8500 -p 8300:8300 -p 8301:8301 -p 8302:8302 -p 8600:8600/udp  consul consul agent  -dev -client=0.0.0.0

api文档

实现

user-service注册

配置文件增加consul配置

consul:
  host: xx.xx.xx.xx
  port: xxxx

定义consul配置结构体

type ConsulConfig struct {
	Host string `mapstructure:"host"`
	Port int    `mapstructure:"port"`
}

添加全局变量和初始化

	ConsulConfig  *models.ConsulConfig

	ConsulConfig = &models.ConsulConfig{}

添加解析配置文件代码

	err = vp.UnmarshalKey("consul", &global.ConsulConfig)
	if err != nil {
		panic(any(fmt.Sprintf("Read consul config failed:%v", err)))
	}

实现注册函数

func RegisterService(address, name, id string, port int, tags []string) error {
	cfg := api.DefaultConfig()
	cfg.Address = fmt.Sprintf("%s:%d", global.Config.Consul.Host, global.Config.Consul.Port)

	client, err := api.NewClient(cfg)
	if err != nil {
		panic(any(err))
	}
	check := &api.AgentServiceCheck{
		GRPC:                           fmt.Sprintf("%s:%d", global.Config.Service.Host, global.Config.Service.Port),
		GRPCUseTLS:                     false,
		Timeout:                        "5s",
		Interval:                       "5s",
		DeregisterCriticalServiceAfter: "10s",
	}

	registration := api.AgentServiceRegistration{}
	registration.ID = id
	registration.Name = name
	registration.Port = port
	registration.Address = address
	registration.Tags = tags
	registration.Check = check

	err = client.Agent().ServiceRegister(&registration)
	if err != nil {
		panic(any(err))
	}
	return nil
}

主函数调用注册函数

	err = initializer.RegisterService(
		global.Config.Service.Host, global.Config.Service.Name, global.Config.Service.Id,
		global.Config.Service.Port, strings.Split(global.Config.Service.Tags, ","),
	)
	if err != nil {
		zap.S().Fatal("RegisterService failed")
	}

image-20220319180231384

可以看到此时,健康检查是失败的,我们需要注册健康检查到grpc中。首先实现健康检查的接口

type HealthImpl struct{}

func (h *HealthImpl) Check(ctx context.Context, req *grpc_health_v1.HealthCheckRequest) (*grpc_health_v1.HealthCheckResponse, error) {
	return &grpc_health_v1.HealthCheckResponse{
		Status: grpc_health_v1.HealthCheckResponse_SERVING,
	}, nil
}

func (h *HealthImpl) Watch(*grpc_health_v1.HealthCheckRequest, grpc_health_v1.Health_WatchServer) error {
	return nil
}

再在grpc中进行注册

	grpc_health_v1.RegisterHealthServer(grpcServer, &initializer.HealthImpl{})

image-20220319180406140

可以看到,此时已经好了。

user-api服务发现

在配置文件增加consul的配置块

consul:
  host: xx.xx.xx.xx
  port: xxxx

添加consul配置结构体

type ConsulConfig struct {
	Host string `mapstructure:"host"`
	Port int    `mapstructure:"port"`
}

添加全局变量

	ConsulConfig  *models.ConsulConfig
	
	ConsulConfig = &models.ConsulConfig{}

增加解析配置文件

	err = vp.UnmarshalKey("consul", &global.ConsulConfig)
	if err != nil {
		panic(any(fmt.Sprintf("Read consul config faild: %v", err)))
	}

实现根据服务名获取地址信息的方法

func FilterServiceByName(name string) (host string, port int, err error) {
	cfg := api.DefaultConfig()
	cfg.Address = fmt.Sprintf("%s:%d", global.ConsulConfig.Host, global.ConsulConfig.Port)

	client, err := api.NewClient(cfg)
	if err != nil {
		panic(any(err))
	}

	data, err := client.Agent().ServicesWithFilter(fmt.Sprintf(`Service == "%s"`, name))
	if err != nil {
		panic(any(err))
	}
	for _, v := range data {
		host = v.Address
		port = v.Port
		return
	}
	return
}

替换掉注册user-service的地址信息

    host, port, err := utils.FilterServiceByName(global.UserService.Name)
	if err != nil {
		zap.S().Fatalw("FilterServiceByName", "name", global.UserService.Name, "err", err)
		return
	}
	userConn := initialize.InitUserConnection(host, port)

为了方便测试,我把密码登陆中的验证码注释掉了。可以看到成功的连接到了用户服务并获取到了数据

image-20220319182237448

posted @ 2022-04-07 21:17  丶吃鱼的猫  阅读(322)  评论(0编辑  收藏  举报