Prerequisites(先決條件)
- Go
Go的三個最新主要版本之一 - Protocol buffer 編譯器,protoc,version3
http://www.lxweimin.com/p/5324b412f1de - protocol 編譯器的 Go 插件:
http://www.lxweimin.com/p/5324b412f1de
獲取示例代碼
- 下載實例代碼
$ git clone -b v1.46.0 --depth 1 https://github.com/grpc/grpc-go
- 切換代碼目錄
$ cd grpc-go/examples/helloworld
運行示例
在 examples/helloworld 目錄下:
- 編譯和執行服務端代碼
$ go run greeter_server/main.go
- 在另外一個終端中,編譯和執行客戶端代碼,會看到客戶端輸出:
$ go run greeter_client/main.go Greeting: Hello world
更新 gRPC 服務
在本節中,將使用額外的 server 方法更新應用程序。gRPC服務是使用 protocol buffers 定義的。
現在,只需要知道服務器和客戶端存根都有一個 SayHello()RPC方法,該方法從客戶端獲取一個 HelloRequest 參數,并從服務器返回一個 HelloReply,該方法的定義如下:
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
打開 helloworld/helloworld.proto,添加一個新的方法 SayHelloAgain()
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
重新生成 gRPC 代碼
在可以使用新的服務方法之前,需要重新編譯更新后的 .proto 文件。
在 examples/helloworld 目錄下,運行下面的命令:
$ protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
helloworld/helloworld.proto
paths:用于指定生成文件的路徑的結構,有兩個值:
1. paths=import 相對于導入路徑, 默認值
2. paths=source_relative 相對于輸入文件,即proto文件的路徑
重新生成的 helloworld/helloworld.pb.go 和 helloworld/helloworld_grpc.pb.go 文件中包含:
- xxx.pb.go
它包含用于填充、序列化和檢索 請求和響應消息類型 的所有protocol buffer 代碼。 - xxx_grpc.pb.go
客戶端使用的 服務中定義的方法調用的接口類型(或存根)。
服務器要實現的接口類型。
更新并運行應用程序
雖然已經生成了客戶端、服務端代碼,但是任然需要示例程序中 實現和調用 新的方法。
- 更新 服務端
打開 greeter_server/main.go 添加下面的函數:func (s *server) SayHelloAgain (ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) { retrn &pb.HelloReply{Message: "Hello again " + in.GetName()}, nil }
- 更新客戶端
打開 greeter_client/main.go 在 main() 函數體的最下方添加下面代碼:r, err = c.SayHelloAgain(ctx, &pb.HelloRequest{Name: name}) if err != nil { log.Fatalf("could not greet : %v", err) } log.Printf("Greetine : %s", r.GetMessage())
- 運行
# 運行 server go run greeter_server/main.go # 運行 client go run greeter_client/main.go Alice # client 輸出 2021/05/15 23:55:08 Greeting: Hello Alice 2021/05/15 23:55:08 Greeting: Hello again Alice
總結
- gRPC基本使用流程
在 .proto 文件中定義 service、message
通過 protocol buffer 編譯器生成代碼
-
創建服務端
3.1 實現 servic 中定義的接口
gRPC 允許你定義四種類型的服務方法3.2 啟動一個gRPC 服務,監聽客戶端請求
一旦你實現了所有的方法,我們需要啟動一個 gRPC 服務,目的是客戶端能夠使用我們的服務。
如何構建并啟動一個服務:
3.2.1 指定用于 監聽客戶端請求的端口
lis, err := net.Listen(...)3.2.2 創建一個 gRPC 服務實例
grpcServer := grpc.NewServer(...)3.2.3 在 gRPC服務器上注冊我們的服務實現
pb.RegisterRouterGuideServer(...)3.2.4 在服務器上使用 端口詳細信息 調用Serve() 方法,以執行阻塞等待,直到進程被終止 或 調用 Stop()
grpcServer.Serve(...)lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", *port)) if err != nil { log.Fatalf("failed to listen: %v", err) } var opts []grpc.ServerOption ... grpcServer := grpc.NewServer(opts...) pb.RegisterRouteGuideServer(grpcServer, newServer()) grpcServer.Serve(lis)
創建客戶端
-
創建一個stub
要調用服務方法,我們首先需要創建一個gRPC通道來與服務器通信。我們通過將服務器地址和端口號傳遞給 grpc.Dial() 來創建它,如下所示:var opts []grpc.DialOption ... conn, err := grpc.Dial(*serverAddr, opts...) if err != nil { ... } defer conn.Close()
可以使用 DialOptions 在 grpc.Dial 中設置身份驗證憑據(例如,TLS、GCE憑據或JWT憑據),當服務需要這些憑據時可以使用它們。
一旦 gRPC通道 設置好,我們就需要一個客戶端存根來執行RPC。我們使用從 .proto文件 生成的 pb包 提供的 NewRouteGuideClient方法 獲得它。
client := pb.NewRouteGuideClient(conn)
調用服務方法
gRPC允許定義四種類型的服務方法執行客戶端、服務端應用程序