GRPC 学习笔记
2020 年 09 月 27 日
做微服务的想法由来已久,之前也试验过REST,感觉Java做服务端也还算方便,不过还是略显折腾。
最近需要做一个demo,要将一个python服务放出来,由于涉及到文件流传输,不太想用REST,于是就想到了GRPC。
工程说起来倒是也没啥复杂的,客户端打算用web app来做,所以必然是用grpc-web。服务端虽然是要用python,不过鉴于目前还没学习过,打算先拿rust来搞一个调试一下,那就自然是用tonic。
首先是搞服务端,参考tonic的examples就很容易了。工程直接可以运行,拿helloworld跑起来就可以,helloworld-client和helloworld-server可以互通。
然后客户端稍微有些麻烦,参考的文章在这里。原理本身很简单,但有些步骤跟原文不同,需要注意的有以下几点:
- 参考文章中使用protoc转换proto文件,用到了grpc-web,protoc安装时是不会安装对应的转换插件的。需要用
npm install protoc-gen-grpc-web
安装这个对应插件。令我有点意外的是,我加上-g
参数试图安装到系统全局,结果失败了,但安装到本地路径没有问题。 - 安装好protoc-gen-grpc-web后,在执行参考文章中执行protoc命令时,需要指定插件目录才可以正常转换。即
node_modules/protoc-gen-grpc-web/bin
。 - 转换完成后,生成了两个文件,在我的例子里是
helloworld_pb.js
和helloworld_grpc_web_pb.js
,前者是数据结构,后者是API接口。 - 调用接口的例子代码如下:
this.client = new GreeterClient("http://localhost:50000", null, null);
let request = new HelloRequest();
request.setName("cliff");
this.client.sayHello(request, {}, (err, response) => {
let resp = response.toObject();
console.log(`response=${JSON.stringify(resp)}`);
});
最后这段代码有几个需要注意的点:
- 关于端口,rust demo开的默认端口是50051,但为什么这里不直接使用呢?其实是因为grpc-web不能直接连接grpc server,需要经过一个proxy,通常用envoy构建。这部分说起来也比较简单,安装envoy,然后参考grpc-web的说明,下载envoy的例子配置yaml文件,然后配置端口即可。最后的运行用
envoy -c envoy.yaml
这样的形式即可。 - 关于request参数,需要用set函数设置。
- 关于response的解析,需要使用
response.toObject()
才能获得正确的response对象。
一开始没注意到envoy proxy的部分,直到做完才注意到。另外,grpc-web对于streaming的支持也是受限的,在gprc-web的roadmap和streaming-roadmap中有提到这点。最主要的问题,无法支持http上的全双工streaming。
考虑到demo同时需要文件的上传和下载,看起来grpc-web的限制在这里影响很大,因此我打算更换rsocket再试试。残念……