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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35065875/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 17:13:50  来源:igfitidea点击:

How to bring a gRPC defined API to the web browser

javascriptnode.jsprotocol-buffersmicroservicesgrpc

提问by Oliver

We want to build a Javascript/HTML gui for our gRPC-microservices. Since gRPC is not supported on the browser side, we thought of using web-sockets to connect to a node.js server, which calls the target service via grpc. We struggle to find an elegant solution to do this. Especially, since we use gRPC streams to push events between our micro-services. It seems that we need a second RPC system, just to communicate between the front end and the node.js server. This seems to be a lot of overhead and additional code that must be maintained.

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

Does anyone have experience doing something like this or has an idea how this could be solved?

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

采纳答案by Marcus

Edit: Since Oct 23,2018 the gRPC-Web project is GA, which might be the most official/standardized way to solve your problem. (Even if it's already 2018 now... ;) )

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

From the GA-Blog: "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. [...]"

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

We recently built gRPC-Web (https://github.com/improbable-eng/grpc-web) - a browser client and server wrapper that follows the proposed gRPC-Web protocol. The example in that repo should provide a good starting point.

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

It requires either a standalone proxy or a wrapper for your gRPC server if you're using Golang. The proxy/wrapper modifies the response to package the trailers in the response body so that they can be read by the browser.

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

Disclosure: I'm a maintainer of the project.

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

回答by Nicolas Noble

Unfortunately, there isn't any good answer for you yet.

不幸的是,您还没有任何好的答案。

Supporting streaming RPCs from the browser fully requires HTTP2 trailers to be supported by the browsers, and at the time of the writing of this answer, they aren't.

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

See this issuefor the discussion on the topic.

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

Otherwise, yes, you'd require a full translation system between WebSockets and gRPC. Maybe getting inspiration from grpc-gatewaycould be the start of such a project, but that's still a very long shot.

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

回答by Cody A. Ray

An official grpc-web (beta) implementation was released on 3/23/2018. You can find it at

2018 年 3 月 23 日发布了官方 grpc-web(测试版)实现。你可以在

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

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

The following instructions are taken from the README:

以下说明取自自述文件:

Define your gRPC service:

定义您的 gRPC 服务:

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

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

Build the server in whatever language you want.

以您想要的任何语言构建服务器。

Create your JS client to make calls from the browser:

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

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

Make a unary RPC call

进行一元 RPC 调用

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

Streams from the server to the browser are supported:

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

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

Bidirectional streams are NOT supported:

不支持双向流:

This is a work in progress and on the grpc-web roadmap. While there is an example protobufshowing bidi streaming, this commentmake it clear that this example doesn't actually work yet.

这是一项正在进行的工作,位于grpc-web 路线图上。虽然有一个示例 protobuf显示了 bidi 流,但是这个评论清楚地表明这个例子实际上还没有工作。

Hopefully this will change soon. :)

希望这会很快改变。:)

回答by RickyA

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

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

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

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

回答by tmc

https://github.com/tmc/grpc-websocket-proxysounds like it may meet your needs. This translates json over web sockets to grpc (layer on top of grpc-gateway).

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

回答by Gabriel Grant

GRPC Bus WebSocket Proxy does exactly this by proxying all GRPC calls over a WebSocket connection to give you something that looks very similar to the Node GRPC API in the browser. Unlike GRPC-Gateway, it works with both streaming requests and streaming responses, as well as non-streaming calls.

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

There is both a server and client component. The GRPC Bus WebSocket Proxy servercan be run with Docker by doing docker run gabrielgrant/grpc-bus-websocket-proxy

有服务器和客户端组件。该GRPC总线的WebSocket代理服务器可以与码头工人做运行docker run gabrielgrant/grpc-bus-websocket-proxy

On the browser side, you'll need to install the GRPC Bus WebSocket Proxy clientwith npm install grpc-bus-websocket-client

在浏览器端,你需要安装GRPC总线的WebSocket代理客户端npm install grpc-bus-websocket-client

and then create a new GBC object with: new GBC(<grpc-bus-websocket-proxy address>, <protofile-url>, <service map>)

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

For example:

例如:

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
  });

The client library expects to be able to download the .protofile with an AJAX request. The service-mapprovides the URLs of the different services defined in your proto file as seen by the proxy server.

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

For more details, see the GRPC Bus WebSocket Proxy client README

更多详细信息,请参阅GRPC 总线 WebSocket 代理客户端 README

回答by Tiberiu-Ionu? Stan

I see a lot of answers didn't point to a bidirectional solution over WebSocket, as the OP asked for browser support.

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

You may use JSON-RPC instead of gRPC, to get a bidirectional RPC over WebSocket, which supports a lot more, including WebRTC (browser to browser).

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

I guess it could be modified to support gRPC if you really need this type of serialization.

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

However, for browser tab to browser tab, request objects are not serializsed and are transfered natively, and the same with NodeJS cluster or thread workers, which offers a lot more performance.

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

Also, you can transfer "pointers" to SharedArrayBuffer, instead of serializing through the gRPC format.

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

JSON serialization and deserialization in V8 is also unbeatable.

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

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

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

回答by Sepehr

Looking at the current solutions with gRPC over web, here is what's available out there at the time of writing this (and what I found):

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

I also want to shamelessly plug my own solution which I wrote for my company and it's being used in production to proxy requests to a gRPC service that only includes unary and server streaming calls:

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

Every inch of the code is covered by tests. It's an Express middleware so it needs no additional modifications to your gRPC setup. You can also delegate HTTP authentication to Express (e.g with Passport).

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