gRPC框架學習:5、 go+gRPC+proto詳細使用實體
文章目錄
- gRPC框架學習:5、 go+gRPC+proto詳細使用實體
- 1. 前言
- 2. 完成proto檔案
- 3. 下載安裝proto編譯器及go相關插件
- 4. 編譯proto檔案生成go相關檔案
- 5. 使用框架代碼時的包依賴坑點
- 6. 創建服務端
- (1). 代碼
- (2). 可能的錯誤
- 7. 創建客戶端
- 8. 結果
1. 前言
在掌握rpc、gRPC和proto的一些基本概念、可以書寫簡單(看懂)proto檔案、可以編譯proto檔案生成對應語言檔案后(有點類似SOAP協議需要SWDL檔案,proto檔案可以結合json并且proto檔案書寫起來稍微簡單一些),我們結合實體進行快速使用,看下如何序列化反序列化需要傳遞的資料以及如何快速生成rpc服務及如何進行多語言互動,
我們這里以Go語言生成rpc服務,然后使用go客戶端做測驗,理論上還可以使用c++、Java、python等進行測驗,等后面有機會用到的話再單獨出實體分析總結,
其它語言的一些支持需要的可以在這里查看并結合Quick Start的檔案自行做下測驗:https://www.grpc.io/docs/languages
我們這里仿照官方的hello world實體寫一個簡單的rpc服務提供獲取服務版本號的功能,以此總結一下從proto檔案到編譯生成go檔案,到利用生成的go檔案創建服務端程式和客戶端程式這個流程做一下總結,程序中會對注意事項和踩坑點做詳細總結便于下次快速搭建,
2. 完成proto檔案
這個其實也是編程的一部分,proto是一個簡單的語言,利用該語言和我們需要設計的介面寫.proto檔案,
關于proto的語法和規范我們之前已經總結了,這里就不多說了,建議先看這部分對相關概念有了解和學習,
syntax = "proto3";
option go_package = "./;test_grpc";
package test_grpc;
service TestGRPC {
rpc GetVersion (GetVersionRequest) returns (GetVersionResponse);
}
message BaseResponse {
int32 code = 1; // 錯誤碼 0:成功; 其他:參考《錯誤碼統計》
string message = 2; // 錯誤訊息
}
/*
** 版本資訊
*/
message Version {
string software_version = 1; // 軟體版本號
int64 last_compile_time = 2; // 上次編譯時間
}
message GetVersionRequest {
}
message GetVersionResponse {
BaseResponse response = 1;
Version version = 2;
}
3. 下載安裝proto編譯器及go相關插件
其實官方的go插件安裝講的比較籠統,我就著了這個道,通過官方的檔案我們可以知道除了要安裝protoc之外,還需要安裝protoc-gen-go,實際上如果我們需要使用Go生成rpc服務介面的話還需要安裝protoc-gen-go-grpc插件,否則只會生成一個.pb.go,我們在進行rpc服務開發時還需要xx_grpc.pb.go,官方的指南中很容易忽略這一點,
注:官方是將proto和gRPC可能是為了強調proto和gRPC的獨立性,所以只說了protoc-gen-go插件,實際上當結合go+gRPC+proto使用時需要安裝一個軟體,兩個插件:
1、protoc
2、protoc-gen-go-grpc
3、protoc-gen-go
因為rpc的框架不止gRPC,proto也可以和其它rpc框架結合使用,
1.安裝protoc
根據作業系統具體安裝:https://github.com/protocolbuffers/protobuf/tags
2.安裝protoc-gen-go
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
3.安裝protoc-gen-go-rpc
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
4. 編譯proto檔案生成go相關檔案
需要指定兩個插件以及源檔案的位置和生成檔案的位置,可以指定相對路徑(可通過protoc --help獲取幫助):
protoc -I=. --go_out=. --go-grpc_out=. ./version.proto
根據proto檔案會生成兩個檔案,這個是官方例子的檔案樹:
D:\mynotes\go\src\google.golang.org\grpc\examples\helloworld>tree . /F
檔案夾 PATH 串列
卷序列號為 0865-F52B
D:\MYNOTES\GO\SRC\GOOGLE.GOLANG.ORG\GRPC\EXAMPLES\HELLOWORLD
├─greeter_client
│ main.go
│
├─greeter_server
│ main.go
│
└─helloworld
helloworld.pb.go
helloworld.proto
helloworld_grpc.pb.go
這個是我們生成的代碼的檔案:
$ ls
version.pb.go version.proto version_grpc.pb.go
5. 使用框架代碼時的包依賴坑點
生成.pb.go等插件生成的檔案后在使用時需要一些依賴(protobuf相關包及其依賴),但是這些依賴我通過go get的一些全球代理或者七牛的國內代理也沒有獲取成功,最后還是采用老方法,直接通過GitHub上的倉庫clone下載(或者fork到gitee等國內倉后下載,避免某些時候墻的厲害GitHub也無法訪問下載),比如:
git clone https://github.com/golang/net.git src/golang.org/x/net
git clone https://github.com/golang/crypto.git src/golang.org/x/crypto
git clone https://github.com/golang/sys.git src/golang.org/x/sys
git clone https://github.com/golang/text.git src/golang.org/x/text
git clone https://github.com/googleapis/go-genproto.git src/google.golang.org/genproto
其它有需要的話也是類似的處理方式,
6. 創建服務端
(1). 代碼
直接上代碼吧,結合官方的helloworld實體,如果前面編譯proto檔案及依賴安裝沒有問題的話照貓畫虎即可:
package main
import (
"context"
"gitee.com/commanderZY/test_grpc/version"
"google.golang.org/grpc"
"log"
"net"
)
type server struct {
test_grpc.UnimplementedTestGRPCServer
}
func (s *server) GetVersion(ctx context.Context, in *test_grpc.GetVersionRequest) (*test_grpc.GetVersionResponse, error) {
resp := test_grpc.BaseResponse{
Code: 0,
Message: "",
}
ver := test_grpc.Version{
SoftwareVersion: "1.0",
LastCompileTime: 0,
}
verResp := test_grpc.GetVersionResponse{
Response: &resp,
Version: &ver,
}
return &verResp, nil
}
func main() {
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
test_grpc.RegisterTestGRPCServer(s, &server{})
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
(2). 可能的錯誤
無法將 ‘&server{}’ (型別 *server) 用作型別 TestGRPCServer 型別未實作 ‘TestGRPCServer’ ,因為缺少某些方法: mustEmbedUnimplementedTestGRPCServer()
在issue上找到了解決方法:
https://github.com/grpc/grpc-go/issues/3794

即在定義的結構體中嵌入該空方法即可,
7. 創建客戶端
代碼:
package main
import (
"context"
"fmt"
testgrpc "gitee.com/commanderZY/test_grpc/version"
"google.golang.org/grpc"
)
func main() {
conn, err := grpc.Dial(":50051", grpc.WithInsecure())
if err != nil {
fmt.Println("connect server failed,", err)
}
defer conn.Close()
c := testgrpc.NewTestGRPCClient(conn)
r1, err := c.GetVersion(context.Background(), &testgrpc.GetVersionRequest{})
if err != nil {
fmt.Println("can't get version,", err)
return
}
fmt.Println(r1.Version)
}
8. 結果
先編譯運行服務端程式,然后運行客戶端程式,測驗結果如下:

轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/281701.html
標籤:區塊鏈
