通过gRPC实现跨语言通信
Stitch-Zhang
An iddle programer在项目中,有时候会使用利用多种语言相互配合来完成某项任务,其必离不开跨语言之间的通信,通常为远程过程调用(RPC)或HTTP接口(Restful API)
本文中将介绍如何使用gRPC实现Go与 Python之间的通信
过程调用#
过程调用可分为两类
本地过程调用(LPC,Local Procedure Call)是由
Windows NT内核提供的内部进程间通信方式远程过程调用(Remote Procedure Call) 首次出现于
Unix平台但后续发展迅速,几乎登陆所有操作系统。RPC是一种服务器-客户端(Client/Server)模式,经典实现是一个通过发送请求-接受回应进行信息交互的系统
gRPC#
gRPC 是一个由Google开源的,基于HTTP2.0协议及Protocol Buffer的高性能跨平台统一RPC框架,能够实现跨平台跨语言之间的通信
底层数据传输格式#
- 【默认】Protocol Buffers 一种接口定义语言(Interface Definition Language)
- 【可选】JSON
浅析Protocol Buffers#
在 Protocol Buffers 中,一个最小的数据信息发送单位为:消息(message)。
消息结构类似于结构体,即一个或多个属性的结合体
使用流程🍜#
编写
proto文件使用
protoc将proto文件编译成指定语言的对应的源文件程序引用
info
通常一个proto文件编译输出为两个源文件
如编写一个名为aloha的proto文件,指定Go为输出语言
aloha.pb.go负责对数据序列化/反序列化,获取/设置属性值``aloha_grpc.pb.gogRPC相关服务实现
支持如下语言#
安装gRPC#
本地环境信息#
- Go:
1.16.3 - Python:
3.7.6
目录结构:
Go准备gRPC相关环境#
下载protoc执行文件,放置于环境变量目录中
安装Go的protoc插件
tip
由于网络环境问题,go install 可能会显示超时,请参考配置go module代理
若安装后执行protoc-gen-go显示未找到,请确保go根目录/bin目录位于环境变量中
Python准备gRPC环境#
虚拟环境#
在Python中,默认的包(模块)管理工具
pip安装新的包,会将新安装的包的源文件放置于python根目录/Lib/site-packages下,以便程序使用,但这样通常会导致
- 若多个项目使用某包的指定不同版本,则会造成冲突
- 无法通过
pip freeze有效的输出某个项目的依赖包集合信息
在Python 3.3版本时,内置了虚拟环境工具venv
新建虚拟环境#
此时目录结构为为
当前窗口激活虚拟环境#
| 终端类型 | 命令 |
|---|---|
| cmd | activate.bat |
| bash | source activate |
请在 Scripts目录下执行
此时命令行前应新增标识符 (gRPC_demo)
使用pip安装gRPC#
示例#
需求说明#
我们将定义一个名为Expirement的类型(对象),其有三个属性(成员)
name| 字符串id| 数字skill| 字符串
实现通过一个Name属性来查询其对应的完整信息
定义proto文件#
在proto目录中新建一个名为expirement的proto文件
expirement.proto
编译proto文件#
请确保当前目录位于 proto
Go#
参数解释:
- --go_out 输出的
protocol buffer序列化/反序列化源文件路径 - --go_opt=paths=source_relative
go_out路径输出选项为相对路径 - --go-grpc_out
gRPC相关服务实现的文件路径,通常和 序列化/反序列化源文件放置同一目录 - --go-grpc_opt
grpc_opt路径输出选项为相对路径 <proto文件>
输出的文件#
expirement.pb.go负责定义消息的序列化/发布序列化、属性的值获取/设置expirement_grpc.pb.go实现RPC服务
Python#
参数解释:
- --m grpc_tools.protoc 调用
grpc_tools.protoc功能,依赖于上述中使用pip安装gRPC - -I .
proto文件的输入目录 - --python_out 输出的
protocol buffer序列化/反序列化源文件路径 - --grpc_python_out
gRPC相关服务实现的文件路径 <proto文件>
输出的文件#
expirement_pb2.py负责定义消息的序列化/发布序列化、属性的值获取/设置expirement_pb2_grpc.py实现RPC服务
此时目录结构为为
启用Go Module#
在Go 1.13 后官方推荐使用Go Module 作为包管理。若需要导入本地包,启用Go Module将更加方便。且不再局限于你的项目文件的存放位置,在此之前即Go PATH时,Go项目文件必须存放于$GOPATH/src/
请位于 gRPC_demo/go 目录下执行
实现#
Go为服务端,Python为客户端#
- Go
- Python
运行测试#
- Go
- Python
Python为服务端,Go为客户端#
- Go
- Python
运行测试#
- Go
- Python
结语#
至此我们已经能够实现两个语言互通了,分别使用它们来充当服务端/客户端,实现通过一个name属性来查询其对应的skill和id
参考链接#
https://github.com/grpc/grpc-go/tree/master/examples/helloworld
https://developers.google.cn/protocol-buffers/docs/overview#simple