如何将 API 定义的 gRPC 引入 Web 浏览器

How to bring a gRPC defined API to the web browser

我们想为我们的 gRPC 微服务构建一个 Javascript/HTML 图形用户界面。由于浏览器端不支持gRPC,我们想到了使用web-sockets连接一个node.js服务器,通过grpc调用目标服务。 我们努力寻找一个优雅的解决方案来做到这一点。特别是,因为我们使用 gRPC 流在我们的微服务之间推送事件。 看来我们需要第二个RPC系统,只是为了前端和node.js服务器之间的通信。这似乎是很多开销和必须维护的额外代码。

有没有人有过这样做的经验或知道如何解决这个问题?

抱歉,目前还没有适合您的答案。

从浏览器支持流式 RPC 完全需要浏览器支持 HTTP2 预告片,而在撰写本回答时,它们还不支持。

有关该主题的讨论,请参阅 this issue

否则,是的,您需要 WebSocket 和 gRPC 之间的完整转换系统。也许从 grpc-gateway 中获得灵感可能是这样一个项目的开始,但这仍然是一个很长的路要走。

https://github.com/tmc/grpc-websocket-proxy 听起来可能会满足您的需求。这会将 json 通过网络套接字转换为 grpc(grpc-gateway 之上的层)。

https://github.com/grpc/ are currently building a js implementation.

的 grpc 人

重现在https://github.com/grpc/grpc-web (gives 404 ->) which is currently (2016-12-20) in early access so you need to request access

GRPC Bus WebSocket Proxy 通过代理 WebSocket 连接上的所有 GRPC 调用来实现这一点,为您提供看起来与浏览器中的节点 GRPC API 非常相似的东西。与 GRPC-Gateway 不同,它适用于流式请求和流式响应,以及非流式调用。

同时有服务器和客户端组件。 通过执行 docker run gabrielgrant/grpc-bus-websocket-proxy

GRPC Bus WebSocket Proxy server 可以是 运行 和 Docker

在浏览器端,您需要安装 GRPC Bus WebSocket Proxy clientnpm install grpc-bus-websocket-client

然后创建一个新的 GBC 对象:new GBC(<grpc-bus-websocket-proxy address>, <protofile-url>, <service map>)

例如:

var GBC = require("grpc-bus-websocket-client");

new GBC("ws://localhost:8080/", 'helloworld.proto', {helloworld: {Greeter: 'localhost:50051'}})
  .connect()
  .then(function(gbc) {
    gbc.services.helloworld.Greeter.sayHello({name: 'Gabriel'}, function(err, res){
      console.log(res);
    });  // --> Hello Gabriel
  });

客户端库希望能够使用 AJAX 请求下载 .proto 文件。 service-map 提供代理服务器所见的原型文件中定义的不同服务的 URL。

有关详细信息,请参阅 GRPC Bus WebSocket Proxy client README

编辑:自 2018 年 10 月 23 日起 gRPC-Web project is GA,这可能是解决您问题的最 official/standardized 方法。 (即使现在已经是 2018 年了……;))

来自 GA 博客:"gRPC-Web, just like gRPC, lets you define the service “contract” between client (web) and backend gRPC services using Protocol Buffers. The client can then be auto generated. [...]"

我们最近构建了 gRPC-Web (https://github.com/improbable-eng/grpc-web) - 一个遵循提议的 gRPC-Web 协议的浏览器客户端和服务器包装器。该回购协议中的示例应该提供一个很好的起点。

如果您使用的是 Golang,则需要独立代理或 gRPC 服务器包装器。 proxy/wrapper 修改响应以将预告片打包在响应正文中,以便浏览器可以读取它们。

披露:我是该项目的维护者。

查看当前基于 Web 的 gRPC 解决方案,以下是撰写本文时可用的解决方案(以及我发现的):

我还想无耻地插入我自己为公司编写的解决方案,它在生产中用于代理对 gRPC 服务的请求,该服务仅包括一元和服务器流调用:

代码的每一寸都被测试覆盖。它是一个 Express 中间件,因此不需要对您的 gRPC 设置进行额外修改。您还可以将 HTTP 身份验证委托给 Express(例如使用 Passport)。

官方 grpc-web(测试版)实施于 2018 年 3 月 23 日发布。您可以在

找到它

https://github.com/grpc/grpc-web

以下说明摘自自述文件:

定义您的 gRPC 服务:

service EchoService {
  rpc Echo(EchoRequest) returns (EchoResponse);

  rpc ServerStreamingEcho(ServerStreamingEchoRequest)
      returns (stream ServerStreamingEchoResponse);
}

用你想要的任何语言构建服务器。

创建您的 JS 客户端以从浏览器进行调用:

var echoService = new proto.grpc.gateway.testing.EchoServiceClient(
  'http://localhost:8080');

进行一元 RPC 调用

var unaryRequest = new proto.grpc.gateway.testing.EchoRequest();
unaryRequest.setMessage(msg);
echoService.echo(unaryRequest, {},
  function(err, response) {
    console.log(response.getMessage());
  });

支持从服务器到浏览器的流:

var stream = echoService.serverStreamingEcho(streamRequest, {});
stream.on('data', function(response) {
  console.log(response.getMessage());
});

不支持双向流:

这是一项正在进行的工作,grpc-web roadmap. While there is an example protobuf showing bidi streaming, this comment 明确表示此示例尚未实际运行。

希望这会很快改变。 :)

我看到很多答案都没有指向基于 WebSocket 的双向解决方案,因为 OP 要求浏览器支持。

您可以使用 JSON-RPC 而不是 gRPC,以通过 WebSocket 获得 双向 RPC,它支持更多,包括 WebRTC(浏览器到浏览器) .

如果你真的需要这种类型的序列化,我想可以修改它以支持 gRPC。

但是,对于浏览器选项卡到浏览器选项卡,请求对象不会被序列化,而是在本地传输,与 NodeJS 集群或线程工作者相同,这提供了更多的性能。

此外,您可以将 "pointers" 传输到 SharedArrayBuffer,而不是通过 gRPC 格式序列化。

JSONV8中的序列化和反序列化也是无敌的

https://github.com/bigstepinc/jsonrpc-bidirectional