本篇博文完整讲述了如果通过 protocol buffers 定义并启动一个 gRPC 服务,然后在 gRPC 服务上提供一个 RESTful JSON API 的反向代理 gateway,
最后通过 swagger ui 来提供 RESTful JSON API 的说明,完整代码 helloworld_restful_swagger。

本来呢,我是专注 OpenFaas 的开发和设计的,Serverless 和微服务有相似点又有区别,但是二者实际落地的过程中还是需要结合实际的应用场景进行选择的;grpc 微服务主要是远程服务调用,公司成立以后技术体系会根据公司的选型就决定了公司会招聘那些技术栈的人,语言本身就是一种实现,一种工具,没有什么特别的;可是不同语言确实在不同领域有着不同的优势所在,比如你要用 C 语言做人工智能的脑仿真实验就是很奇葩的一件事;为了解决跨部门跨语言之间的相互调用,所以谷歌开源了 grpc ,一种语言中立的通讯协议;

serverless 说的直白点就是通过提供一种通用的框架,各个语言可以实现开发和相互调用,但是 FaaS 的框架基于传统的 RestfulApi 进行调用的,即使可以通过 Api 方式调用,也需要基于开发语言进行实现,所以 grpc 的优势就是在于,基于 protol 的协议可以实现远程过程调用,不需要再基于当前开发语言进行实现;因此 grpc 的应用场景一般是大公司和企业的跨部门跨语言的协作开发;Serverless 则是偏向传统开发语言的内外的调用实现,grpc 用于内部开发协作的调用;serverlees 用于内部和外部应用的调用实现,简单这么理解吧,基本就可以应用于绝大多数的场景了;

项目地址(私有项目,不公开): https://github.com/mateclouder/mate-grpc.git

# windows & linux 设置代理
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
# 下载依赖
pip install grpcio
pip install grpcio-tools googleapis-common-protos

gRPC由两个部分构成,grpcio 和 gRPC 工具, 后者是编译 protocol buffer 以及提供生成代码的插件。

编写protocol buffer
使用 gRPC 首先需要做的是设计 protocol buffer。新建一个 helloworld.proto 文件。

详情见 helloworld.proto;

生成接口代码

因为之前安装好了一些辅助插件,使用这里直接可以生成。

python -m grpc_tools.protoc -I . --python_out=. --grpc_python_out=. helloworld.proto

编写 gRPC 服务类

文件 helloworld_pb2_grpc.py 提供了 gRPC server 类(GreeterServicer)提供了 gRPC 服务的规范定义,
没有具体的实现。我们需要自己编写 gRPC 服务类文件 server.py,代码如下,

详情见 server.py;

然后启动 gRPC server:

python server.py

编写客户端

文件 helloworld_pb2_grpc.py 提供了 gRPC client 类(GreeterStub)定义。
我们需要编写自己的 client.py 代码来通过 GreeterStub 调用 gRPC server 方法。代码内容如下:

详情见 client.py;

启动 gRPC client:

python client.py

至此,可见我们的 gRPC helloworld 服务已经可用。

RESTful JSON API Gateway

调用 gRPC 服务需要自己编写相对应的 client 代码才行,这无疑给访问 gRPC 带来了一定的难度。我们可以通过在 gRPC 服务上面提供一个 RESTful API gateway,可以直接通过 RESTful JSON API 来访问。

grpc-gateway 是 protoc 的一个插件,用于读取 gRPC 服务定义,然后生成一个反向代理服务来将 RESTful JSON API 转换为 gRPC 调用。

a. 修改 helloworld.proto

修改文件 helloworld.proto,添加gateway option,
详情见 helloworld.proto

python -m grpc_tools.protoc -I . --go_out=plugins=grpc:. --python_out=. --grpc_python_out=. helloworld.proto
python -m grpc_tools.protoc -I . --grpc-gateway_out=logtostderr=true:. helloworld.proto

a. Install grpc-gateway

确保你本地安装了 golang 6.0 以上版本,并且将 $GOPATH/bin 添加到 $PATH 中。然后运行下面命令,

$  go get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway
$ go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger
$ go get -u github.com/golang/protobuf/protoc-gen-go

b. 编写 entrypoint 文件

编写 entrypoint 文件 proxy.go,内容如下
详情参见 proxy.go

编译,生成可执行文件 helloworld_restful_swagger,

go build .

c. 启动服务

# 先启动 gRPC 服务
python server.py
# 启动 gateway
grpc-helloworld.exe
# 通过 curl 进行访问
curl -X POST -k http://localhost:8080/v1/hello -d '{"name": "world"}'
curl -X POST -k http://localhost:8080/v1/hello -d '{"name": "lienhua34"}'

自此,RESTful JSON API gateway 已经可用了。

swagger UI

通过下面命令可以生成 RESTful JSON API 的 swagger 说明文件

python -m grpc.tools.protoc -I. --swagger_out=logtostderr=true:. helloworld.proto

该命令在 pb 目录下生成一个 helloworld.swagger.json 文件。我们在 pb 目录下直接新增一个文件 helloworld.swagger.go,
然后在里面定义一个常量 Swagger,内容即为 helloworld.swagger.json 的内容。

修改 proxy.go 文件中的 run() 方法来添加一个 API 路由来返回 swagger.json 的内容

备注: 此时不会继续推进 swagger-ui 的路由配置了,因为引入 swagger-ui 将会对代码结构产生一定的破坏,swagger-ui 将会通过容器化的方式进行展示;

后会无期,未来可期!