grpc-web demo跑起来
最近调研区块链钱包插件的技术可行性,其中牵扯到grpc技术,官方repo有demo,但正常跑起有些门槛儿的,因此这里总结下。
安装
protobuf
1 | # 推荐安装方式,这样不需要再编译及进行环境变量配置,https://formulae.brew.sh/formula/protobuf |
protoc-gen-grpc-web
为了生成PB定义服务的Web端代码需要安装该工具
protoc-gen-grpc-web需要手动安装下,访问https://github.com/grpc/grpc-web/releases
比如我的intel-Mac,下载protoc-gen-grpc-web-1.3.0-darwin-x86https://grpc.io/_64
执行以下命令
1 | sudo mv ~/Downloads/protoc-gen-grpc-web-1.3.0-darwin-x86_64 \ |
同上,终端输入protoc-gen-grpc-web发现可以识别即表示安装成功。
protoc-gen-grpc-web的安装太麻烦了,定个flag,维护个npm包方便下大家下载安装。
brew使用补充
brew search package
可以搜索包有哪些版本源brew install package@versionNumber
可以直接安装目标版本
测试
按照定义的PB格式文件生成对应的JS版代码。
1 | protoc -I=. helloworld.proto --js_out=import_style=commonjs:. --grpc-web_out=import_style=commonjs,mode=grpcwebtext:. |
构建启动
以上步骤完成后,环境层问题即解决。紧接着按照readme的启动步骤一步步执行即可。
注意
如果开发机是Mac平台,需要如下两点修改
envoy.yaml配置修改
1
address: host.docker.internal
注意,只需要修改这一句即可
docker 启动命令调整-去掉network设定
1
2docker run -d -v "$(pwd)"/envoy.yaml:/etc/envoy/envoy.yaml:ro \
-p 8080:8080 -p 9901:9901 envoyproxy/envoy:v1.20.0
错误
Http response at 400 or 500 level
启动后,如果遇到该错误,即网络服务不同,查看服务是否正常启动,比如上述代理配置错造成容器通讯问题。如果是envoy代理的某节点挂掉也会导致报错。
常见问题
grpc-web使用中遇到了些问题,官方文档及社区并不活跃,很多坑还得自己踩,这里总结下常见的一些问题
grpc: received message larger than max (1094796627 vs. 4194304)
遇到该报错,存在两种情况
大小设定
grpc.max_send_message_length
设置,单位bytes,-1
表示没有限制- 服务端/客户端设置相互独立
官方配置见https://grpc.github.io/grpc/core/group__grpc__arg__keys.html#gab4defdabac3610ef8a5946848592458c
–grpc-web_out
确定WEB输出模式是grpcwebtext还是grpcweb,如果是grpcweb,但最终发的是二进制,则会报received message larger than max,有1G之多。
1 | $ protoc -I=. helloworld.proto --js_out=import_style=commonjs:. --grpc-web_out=import_style=commonjs,mode=grpcweb:. |
413 (Request Entity Too Large)
- 确定nginx
client_max_body_size
配置 - 确认grpc-server端
grpc.max_receive_message_length
配置
自定义头部字段
有时发送请求希望自定义头部,比如这样实现动态代理grpc服务。
实现需要2部分设置
1 | var client = new GreeterClient('http://' + window.location.hostname + ':9090', null, null); |
nginx设定读取自定义字段从而实现动态代理
1 | server { |
Nginx动态代理gRPC服务
1 | location / { |
注意http_x_grpc_node
为HTTP自定义头部字段值。如果需要代理SSL服务,对应是grpcs://
,具体配置如下
代理gRPCs
1 | location / { |
注意
grpc_ssl_certificate,grpc_ssl_certificate_key文件值支持变量
,因此可以动态代理不同的server。grpc_pass/grpc_ssl_certificate
这些指令并不支持在if条件块中书写,因此无法做到grpc和grpcs的动态代理切换。
补充
- 在确定RPC server是否正常启动时,可以使用telnet来测试端口联通性,比如
telnet 192.168.1.203 16301
参考文档
- https://www.npmjs.com/package/google-protobuf
- https://grpc.io/docs/protoc-installation/
- https://github.com/grpc/grpc-web
- https://stackoverflow.com/questions/9421933/cross-origin-xmlhttprequest-in-chrome-extensions
- https://stevenocean.github.io/2020/06/20/nginx-grpc-web-go.html
写在最后
初步尝试下,有以下几点认识
- gRPC 默认通过 Protocol Buffers 来定义接口。因此grpc使用牵扯到pb
- gRPC Web是gRPC协议在浏览器端的javascript实现,但想真的连接grpc-server需要代理服务,比如Envoy/Nginx等
- gRPC Web使Web能间接与后端gRPC服务通信