基于GRPC结合Consul实现微服务调用
1 )环境准备
- 基于 go workspace 准备3个包: protos,server, client
- 新建 demo目录,其内部结构如下
├── protos │ ├── go.mod │ └── users │ ├── users.proto │ ├── users.pb.go │ └── users_grpc.pb.go ├── server │ ├── go.mod │ └── main.go ├── client │ ├── go.mod │ └── main.go └── go.work - 这里可以看出是对用户操作的业务场景
- 其实目前无关业务场景,用一个简单的示例来演示grpc和consul的结合
- 这里可以看到,已经初始化了每个包,同时也基于 go work 处理了3个包之前可以调用的关系
- 这里不再过多阐述,参考之前的博文
- 启动 consul, $
consul agent -dev
2 )准备 protos
- 由上面的目录设计可知,需要 users.proto
syntax="proto3"; option go_package="./users"; service Users { rpc AddUser(AddUserReq) returns (AddUserRes); rpc GetUser(GetUserReq) returns (GetUserRes); } message UsersModel { string name = 1; int32 age = 2; } message AddUserReq { UsersModel user = 1; } message AddUserRes { string message = 1; bool success = 2; } message GetUserReq { } message GetUserRes { repeated UsersModel userList =1 ; } - 进入 demo/protos/users 目录生成 users.pb.go,users_grpc.pb.go
- 执行
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative ./users.proto
- 执行
3 )处理 server
-
新建 demo/server/main.go
package main import ( "context" "fmt" "protos/users" "net" "strconv" "google.golang.org/grpc" "github.com/hashicorp/consul/api" ) // 定义通用度变量 var ( host string = "127.0.0.1" port int = 9000 portStr string = strconv.Itoa(port) address = host + ":" + portStr ) type Users struct { users.UnimplementedUsersServer } func (g Users) AddUser(c context.Context, req *users.AddUserReq) (*users.AddUserRes, error) { fmt.Println(req) return &users.AddUserRes{ Success: true, Message: "增加用户成功", }, nil } func (g Users) GetUser(c context.Context, req *users.GetUserReq) (*users.GetUserRes, error) { var tempList []*users.UsersModel for i := 0; i < 10; i++ { tempList = append(tempList, &users.UsersModel{ Name: "商品" + strconv.Itoa(i), Age: int32(i), }) } return &users.GetUserRes{ UserList: tempList, }, nil } func main() { // ----------------------- 1. 注册consul服务 ----------------------- // 1、初始化consul配置 consulConfig := api.DefaultConfig() // consulConfig.Address = "127.0.0.1:8500" // consul服务的默认地址可省略,如果不是本机,需要补充 // 2、获取consul操作对象 consulClient, _ := api.NewClient(consulConfig) // 3、配置注册服务的参数 agentService := api.AgentServiceRegistration { ID: "1", // 不要重复 Tags: []string{"test"}, Name: "UsersService", Port: port, // 和下面 grpc server 的配置相同, 否则就连接不上微服务 Address: host, // 同上 Check: &api.AgentServiceCheck{ TCP: address, Timeout: "5s", Interval: "30s", }, } // 4、注册服务到consul上 consulClient.Agent().ServiceRegister(&agentService) // ----------------------- 2. 注册GRPC ----------------------- // 1、获取Grpc示例 grpcServer := grpc.NewServer() // 2、注册服务 users.RegisterUsersServer(grpcServer, &Users{}) // 3、监听端口 listener, err := net.Listen("tcp", address) if err != nil { fmt.Println(err) } // 4、退出服务的时候关闭监听 defer listener.Close() // 5、启动服务 grpcServer.Serve(listener) } -
主要关注 main 函数中,注册consul服务相关代码
-
重新处理依赖 $
go mod tidy -
运行起来 $
go run main.go -
刷新发现 127.0.0.1:8500 这个 consul 注册中心面板出来了一个新的服务
4 )处理 client
-
新建 demo/client/main.go
package main import ( "fmt" "protos/users" "context" "strconv" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "github.com/hashicorp/consul/api" ) func main() { // ------------------------------- 1. 初始化 consul 客户端 ------------------------------- // 1、初始化 consul 配置 consulConfig := api.DefaultConfig() // consulConfig.Address = "127.0.0.1:8500" // 默认consul服务的地址,如有改变,重新指定 // 2、获取consul操作对象 consulClient, _ := api.NewClient(consulConfig) // ------------------------------- 2. 基于consul解析UserService的address ------------------------------- usersServiceEntry, _, _ := consulClient.Health().Service("UsersService", "test", false, nil) usersServicePtr := usersServiceEntry[0].Service // service 指针对象 userAddress := usersServicePtr.Address + ":" + strconv.Itoa(usersServicePtr.Port) // ------------------------------- 3. 基于GRPC连接和调用 ------------------------------- // 1、建立连接 userGrpcClient, err := grpc.Dial(userAddress, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { fmt.Println(err) } // 2、注册客户端 userClient := users.NewUsersClient(userGrpcClient) // 3. 调用接口1:增加用户 res1, _ := userClient.AddUser(context.Background(), &users.AddUserReq { User: &users.UsersModel { Name: "测试", Age: 20, }, }) fmt.Println(res1) fmt.Println() // 4. 调用接口2:获取数据 res2, _ := userClient.GetUser(context.Background(), &users.GetUserReq{}) fmt.Println(res2.UserList) // ------------------------------- 4. 以上完成了 users 服务的调用,如果需要调用其他服务,仍需重复步骤2,获取其他服务的入口,再次进行步骤3处理 TODO ------------------------------- } -
以上的调用,可以进行适当的封装来满足不同业务的调用,仅供演示
-
当然结合数据库操作封装功能完成闭环调用,不再赘述
-
在 demo/client 下执行 $
go mod tidy -
运行起来,$
go run main.go发现服务端,客户端控制台都打印输出出来了
1136



被折叠的 条评论
为什么被折叠?



