随着微服务的兴起,跨服务的调用比比皆是,RPC(Remote Procedure Call)是一种在本地调用远程函数的技术思想,gRPC是谷歌基于这一思想实现的框架,现在很多web-server采用go去编写,所有这种调用方式慢慢兴起。关于什么是grpc,这里就不细讲了,如果你需要在前端使用grpc,可以参照下面的方式来做。
文章开始之前先说一下几个目标:
- 在前端如何搭建一个mvp版本
- 这些搭建过程有哪些坑
- 还有一些官方文档上没有的处理方法(如何取消当前grpc请求,如何获取grpc的response header等)
搭建环境
这里会把每个细节说清楚,前端使用grpc的方式有很多,现在比较流行的解决方案是grpc-web这个插件。
使用步骤
安装gRPC-web 运行时库
$ npm i grpc-web
然后安装代码生成器插件,就是protoc,首先进入 protobuf 的 github,进入 release,下载所在平台的文件,然后进行安装,安装完记得把其加入到设置环境变量里,确保可以全局使用。
// 这是mac的安装方法,直接安装
brew install protobuf
然后安装grpc-web提供的解析插件release,这里对应不同系统,你可以根据自己的系统来做安装。
确保它们都是可执行的并且可以从您的 PATH 中发现,这里就是配置到环境变量的具体操作,例如,在 MacOS 中,您可以执行以下操作:
$ sudo mv ~/Downloads/protoc-gen-grpc-web-1.3.1-darwin-x86_64 \
/usr/local/bin/protoc-gen-grpc-web
$ chmod +x /usr/local/bin/protoc-gen-grpc-web
做完这些之后,执行 protoc --version 查看一下版本
编译执行
安装完成之后就是编译和使用,通常您将运行以下命令来编译.proto文件,生成我们可识别的js文件。
$ protoc -I= $DIR echo.proto \
--js_out=import_style=commonjs: $OUT_DIR \
--grpc-web_out=import_style=commonjs,mode=grpcwebtext: $OUT_DIR
// 这里提供一个例子
$ protoc -I=. src/Api/grpc/app.proto --js_out=import_style=commonjs:. --grpc-web_out=import_style=commonjs+dts,mode=grpcwebtext:.
然后你就会发现会生成几个_pb文件
使用
grpc-web的官网上提供了一些demo。
import * as grpcWeb from 'grpc-web';
import {EchoServiceClient} from './echo_grpc_web_pb';
import {EchoRequest, EchoResponse} from './echo_pb';
const echoService = new EchoServiceClient('http://localhost:8080', null, null);
const request = new EchoRequest();
request.setMessage('Hello World!');
const call = echoService.echo(request, {'custom-header-1': 'value1'},
(err: grpcWeb.RpcError, response: EchoResponse) => {
console.log(response.getMessage());
});
call.on('status', (status: grpcWeb.Status) => {
// ...
});
到这里就可以拿到数据了。
你不知道的操作
取消当前grpc请求?
其实在上面代码中我们发现call是整个请求的结果。于是我们答应这个call会发现在它的原型上有三个方法。
细心的小伙伴会发现这个cancel,其实这个cancel就是取消当前请求的方法。
获取grpc请求的response header?
有很多情况我们可能会自定义很多header来做权限处理。你会发现grpc并不像ajax可以直接在res中拿到对应的response header,刚好笔者就有这个需求。于是发现官方文档并没有相关的说明。于是去查看grpc-web提供的例子发现了解决办法。
const echoService = new EchoServiceClient('http://localhost:8080', null, null)
const req = new EchoRequest()
req.setMessage('aaa')
// this test tries to make sure that these types are as accurate as possible
const call1 : grpcWeb.ClientReadableStream<EchoResponse> =
echoService.echo(req, {}, (err: grpcWeb.Error,
response: EchoResponse) => {
})
// 这个call就是整个请求返回的结果,刚刚我们发现他的原型上有个叫做on的方法
call1
.on('status', (status: grpcWeb.Status) => {
//这里可以获取到当前请求的状态,和对应grpc的状态码
})
.on('metadata', (metadata: grpcWeb.Metadata) => {
// 这里就可以获取到我们的response header了
})
const call2 : grpcWeb.ClientReadableStream<ServerStreamingEchoResponse> =
echoService.serverStreamingEcho(new ServerStreamingEchoRequest(), {})
call2
.on('data', (response: ServerStreamingEchoResponse) => {
})
.on('error', (error: grpcWeb.Error) => {
})
这个issue 还说明设置custom header办法。
怎么查看grpc-web返回的数据
我们可能会注意到,在浏览器的控制台nextwork中查看接口返回的结果是一段二进制的内容。类似
这边有几种解决办法,使用一些解析工具去处理。还有一些反解析protobuf,然后再转成我们可识别的格式,整体看来都不太优雅。
笔者这边使用的办法是一个浏览器插件gRPC-Web Developer Tools这个插件之前在chrome插件商城可以下载,但是后面因为一些原因下架了,但是一些老用户还是保留了这个插件。
只是把这个插件放入需要在chrome安装插件的位置~/.config/google-chrome/Default/Extensions就行。
插件链接链接: pan.baidu.com/s/1jjIoBiEd… 提取码: 6gx4 ,请自取。 最终效果: