82

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

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

4

8 回答 8

43

编辑:自 2018 年 10 月 23 日以来,gRPC-Web 项目是 GA,这可能是解决您的问题的最官方/标准化的方式。(即使现在已经是 2018 年了……;))

来自 GA-Blog:“gRPC-Web 就像 gRPC 一样,允许您使用协议缓冲区定义客户端(Web)和后端 gRPC 服务之间的服务“合同”。然后可以自动生成客户端。[...]”

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

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

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

于 2017-07-26T19:32:16.377 回答
17

不幸的是,还没有适合您的答案。

支持来自浏览器的流式 RPC 完全需要浏览器支持 HTTP2 预告片,而在撰写此答案时,它们还没有。

有关该主题的讨论,请参阅此问题

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

于 2016-02-03T00:42:23.240 回答
10

官方 grpc-web (beta) 实现于 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 路线图上。虽然有一个显示双向流的示例 protobuf ,但此评论清楚地表明该示例实际上还没有工作。

希望这会很快改变。:)

于 2018-03-25T06:54:34.047 回答
7

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

于 2016-10-14T17:19:27.157 回答
7

https://github.com/grpc/的 grpc 人目前正在构建一个 js实现

重现位于https://github.com/grpc/grpc-web(提供 404 ->),目前 (2016-12-20) 处于早期访问阶段,因此您需要请求访问

于 2016-12-20T13:01:21.367 回答
3

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

有服务器和客户端组件。GRPC Bus WebSocket 代理服务器可以通过 Docker运行docker run gabrielgrant/grpc-bus-websocket-proxy

在浏览器端,您需要安装GRPC Bus WebSocket 代理客户npm 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
  });

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

有关更多详细信息,请参阅GRPC 总线 WebSocket 代理客户端自述文件

于 2017-07-19T06:59:38.567 回答
2

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

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

如果您真的需要这种类型的序列化,我想可以对其进行修改以支持 gRPC。

但是,对于浏览器选项卡到浏览器选项卡,请求对象不是序列化的,而是本地传输的,NodeJS 集群或线程工作者也是如此,它提供了更多的性能。

此外,您可以将“指针”传输到 SharedArrayBuffer,而不是通过 gRPC 格式进行序列化。

V8 中的 JSON 序列化和反序列化也是无与伦比的。

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

于 2019-02-09T15:25:33.383 回答
0

查看当前使用 gRPC over web 的解决方案,以下是在撰写本文时可用的内容(以及我发现的内容):

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

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

于 2018-03-06T23:18:11.053 回答