使用grpc在go后端和python服务间通信
grpc前言
gRPC是Google 开发的高性能、开源的远程过程调用(RPC)框架, 基于 HTTP/2 协议进行通信,使用 Protocol Buffers(protobuf)作为接口定义语言,可以看为一种协议。 grpc可以用于各种不同服务间的通信,屏蔽底层细节(如编程语言,操作系统等)
由于我的一个go后端(也可以不是go)需要实现神经网络相关的功能,我要调用一个python的服务,于是想到了使用grpc的方式。
初次接触,将从0介绍到功能实现。
感谢官方的文档
主要流程
- 定义.proto文件:创建一个 .proto 文件,定义图数据和 GCN 结果的消息类型以及服务接口。
- 生成 gRPC 代码:使用 Protocol Buffers 编译器 protoc,根据 .proto 文件生成 Go 和 Python 的 gRPC 代码。
- 实现 Python 服务器:在 Python 中实现 gRPC 服务器,接收来自 Go 客户端的图数据,进行 GCN 处理,并返回处理结果。
- 实现 Go 客户端:在 Go 中实现 gRPC 客户端,发送图数据到 Python 服务器,并接收处理结果。
安装protoc解释器
grpc是通过pb(protocolbuffer)这个协议工作的,首先安装protoc的解释器,并将其bin文件夹添加到环境变量。 地址:https://github.com/protocolbuffers/protobuf/releases 下载后解压到任意文件夹位置,然后将解压后的bin文件夹添加到环境变量。
打开cmd输入 protoc有数据返回就ok了。
为了在项目中使用protoc的一些指令可以正常工作,还有把bin文件下的 protoc.exe文件复制一份到 C:\Windows\System32文件夹下。
顺便一提,为了proto文件可以在vscode高亮显示,可以安装官方的插件:protobuf,作者:pbkit
go端工作
首先安装go的grpc库
然后安装可以将proto文件自动解析为go文件的解释器:
定义proto文件 gcn.proto:
其中go_package是指定生成的文件位置和文件所在包名。“.” 表示文件生成在当前目录,“;”表示参数分割,后面的proto是将生成文件放在proto包中。
还有更多可选参数,自行参考官方
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:指定优化选项,可以是 SPEED、CODE_SIZE 或 LITE_RUNTIME,格式为 option optimize_for = SPEED;,默认为 SPEED。
deprecated:指定消息或字段已过时,格式为 option deprecated = true;。
rpc_timeout:指定 gRPC 调用的超时时间,格式为 option rpc_timeout = “10s”;,表示超时时间为 10 秒。
gcn.proto协议文件具体定义为:
我这里是用来处理图数据。
接下来生成 gRPC 代码:
会生成两个文件 gcn.pb.go和 gcn_grpc.pb.go
- 前者生成的文件,包含所有pb协议的go代码,将数据格式写为go的结构体形式。包含填充、序列化,检索请求和响应消息类型。
- 后者包含客户端使用中定义的方法,调用的接口类型。以及服务端要实现的接口类型。包含创建客户端服务和服务端服务的方法。
请注意,无论go后端作为请求grpc的一方(client)还是做出响应的一方(server),这两个文件都是必须生成的。
使用
client := pb.NewXXXXServiceClient(conn)的方式创建客户端
最后就是完成go端的grpc请求代码,每次请求都创建一个grpc的连接,请求完毕defer断开:
最后的最后别忘了创建一个路由调用这个方法。
python端工作
py同样安装grpc相关库
生成grpc文件
终端cd到proto文件目录下,执行:
py的服务端代码grpc相关的代码较为简洁,重点在于数据处理。将其服务端口和grpc客户端的请求端口保持一致。 部分代码取自官方示例。
启动
做好了以上工作就大功告成了,启动两个服务即可
go run main.go
python server.py
然后访问定义的路由地址,如下显示,nice~
