使用grpc實現(xiàn)golang后端和python服務間通信
grpc前言
gRPC是Google 開發(fā)的高性能、開源的遠程過程調用(RPC)框架,基于 HTTP/2 協(xié)議進行通信,使用 Protocol Buffers(protobuf)作為接口定義語言,可以看為一種協(xié)議。
grpc可以用于各種不同服務間的通信,屏蔽底層細節(jié)(如編程語言,操作系統(tǒng)等)
由于我的一個go后端(也可以不是go)需要實現(xiàn)神經(jīng)網(wǎng)絡相關的功能,我要調用一個python的服務,于是想到了使用grpc的方式。
初次接觸,將從0介紹到功能實現(xiàn)。
感謝官方的文檔
https://grpc.io/docs/languages/go/quickstart/
主要流程
定義.proto文件:創(chuàng)建一個 .proto 文件,定義圖數(shù)據(jù)和 GCN 結果的消息類型以及服務接口。
生成 gRPC 代碼:使用 Protocol Buffers 編譯器 protoc,根據(jù) .proto 文件生成 Go 和 Python 的 gRPC 代碼。
實現(xiàn) Python 服務器:在 Python 中實現(xiàn) gRPC 服務器,接收來自 Go 客戶端的圖數(shù)據(jù),進行 GCN 處理,并返回處理結果。
實現(xiàn) Go 客戶端:在 Go 中實現(xiàn) gRPC 客戶端,發(fā)送圖數(shù)據(jù)到 Python 服務器,并接收處理結果。
安裝protoc解釋器
grpc是通過pb(protocolbuffer)這個協(xié)議工作的,首先安裝protoc的解釋器,并將其bin文件夾添加到環(huán)境變量。
地址:https://github.com/protocolbuffers/protobuf/releases
下載后解壓到任意文件夾位置,然后將解壓后的bin文件夾添加到環(huán)境變量。
打開cmd輸入protoc有數(shù)據(jù)返回就ok了。
為了在項目中使用protoc的一些指令可以正常工作,還有把bin文件下的protoc.exe文件復制一份到C:\Windows\System32文件夾下。
順便一提,為了proto文件可以在vscode高亮顯示,可以安裝官方的插件:protobuf,作者:pbkit
go端工作
首先安裝go的grpc庫
go get -u google.golang.org/grpc
然后安裝可以將proto文件自動解析為go文件的解釋器:
go install google.golang.org/protobuf/cmd/protoc-gen-go go install google.golang.org/grpc/cmd/protoc-gen-go-grpc
定義proto文件 gcn.proto:
其中go_package是指定生成的文件位置和文件所在包名。“.” 表示文件生成在當前目錄,“;”表示參數(shù)分割,后面的proto是將生成文件放在proto包中。
還有更多可選參數(shù),自行參考官方
go_package:指定生成 Go 代碼時的包路徑,格式為 option go_package = “package_path”;,用于將生成的代碼放置在指定的 Go 包中。
java_package:指定生成 Java 代碼時的包路徑,格式為 option java_package = “package_path”;,用于將生成的代碼放置在指定的 Java 包中。
java_outer_classname:指定生成 Java 代碼時的外部類名,格式為 option java_outer_classname = “ClassName”;,用于指定生成的 Java 類的外部類名。
cc_generic_services:指定是否生成 C++ 通用服務(generic services),格式為 option cc_generic_services = true; 或 option cc_generic_services = false;,默認為
true。
cc_enable_arenas:指定是否啟用 C++ arenas 內存管理,格式為 option cc_enable_arenas = true; 或 option cc_enable_arenas = false;,默認為 false。
optimize_for:指定優(yōu)化選項,可以是 SPEED、CODE_SIZE 或 LITE_RUNTIME,格式為 option optimize_for = SPEED;,默認為 SPEED。
deprecated:指定消息或字段已過時,格式為 option deprecated = true;。
rpc_timeout:指定 gRPC 調用的超時時間,格式為 option rpc_timeout = “10s”;,表示超時時間為 10秒。
gcn.proto協(xié)議文件具體定義為:
syntax = "proto3";
option go_package = ".;proto";
message Node {
string id = 1;
repeated float features = 2;
}
message Edge {
string source_id = 1;
string target_id = 2;
}
message GraphData {
repeated Node nodes = 1;
repeated Edge edges = 2;
}
message GCNResult {
map<string, float> node_scores = 1;
}
service GCNService {
rpc ProcessGraph(GraphData) returns (GCNResult);
}
我這里是用來處理圖數(shù)據(jù)。
接下來生成 gRPC 代碼:
protoc --go_out=. --go_opt=paths=source_relative your_proto_file.proto
protoc --go-grpc_out=. --go-grpc_opt=paths=source_relative your_proto_file.proto
會生成兩個文件gcn.pb.go和gcn_grpc.pb.go
前者生成的文件,包含所有pb協(xié)議的go代碼,將數(shù)據(jù)格式寫為go的結構體形式。包含填充、序列化,檢索請求和響應消息類型。
后者包含客戶端使用中定義的方法,調用的接口類型。以及服務端要實現(xiàn)的接口類型。包含創(chuàng)建客戶端服務和服務端服務的方法。
請注意,無論go后端作為請求grpc的一方(client)還是做出響應的一方(server),這兩個文件都是必須生成的。
使用client := pb.NewXXXXServiceClient(conn)的方式創(chuàng)建客戶端
最后就是完成go端的grpc請求代碼,每次請求都創(chuàng)建一個grpc的連接,請求完畢defer斷開:
func GCN_request() (map[string]float32, error) {
conn, err := grpc.Dial("localhost:9999", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
// Failed to connect to gcnserver(py) by grpc
return nil, err
}
defer conn.Close()
client := pb.NewGCNServiceClient(conn)
// 創(chuàng)建一個實例的圖數(shù)據(jù)
G_example := &pb.GraphData{
Nodes: []*pb.Node{
{Id: "node1", Features: []float32{0.1, 0.2, 0.3}},
{Id: "node2", Features: []float32{0.4, 0.5, 0.6}},
},
Edges: []*pb.Edge{
{SourceId: "node1", TargetId: "node2"},
},
}
// 發(fā)送請求并接收響應
result, err := client.ProcessGraph(context.Background(), G_example)
if err != nil {
// Error calling ProcessGraph
return nil, err
}
return result.NodeScores, err
}
最后的最后別忘了創(chuàng)建一個路由調用這個方法。
python端工作
py同樣安裝grpc相關庫
pip install grpcio pip install grpcio-tools
py的服務端代碼grpc相關的代碼較為簡潔,重點在于數(shù)據(jù)處理。將其服務端口和grpc客戶端的請求端口保持一致。
部分代碼取自官方示例。
import grpc
from concurrent import futures
from proto import gcn_pb2_grpc, gcn_pb2
class GCNServicer(gcn_pb2_grpc.GCNServiceServicer):
def ProcessGraph(self, request, context):
# Process graph data using GCN and return result
# example: return gcn_pb2.GCNResult(node_scores={"node1": 0.5, "node2": 0.8})
def server():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
gcn_pb2_grpc.add_GCNServiceServicer_to_server(GCNServicer(), server)
server.add_insecure_port('[::]:9999')
server.start()
print('gRPC 服務端已開啟,端口為9999...')
server.wait_for_termination()
if __name__ == '__main__':
server()啟動
做好了以上工作就大功告成了,啟動兩個服務即可
go run main.go
python server.py
然后訪問定義的路由地址,如下顯示,nice~
到此這篇關于使用grpc實現(xiàn)golang后端和python服務間通信的文章就介紹到這了,更多相關go python服務間通信內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
使用用Pyspark和GraphX實現(xiàn)解析復雜網(wǎng)絡數(shù)據(jù)
GraphX是Spark提供的圖計算API,它提供了一套強大的工具,這篇文章將詳細為大家介紹如何在Python?/?pyspark環(huán)境中使用graphx進行圖計算,感興趣的可以了解下2024-01-01
解決windows上安裝tensorflow時報錯,“DLL load failed: 找不到指定的模塊”的問題
這篇文章主要介紹了解決windows上安裝tensorflow時報錯,“DLL load failed: 找不到指定的模塊”的問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-05-05
Kwargs傳遞給Python 中的另一個函數(shù)實現(xiàn)方法
Python 列出了可以傳遞給程序中的函數(shù)的兩種類型的參數(shù), 非關鍵字參數(shù)**args和關鍵字參數(shù) **kwargs ,在本文中,我們將討論如何使用關鍵字參數(shù)及如何將關鍵字參數(shù)傳遞給另一個函數(shù),感興趣的朋友跟隨小編一起看看吧2023-08-08
python中CURL 和python requests的相互轉換實現(xiàn)
本文主要介紹了python中CURL 和python requests的相互轉換實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-03-03

