背景

因为业务需要,需要一个跨语言调用的RPC框架,gRPC是Google发布的基于HTTP 2.0传输层协议承载的高性能开源软件框架,本文使用Golang实现一个简单的gRPC服务端。

环境

环境版本
系统CentOS7
Golang1.19
libprotoc22.0

安装golang和grpc相关的依赖

golangprotocgrpc
go get google.golang.org/grpc
protoc-gen-go
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
protoc-gen-go-grpc
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
protoc-gen-grpc-gateway
go install github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway@latest
protoc-gen-swagger
go install github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger@latest
go install$GOPATH/bin$GOPATH/bin$PATH
echo 'export PATH=$PATH:$GOPATH/bin' >> ~/.bashrc
source ~/.bashrc

创建hello.proto文件

./hellohelloHelloPrintHelloHelloRequeststringnameHelloReplystringmessage
syntax = "proto3";option go_package="./hello;hello";package hello;service Hello {rpc PrintHello (HelloRequest) returns (HelloReply) {}
}message HelloRequest {string name = 1;
}message HelloReply {string message = 1;
}
option go_package = "path;name";
path 表示生成的go文件的存放地址,会自动生成目录
name 表示生成的go文件所属的包名

使用protocol buffer编译器生成golang代码

执行

mkdir -p pb
protoc -I ./ hello.proto --go_out=./pb --go-grpc_out=./pb
hello/hello.pb.gohello/hello_grpc.pb.go

编写server.go实现gRPC服务端

go mod init server
package mainimport ("context""fmt""net""server/pb/hello""google.golang.org/grpc"
)const (port = ":1234"
)type server struct {hello.UnimplementedHelloServer // 必须加的结构体
}func (s *server) PrintHello(ctx context.Context, in *hello.HelloRequest) (*hello.HelloReply, error) {fmt.Printf("客户端消息:: %v", in.Name)return &hello.HelloReply{Message: "Hello " + in.Name}, nil
}func main() {lis, err := net.Listen("tcp", port)if err != nil {fmt.Printf("无法监听端口: %v", err)panic(err)}s := grpc.NewServer()hello.RegisterHelloServer(s, &server{})fmt.Println("服务启动于", port)if err := s.Serve(lis); err != nil {fmt.Printf("无法提供服务: %v", err)panic(err)}
}
go mod tidy
go run server.go

显示如下,则gRPC服务端在1234端口启动

服务启动于 :1234

编写client.go连接gRPC客户端

package mainimport ("context""fmt""server/pb/hello""google.golang.org/grpc"
)func main() {// 建立GRPC连接conn, err := grpc.Dial("localhost:1234", grpc.WithInsecure())if err != nil {fmt.Printf("无法建立连接: %v", err)panic(err)}defer conn.Close()c := hello.NewHelloClient(conn)r, err := c.PrintHello(context.Background(), &hello.HelloRequest{Name: "hello"})if err != nil {fmt.Printf("无法发起gRPC请求: %v", err)panic(err)}fmt.Printf("返回的消息: %s", r.Message)
}
go run client.go

最后显示gRPC服务端返回的消息:

返回的消息: Hello hello