grpc 专题介绍篇四:grpc 跨语言环境通信
grpc 跨不同语言服务之间互相通信的示例

前面已经介绍了 grpc 在 js 环境下的使用,本身 grpc 是一个语言中立的跨服务通信协议,所以本文再来介绍下其他语言下的使用。本文以最简单的 python 环境下的使用为例,同时也涵盖了对于 protobuf 定义进行预编译的说明,预编译的实现方式本身在大部分有静态检查的语言环境下使用是比较常见的方式。

python 请求 grpc 示例

此部分仅演示使用 python 客户端发送 grpc 请求操作的示例,直接使用先前实现的 ts 服务端程序进行操作应答,python 服务端处理其实是类似的。

  • Proto 定义

因为是直接用的同一套 grpc 操作,直接复用先前的 proto 文件即可。

与 js 环境不同的是,由于语言环境的静态检查需要,在 python/java/.net 等大部分语言环境下使用 grpc,需要将 proto 文件预处理解析成对应的代码模块才能调用,而不支持在运行状态加载 proto 文件动态生成配置的行为。

其实 js 环境下的 grpc 模块本身也支持静态预编译的 proto 模块调用,不过在先前的示例中为了简单处理采用了动态加载的方案。

在调用 protobuf 定义的方法和参数结构前,可以采用如下的方式使用 grpc_tools 工具包中的 protoc 来将 proto 文件预编译成代码文件。例如这里的 worker.proto 就会对应生成 worker_pb2_grpc.py 与 worker_pb2.py 两个文件,分别对应了 grpc service 方法的封装与参数结构的封装。

python -m grpc_tools.protoc \
    --proto_path=./resources/proto \
    --python_out=./lib/grpc \
    --grpc_python_out=./lib/grpc \
    ./resources/proto/worker.proto
  • 客户端实现 - client.request.py

与 js 环境下的实现方式类似,因为已经对 protobuf 的相关结构进行了预编译,协议的调用会更加清晰。直接正常建立与服务端的通信 channel,然后建立对应服务的 stub 对象,再通过 pb2 文件中定义的数据结构封装生成需要发送的数据对象后,即可执行 grpc 的数据请求与接收。

import grpc
import worker_pb2_grpc
import worker_pb2

channel = grpc.insecure_channel('localhost:9050')
stub = worker_pb2_grpc.TaskStub(channel)

task_conf = worker_pb2.TaskConf(id='001', job='test')
result = stub.runTask(task_conf)
print(result)

  • 客户端异步实现 - client.request.async.py

由于 python 语言本身是同步执行的,所以 grpc 在 python 环境下单独提供了异步接收服务端响应的处理方法。仅需按照如下的方式,调用执行方法的 future 方法,即可生成一个异步处理对象,用来手动调用获取返回值。

task = stub.runTask.future(task_conf)
result = task.result()
print(result)
  • 客户端流式接收实现 - client.stream.py

同样,python 环境下也支持流式传输方式的 grpc 通信,甚至对于服务端流式传输的处理上更为简洁,直接将 stream 的通信处理成一个迭代器方法,就可以直接迭代接收了。

for future in stub.runTaskProgress(task_conf):
    print(future.message)

参考文档:

  1. https://grpc.io/docs/tutorials/basic/python.html

最后修改于 2019-04-17