gRPC
RPC
RPC(Remote Procedure Call,远程过程调用)是一种计算机通信协议,允许程序像调用本地函数一样调用另一台计算机上的函数或过程。RPC 屏蔽了底层网络通信的细节,使开发者可以专注于业务逻辑开发,而无需关心数据如何在网络上传输。
RPC 的基本原理
- 客户端调用本地代理(Stub)函数,就像调用本地方法一样。
- 代理函数将请求序列化(编码),通过网络发送到远程服务器。
- 服务器端接收请求并反序列化,调用对应的服务端函数。
- 服务器端函数执行后返回结果,服务器将结果序列化并通过网络返回给客户端。
- 客户端代理函数接收并反序列化结果,最终返回给调用者。
RPC 的常见实现
- gRPC:基于 HTTP/2 和 Protocol Buffers,支持多语言。
- Thrift:Apache 提供的高性能跨语言 RPC 框架。
- JSON-RPC / XML-RPC:基于 JSON 或 XML 的轻量级协议。
sequenceDiagram
participant Caller as Caller (Client)
participant Callee as Callee (Server)
Caller->>Callee: Invoke procedure
Callee->>Callee: Receive procedure
Callee->>Callee: Execute procedure
Callee->>Callee: Send result
Callee-->>Caller: Result from procedure execution
Hello World
使用 Go 语言运行一个简单的 gRPC 项目。
-
准备工作:
brew install go protobuf # 安装 Go 和 Protobuf # 安装 protocol 编译器的 Go 语言插件 go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest参见:Protocol Buffer Compiler Installation | Protocol Buffers Documentation
-
克隆示例代码:
git clone -b v1.73.0 --depth 1 https://github.com/grpc/grpc-go cd grpc-go/examples/helloworld -
使用示例代码进行一次远程过程调用:
go run greeter_server/main.go # 启动服务端go run greeter_client/main.go # 使用客户端调用服务端过程
更新 gRPC 服务
-
在
.proto文件中更新服务定义:vim helloworld/helloworld.proto// The greeting service definition. service Greeter { // Sends a greeting rpc SayHello (HelloRequest) returns (HelloReply) {} + // Sends another greeting + rpc SayHelloAgain (HelloRequest) returns (HelloReply) {} } // The request message containing the user's name. message HelloRequest { string name = 1; } // The response message containing the greetings message HelloReply { string message = 1; } -
重新生成 gRPC 代码:
protoc --go_out=. \ --go_opt=paths=source_relative \ --go-grpc_out=. \ --go-grpc_opt=paths=source_relative \ helloworld/helloworld.proto将生成
helloworld/helloworld.pb.go和helloworld/helloworld_grpc.pb.go文件。 -
更新服务端代码:
vim greeter_server/main.gofunc (s *server) SayHelloAgain(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) { return &pb.HelloReply{Message: "Hello again " + in.GetName()}, nil } -
更新客户端代码:
vim greeter_client/main.gofunc main() { // (原有代码) r, err = c.SayHelloAgain(ctx, &pb.HelloRequest{Name: *name}) if err != nil { log.Fatalf("could not greet: %v", err) } log.Printf("Greeting: %s", r.GetMessage()) } -
运行:
go run greeter_server/main.go # 启动服务端go run greeter_client/main.go --name=Alice # 启动客户端

浙公网安备 33010602011771号