Go語言與gRPC的完美結(jié)合實(shí)戰(zhàn)演練
gRPC 的概念
gRPC 是一個高性能、通用的開源 RPC 框架,是一個由 Google 主導(dǎo)開發(fā)的 RPC 框架。其以 HTTP/2 為基礎(chǔ)通信協(xié)議,支持多種語言,通過 protocol buffers 數(shù)據(jù)格式來實(shí)現(xiàn)服務(wù)之間的調(diào)用。
gRPC 使用 protocol buffers 來實(shí)現(xiàn)服務(wù)定義和數(shù)據(jù)序列化。Protocol buffers 是由 Google 開發(fā)的數(shù)據(jù)描述語言,跨平臺、跨語言支持良好,性能好、版本兼容性高。
gRPC 框架包含了服務(wù)端和客戶端兩部分。服務(wù)端實(shí)現(xiàn) gRPC 服務(wù)接口,客戶端通過 stub 來調(diào)用遠(yuǎn)程服務(wù)。
gRPC 的優(yōu)勢
- 基于 HTTP/2 設(shè)計,性能高,可擴(kuò)展性強(qiáng)
- 支持流式傳輸,低延遲
- 支持跨語言調(diào)用
- 支持雙向流式通信
- 支持服務(wù)發(fā)現(xiàn)及負(fù)載均衡
- Protobuf 格式高效便捷
gRPC 適用場景
- 需要高性能、低延遲的服務(wù)通信
- 要實(shí)現(xiàn)異構(gòu)系統(tǒng)、不同語言間的調(diào)用
- 需要流式數(shù)據(jù)處理的場景
- 微服務(wù)架構(gòu)下服務(wù)間的通信
gRPC 架構(gòu)
gRPC 基于 HTTP/2 協(xié)議設(shè)計,采用 Protocol Buffers 機(jī)制序列化結(jié)構(gòu)化數(shù)據(jù),主要包含以下組件:
- Stub:客戶端調(diào)用 gRPC 服務(wù)的接口
- gRPC Server:實(shí)現(xiàn) gRPC 服務(wù)邏輯的服務(wù)器
- Channel:抽象連接,實(shí)現(xiàn) Socket 級別連接及 RPC 交互
- Protocol Buffers:服務(wù)接口描述語言和數(shù)據(jù)序列化機(jī)制
在服務(wù)器端通過 Protobuf 接口實(shí)現(xiàn)服務(wù),客戶端通過 Stub 完成遠(yuǎn)程調(diào)用。
gRPC 通信流程
gRPC 通信流程主要包括:
- 客戶端調(diào)用 Stub 接口
- Stub 序列化參數(shù)為 Protobuf 數(shù)據(jù)
- 數(shù)據(jù)通過 HTTP/2 協(xié)議發(fā)送給服務(wù)器
- 服務(wù)器獲取請求數(shù)據(jù)并反序列化
- 服務(wù)器處理請求并序列化返回結(jié)果
- 通過 HTTP/2 返回序列化后的數(shù)據(jù)
- 客戶端獲取響應(yīng)數(shù)據(jù)并反序列化
Protobuf 數(shù)據(jù)格式
Protocol Buffer (Protobuf) 是谷歌推出的一種輕便高效的數(shù)據(jù)序列化格式,主要用于促進(jìn)數(shù)據(jù)在網(wǎng)絡(luò)間高效傳輸。
Protobuf 的數(shù)據(jù)格式主要特點(diǎn):
- 跨平臺、語言中立
- 版本兼容
- 體積小,serialize 后數(shù)據(jù)大小只有 XML 的 1/10 到 1/3
- 序列化/反序列化速度快
Protobuf 通過.proto 文件定義數(shù)據(jù)結(jié)構(gòu),然后使用 protoc 編譯器生成各目標(biāo)語言的數(shù)據(jù)訪問類。
gRPC 方法的定義
在 .proto 文件中可以定義服務(wù)接口和方法
service HelloService { rpc SayHello (HelloRequest) returns (HelloResponse); }
方法可以指定請求參數(shù)消息類型和返回值消息類型。
gRPC 服務(wù)的實(shí)現(xiàn)
Go 語言中實(shí)現(xiàn) gRPC 服務(wù)的步驟:
- 定義服務(wù)實(shí)現(xiàn)結(jié)構(gòu)體
- 在結(jié)構(gòu)體中實(shí)現(xiàn)服務(wù)接口方法
- 創(chuàng)建 gRPC 服務(wù)器
- 用服務(wù)器注冊服務(wù)
示例:
type HelloServiceImpl struct{} func (p *HelloServiceImpl) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloResponse, error) { // 方法實(shí)現(xiàn) } func main() { server := grpc.NewServer() pb.RegisterMessageServiceServer(server, &HelloServiceImpl{}) server.Serve(lis) }
gRPC 客戶端調(diào)用
Go 語言 gRPC 客戶端調(diào)用主要分為三步:
- 建立到 gRPC 服務(wù)器的連接
- 通過連接新建客戶端 stub 實(shí)例
- 使用 stub 調(diào)用遠(yuǎn)程服務(wù)方法
示例:
conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure()) client := pb.NewHelloServiceClient(conn) resp, err := client.SayHello(ctx, req)
gRPC 高級用法
1. 流式 RPC
gRPC 支持流式 RPC 調(diào)用,分為四種類型:
- 單向流式:客戶端流式,只有請求是流
- 單向流式:服務(wù)器流式,只有響應(yīng)是流
- 雙向流式:客戶端和服務(wù)器端都可以是流
在 proto 文件中使用 stream 關(guān)鍵字定義:
rpc ClientStream(stream HelloRequest) returns (HelloResponse); rpc ServerStream(HelloRequest) returns (stream HelloResponse); rpc Bidirectional(stream HelloRequest) returns (stream HelloResponse);
2. 證書和認(rèn)證
gRPC 支持 SSL/TLS 安全傳輸及各種身份認(rèn)證方式:
- SSL/TLS 傳輸級安全保障
- 支持基于證書、Token 和 AWS IAM 等認(rèn)證手段
3. 錯誤處理
gRPC 框架定義了狀態(tài)碼和錯誤模型,客戶端可以根據(jù)狀態(tài)碼判斷 RPC 調(diào)用是否成功:
- OK:調(diào)用成功
- Cancelled:調(diào)用被取消
- Unknown:未知錯誤
- InvalidArgument:參數(shù)無效
- DeadlineExceeded:超時錯誤等
4. 超時和取消
gRPC 支持請求級別的超時控制,通過 Context 指定超時時間,還可以通過 Context 取消正在執(zhí)行的 RPC。
5. gRPC 攔截器
gRPC 支持在服務(wù)器端和客戶端使用攔截器(Interceptor)攔截請求:
- 客戶端攔截器:攔截出站請求及響應(yīng)
- 服務(wù)端攔截器:攔截入站請求及響應(yīng)
主要用于日志記錄、監(jiān)控等功能。
6. gRPC 元數(shù)據(jù)
gRPC 通過自定義元數(shù)據(jù)提供請求上下文等附加信息??梢栽谡埱蠛晚憫?yīng)中設(shè)置和獲取元數(shù)據(jù)。
7. gRPC 路由
gRPC 支持按服務(wù)方法特征進(jìn)行請求路由,路由選擇不同的后端服務(wù)。主要通過 gRPC intestine 實(shí)現(xiàn)。
8. 和 HTTP/2 的對比
功能點(diǎn) | gRPC | HTTP/2 |
---|---|---|
連接方式 | persistent connection | persistent connection |
數(shù)據(jù)格式 | Protobuf | JSON |
數(shù)據(jù)壓縮 | 支持 | 不支持 |
流式傳輸 | 支持 | 不支持 |
IDL 接口定義 | 支持 | 不支持 |
gRPC 實(shí)踐案例
1. 簡單 RPC 服務(wù)端與客戶端
簡單的 gRPC Server 端和 Client 端示例,演示基本的 RPC 服務(wù)開發(fā)、注冊和調(diào)用流程。
// server type Server struct{} func (s *Server) SayHello(ctx context.Context, in *pb.StringRequest) (*pb.StringReply, error) { return &pb.StringReply{Value: "Hello " + in.Value}, nil } func main() { grpcServer := grpc.NewServer() pb.RegisterMessageServiceServer(grpcServer, &Server{}) grpcServer.Serve(lis) } // client conn, _ := grpc.Dial("localhost:1234", grpc.WithInsecure()) client := pb.NewStringServiceClient(conn) reply, _ := client.SayHello(context.Background(), &pb.StringRequest{Value: "world"}) fmt.Println(reply.Value)
2. 帶參數(shù)驗(yàn)證的 RPC 服務(wù)
示例在 gRPC 服務(wù)中實(shí)現(xiàn)參數(shù)校驗(yàn)邏輯,如果參數(shù)名稱不符合規(guī)范,將返回錯誤。
// server type Server struct{} func (s *Server) SayHello(ctx context.Context, in *pb.StringRequest) (*pb.StringReply, error) { if ok := validate(in.Value); !ok { return nil, status.Error(codes.InvalidArgument, "Invalid parameter") } return &pb.StringReply{Value: "Hello " + in.Value}, nil } // client r, err := client.SayHello(context.Background(), &pb.StringRequest{Value: "World!"}) if err != nil { //錯誤處理 }
通過狀態(tài)碼和錯誤信息,客戶端可以明確判斷是什么原因?qū)е碌恼{(diào)用異常。
3. 客戶端、服務(wù)端流 RPC
示例實(shí)現(xiàn)了客戶端流式 RPC 和服務(wù)器流式 RPC??蛻舳丝梢酝ㄟ^流方式連續(xù)發(fā)送多個請求,服務(wù)器端可以返回流式的響應(yīng)。
// server type Server struct { } func (s *Server) ClientStream (stream pb.StringService_ClientStreamServer) error { for { in, err := stream.Recv() // 處理 stream.SendAndClose(&pb.StringReply{}) } } // client stream, _ := client.ClientStream(context.Background()) for { stream.Send(&pb.StringRequest{}) } reply, _ := stream.CloseAndRecv()
4. 雙向流 RPC
下面演示了如何使用 gRPC 完成雙向流 RPC 的編碼實(shí)現(xiàn)??蛻舳撕头?wù)器端都可以獨(dú)立地通過流發(fā)送多個請求或響應(yīng)。
// server type Server struct{} func (s *Server) Bidirectional( stream pb.StringService_BidirectionalServer) error { for { in, err := stream.Recv() if err != io.EOF { // 處理請求 stream.Send(&pb.StringReply{}) } } } // client stream, _ := client.Bidirectional(context.Background()) go func() { for { stream.Send(&pb.StringRequest{}) } }() for { reply, err := stream.Recv() if err != nil { break } }
總結(jié)
通過實(shí)踐表明,Go 語言結(jié)合 gRPC 框架可以方便高效地實(shí)現(xiàn)各類 RPC 服務(wù)。gRPC 優(yōu)化了網(wǎng)絡(luò)資源利用效率,支持復(fù)雜數(shù)據(jù)交互模式,整體提高了分布式服務(wù)架構(gòu)的性能。
gRPC 的優(yōu)點(diǎn)包括高效、跨平臺、流式傳輸?shù)?。但也存在需要?yīng)用 HTTP/2 特性的學(xué)習(xí)成本,以及被限制在 Protobuf 生態(tài)內(nèi)等問題。
隨著云原生技術(shù)體系的逐步完善, gRPC 在微服務(wù)和 Service Mesh 體系中的地位日益突出,它的重要性會持續(xù)提升。預(yù)計 gRPC 會越來越多地用于云原生基礎(chǔ)設(shè)施的打造。
以上就是Go語言與gRPC的完美結(jié)合實(shí)戰(zhàn)演練的詳細(xì)內(nèi)容,更多關(guān)于Go語言gRPC的資料請關(guān)注腳本之家其它相關(guān)文章!
- golang通用的grpc?http基礎(chǔ)開發(fā)框架使用快速入門
- Go創(chuàng)建Grpc鏈接池實(shí)現(xiàn)過程詳解
- go?doudou開發(fā)gRPC服務(wù)快速上手實(shí)現(xiàn)詳解
- Golang?gRPC?HTTP協(xié)議轉(zhuǎn)換示例
- Go Grpc Gateway兼容HTTP協(xié)議文檔自動生成網(wǎng)關(guān)
- Go?gRPC進(jìn)階教程gRPC轉(zhuǎn)換HTTP
- Go?gRPC服務(wù)proto數(shù)據(jù)驗(yàn)證進(jìn)階教程
- Go?gRPC服務(wù)進(jìn)階middleware使用教程
- Go?gRPC進(jìn)階教程服務(wù)超時設(shè)置
相關(guān)文章
教你用go語言實(shí)現(xiàn)比特幣交易功能(Transaction)
每一筆比特幣交易都會創(chuàng)造輸出,輸出都會被區(qū)塊鏈記錄下來。給某個人發(fā)送比特幣,實(shí)際上意味著創(chuàng)造新的 UTXO 并注冊到那個人的地址,可以為他所用,今天通過本文給大家分享go語言實(shí)現(xiàn)比特幣交易功能,一起看看吧2021-05-05Go語言數(shù)據(jù)結(jié)構(gòu)之插入排序示例詳解
這篇文章主要為大家介紹了Go語言數(shù)據(jù)結(jié)構(gòu)之插入排序示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08golang(gin)的全局統(tǒng)一異常處理方式,并統(tǒng)一返回json
這篇文章主要介紹了golang(gin)的全局統(tǒng)一異常處理方式,并統(tǒng)一返回json,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01