Go Micro
服务注册与服务发现
服务发现和服务注册是分布式系统中的两个关键概念,他们是构建微服务架构中不可或缺的部分。
- 服务注册
- 服务注册指的是将服务的元数据(例如服务名称,主机名,端口号等)注册到注册中心(例如Zookeeper、Consul、Etcd等)中,以便其它服务或客户端可以发现和调用该服务在服务注册期间,服务提供者将自己的元数据注册到注册中心,以表明它的可用性和位置,服务注册通常是由服务提供者完成。
- 服务发现
- 服务发现是指从注册中心中查找和获取服务的元数据,并使用这些信息来构建服务调用,在服务发现期间,服务消费者通过查询注册中心获取服务提供者的信息,并且采用负载均衡算法选择其中一个服务提供者进行调用,服务发现通常是由服务消费者完成的
服务注册和服务发现的实现通常会使用一些开源的服务发现和注册工具,例如Consul、ZooKeeper、Etcd等,这些工具提供了一个中心化的服务注册表和查询机制,可以让服务提供者和服务消费者通过一种简单、灵活的方式进行服务管理和调用,同时,这些工具还支持服务故障检测和恢复、负载均衡、安全性能等功能,可以提高服务的可靠性和可用性
Consul统筹管理与RPC通信
我们可以在服务与服务之间建立 RPC通信以达到更高的传输效率,但是Consul与服务之间并不是使用RPC互通,他是要用自己的客户端的,我们访问Consul是为了 拿到节点对应的信息,然后进行调用,此时我们就可以建立RPC通信了
具体流程:
- 服务提供者启动时将自己的元数据信息注册到Consul中,包括服务器名称、IP地址、端口号等信息
- 服务消费者在启动时连接到zookeeper,查询目标服务的元服务信息,包括服务名称、IP地址、端口号等信息
- 服务消费者通过RPC框架建立与服务提供者的连接,建立通信通道,向服务提供者发送请求
- 服务提供者收到请求以后,通过RPC框架解析请求,执行相应的业务逻辑,并将结果返回给服务消费者
- 服务消费者接收到服务提供者返回的结果,通过RPC框架解析数据,并且进行相应的处理和展示
注意 RPC通信使用的是Protocol Buffers作为接口定义语言,所以说需要先导入protoc相关的东西
首先要下载protoc 配置好环境变量以后
然后需要
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
这样我们就可以使用命令来进行编写pb文件了
protoc --go_out=路径 输入文件路径
我们可以编写一个bat脚本来进行这个操作 省下CD的步骤
编写好对应的文件以后,我们就可以利用生成的文件来进行RPC的通信
s selector.Selector
myClient := myhttp.NewClient(
client.Selector(s)
client.ContextType("application/json"),
)
req := myClient.NewRequest("服务名","/v1/prods",[protoc方法sheng'ch])
myClient.Call(context.BackGround(),req,&rsp)
使用RPC通信建立服务端
首先我们要使用Protoc建立基本格式
protoc --micro_out=. --go_out=. *.proto
基本protoc文件格式:
syntax = "proto3";
package Proto;
option go_package = "./;MyProto"; //这一行是必要的 不然的话它不能使用micro的编译
message ProdModel{
int32 ProdID =1;
string ProdName = 2;
}
message ProdRequest{
int32 size=1;
}
message ProdListResponse{
repeated ProdModel data=1;
}
service ProdService{
rpc GetProdsList(ProdRequest) returns(ProdListResponse);
}
- synatx 指使用的编译语法是proto几
- option go_package 指定导入文件包
- message 就是常规实体类
- repeated 指的是类似于切片类型的数据
- service 这里 就是添加了一个RPC的服务
- 这里就指定了这个GetProdsList方法 可以用作数据交互 我们把这个方法注册到RPC 服务端去
建立服务端
service := micro.NewService(
micro.Name("prodservice"),
micro.Address(":8081"),
micro.Registry(consul.NewRegistry(registry.Addrs("localhost:8500"))),
)
service.Init() //进行服务的初始化 这里主要是设置超时时间什么的
MyProto.RegistryProServiceHandler(service.Server(),&MyService.ProdService{}) //这里的ProdService是一个空结构体,绑定了对应的方法,可以 //直接传递进去注册到Server中
service.Run() //运行这个服务 这样他就挂在Consul中了
- ProdService中实现的方法代码
func (*ProdService) GetProdsList(context context.Context, in *MyProto.ProdRequest, rsp *MyProto.ProdListResponse) error {
fmt.Println("lalalala")
models := make([]*MyProto.ProdModel, 0)
var i int32
for i = 0; i < in.Size; i++ {
models = append(models, NewProdModel(100+i, "prodname"))
}
rsp.Data = models
return nil
}
- context 上下文对象,这里基本不需要传递什么,传参的时候使用context.BackGround()就可以了
- 然后这里就是他给你生成好的请求体,这里面可以放置对应的参数
- rsp就是响应体,要给响应体添加数据 这里直接对指针做操作就可以了
建立客户端
//首先建立一个客户端服务
myProdsService := micro.NewService(
micro.Name("prodsService.Client")
micro.Registry(consul.NewRegistry(registry.Addrs("localhost:8500"))) //很重要 一定要告诉客户端你的服务中心是什么
)
//然后使用protoc生成的NewService方法建立一个服务,这里要把客户端写入进去
prodsService := MyProto.NewProdsService("prodservice",myProdsService.Client())
//Gin Web逻辑
r := gin.Default()
r.GER("/test",func(contextGin *gin.Context){
var prodReq MyProto.ProdRequest //proto生成的请求结构体 要给他配置参数的
prodReq.Size = 3
contextGin.Bind(prodReq)
list , err := prodsService.GetProdsList(context.Background(),&prodReq) //这里传递上下文对象,传递一个请求结构体
//忽略错误处理
//list就是我们想要的响应数据了 他会自己调用Call方法进行RPC协议通信
contextGin.JSON(200, gin.H{"data": list.Data})
})
这样 当我们访问Gin的web服务的时候,就能通过RPC调用其它的微服务,我们也可以将Gin服务注册到Consul中进行监控 实现一个微服务架构