基于 proto 的 GRPC 实现微服务调用
1 )环境准备
- 新建 demo 项目,并初始化 $
go mod init demo - 在 demo 项目中,分别创建三个包: protos, server, client 并用 go mod 初始化
- $
mkdir protos server client - $
cd protos && go mod init protos - $
cd ../server && go mod init server - $
cd ../client && go mod init client
- $
- 基于 workspace 处理三个包的关联
- $
go work init protos server client - 关于 workspace 的处理,参考:https://blog.youkuaiyun.com/Tyro_java/article/details/135430134
- $
- 新建 demo/protos/greeter.proto
syntax = "proto3"; option go_package="./greeter"; service Greeter { rpc SayHello(HelloReq) returns (HelloRes); } message HelloReq { string name=1; } message HelloRes { string message=1; } - 新建 demo/protos/greeter 目录
- 在 demo/protos 下执行 $
protoc --go_out=./greeter --go_opt=paths=source_relative --go-grpc_out=./greeter --go-grpc_opt=paths=source_relative ./greeter.proto - 这时候生成 demo/protos/greeter包,里面就是
greeter_grpc.pb.go和greeter.pb.go
2 )创建服务端程序
-
新建 demo/server/main.go
package main import ( "context" "fmt" "protos/greeter" "net" "google.golang.org/grpc" ) // 1、定义远程调用的结构体和方法 我们这个结构体需要实现 GreeterServer 的接口 type Hello struct{ // 嵌入UnimplementedGreeterServer来提供默认实现 greeter.UnimplementedGreeterServer } func (this Hello) SayHello(c context.Context, req *greeter.HelloReq) (*greeter.HelloRes, error) { fmt.Println(req) return &greeter.HelloRes{ Message: "回复:你好" + req.Name, }, nil } func main() { // 1. 初始一个 grpc 对象 grpcServer := grpc.NewServer() // 2. 注册服务 greeter.RegisterGreeterServer(grpcServer, &Hello{}) // 3. 设置监听, 指定 IP、port listener, err := net.Listen("tcp", "127.0.0.1:8080") if err != nil { fmt.Println(err) } // 4. 退出关闭监听 defer listener.Close() // 5. 启动服务 grpcServer.Serve(listener) } -
把它运行起来
3 )创建客户端程序
-
新建 demo/client/main.go
package main import ( "fmt" "protos/greeter" "context" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) func main() { // 1、连接服务器 // credentials.NewClientTLSFromFile :从输入的证书文件中为客户端构造TLS凭证 // grpc.WithTransportCredentials :配置连接级别的安全凭证(例如,TLS/SSL),返回一个 DialOption,用于连接服务 grpcClient, err := grpc.Dial("127.0.0.1:8080", grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { fmt.Println(err) } // 2、注册客户端 client := greeter.NewGreeterClient(grpcClient) res, _ := client.SayHello(context.Background(), &greeter.HelloReq{ Name: "张三", }) // fmt.Printf("%#v\r\n", res) fmt.Println(res.Message) } -
运行起来这个客户端,即可看到客户端打印出来的服务端回复信息,同时服务端自身也打印出来了
应用场景
1 )概述
- 这里模拟一些常用的业务场景, 比如添加用户和获取用户列表这两项功能接口
- 参考上述环境准备,分别创建proto文件,服务端和客户端
2 )proto 文件
-
创建 demo/protos/users/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 ; } -
进入 protos/users 目录下
- 执行 $
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative ./users.proto
- 执行 $
-
此时生成了 protos/users/users.pb.go, protos/users/users_grpc.pb.go
-
这里的命令和上面环境搭建里的不同,就是把 一个服务的3个文件放在一个包里
3 )服务端
-
创建 demo/server/main.go
package main import ( "context" "fmt" "protos/users" "net" "strconv" "google.golang.org/grpc" ) 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、获取Grpc示例 grpcServer := grpc.NewServer() // 2、注册服务 users.RegisterUsersServer(grpcServer, &Users{}) // 3、监听端口 listener, err := net.Listen("tcp", "127.0.0.1:9000") if err != nil { fmt.Println(err) } // 4、退出服务的时候关闭监听 defer listener.Close() // 5、启动服务 grpcServer.Serve(listener) } -
这里在server包中执行 $
go mod tidy -
之后运行起来 $
go run main.go
4 ) 客户端
- 创建 demo/client/main.go
package main import ( "protos/users" "context" "fmt" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) func main() { // 1、建立连接 grpcClient, err := grpc.Dial("127.0.0.1:9000", grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { fmt.Println(err) } // 2、注册客户端 client := users.NewUsersClient(grpcClient) // 3. 调用接口1:增加用户 res1, _ := client.AddUser(context.Background(), &users.AddUserReq { User: &users.UsersModel { Name: "测试", Age: 20, }, }) fmt.Println(res1) fmt.Println() // 4. 调用接口2:获取数据 res2, _ := client.GetUser(context.Background(), &users.GetUserReq{}) fmt.Println(res2.UserList) } -
- 这里在server包中执行 $
go mod tidy
- 这里在server包中执行 $
- 之后运行起来 $
go run main.go - 可以看到服务端和客户端的控制台上都打印了出来
- 由此可见,再多一些功能封装和集合数据库就是一个基础的微服务调用模式
1248



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



