Cliff的工作室
GRPC学习笔记

做微服务的想法由来已久,之前也试验过REST,感觉Java做服务端也还算方便,不过还是略显折腾。

最近需要做一个demo,要将一个python服务放出来,由于涉及到文件流传输,不太想用REST,于是就想到了GRPC

工程说起来倒是也没啥复杂的,客户端打算用web app来做,所以必然是用grpc-web。服务端虽然是要用python,不过鉴于目前还没学习过,打算先拿rust来搞一个调试一下,那就自然是用tonic

首先是搞服务端,参考tonic的examples就很容易了。工程直接可以运行,拿helloworld跑起来就可以,helloworld-client和helloworld-server可以互通。

然后客户端稍微有些麻烦,参考的文章在这里。原理本身很简单,但有些步骤跟原文不同,需要注意的有以下几点:

  1. 参考文章中使用protoc转换proto文件,用到了grpc-web,protoc安装时是不会安装对应的转换插件的。需要用npm install protoc-gen-grpc-web 安装这个对应插件。令我有点意外的是,我加上-g参数试图安装到系统全局,结果失败了,但安装到本地路径没有问题。
  2. 安装好protoc-gen-grpc-web后,在执行参考文章中执行protoc命令时,需要指定插件目录才可以正常转换。即node_modules/protoc-gen-grpc-web/bin
  3. 转换完成后,生成了两个文件,在我的例子里是helloworld_pb.jshelloworld_grpc_web_pb.js,前者是数据结构,后者是API接口。
  4. 调用接口的例子代码如下:
    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)}`);
    });

最后这段代码有几个需要注意的点:

  1. 关于端口,rust demo开的默认端口是50051,但为什么这里不直接使用呢?其实是因为grpc-web不能直接连接grpc server,需要经过一个proxy,通常用envoy构建。这部分说起来也比较简单,安装envoy,然后参考grpc-web的说明,下载envoy的例子配置yaml文件,然后配置端口即可。最后的运行用envoy -c envoy.yaml这样的形式即可。
  2. 关于request参数,需要用set函数设置。
  3. 关于response的解析,需要使用response.toObject()才能获得正确的response对象。

一开始没注意到envoy proxy的部分,直到做完才注意到。另外,grpc-web对于streaming的支持也是受限的,在gprc-web的roadmapstreaming-roadmap中有提到这点。最主要的问题,无法支持http上的全双工streaming。

考虑到demo同时需要文件的上传和下载,看起来grpc-web的限制在这里影响很大,因此我打算更换rsocket再试试。残念……

2020 年 09 月 27 日 15 时 06 分