RSS

gRPC-Web 正式发布

我们很高兴地宣布 gRPC-Web 正式发布,这是一个 JavaScript 客户端库,使 Web 应用程序能够直接与 gRPC 后端服务通信,而无需 HTTP 服务器充当中间人。“正式发布”意味着 gRPC-Web 现在已正式可用、稳定,并有资格用于生产环境。

借助 gRPC-Web,您现在可以通过使用 Protocol Buffers 定义客户端服务器端数据类型和服务接口,轻松构建真正的端到端 gRPC 应用程序架构。这是一个被热切要求的功能,我们终于可以高兴地说它现在可以用于生产环境了。此外,能够访问 gRPC 服务为围绕 gRPC 的 基于 Web 的工具 开辟了令人兴奋的新的可能性。

基础知识

gRPC-Web 与 gRPC 一样,允许您使用 Protocol Buffers 定义客户端(Web)和后端 gRPC 服务之间的服务“契约”。然后可以自动生成客户端。为此,您可以在 Closure 编译器或更广泛使用的 CommonJS 之间进行选择。此开发过程消除了管理诸如创建自定义 JSON 序列化和反序列化逻辑、处理 HTTP 状态代码(在 REST API 中可能有所不同)、管理内容类型协商等问题的需要。

从更广泛的架构角度来看,gRPC-Web 实现了端到端 gRPC。下图说明了这一点

图 1. 使用 gRPC-Web 的 gRPC(左)和使用 REST 的 gRPC(右)

在左侧的 gRPC-Web 世界中,客户端应用程序使用 Protocol Buffers 与 gRPC 后端服务器通信,该服务器使用 Protocol Buffers 与其他 gRPC 后端服务通信。在右侧的 REST 世界中,Web 应用程序使用 HTTP 与后端 REST API 服务器通信,然后该服务器使用 Protocol Buffers 与后端服务通信。

使用 gRPC-Web 的优势

gRPC-Web 随着时间的推移将提供更广泛的功能集,但以下是今天的 1.0 版本中的功能

  • 端到端 gRPC — 使您能够使用 Protocol Buffers 制作整个 RPC 管道。想象一下,客户端请求发送到 HTTP 服务器,然后该服务器与 5 个后端 gRPC 服务交互的场景。您很可能会花费与构建整个其余管道一样多的时间来构建 HTTP 交互层。
  • 前端和后端团队之间更紧密的协调 — 通过使用 Protocol Buffers 定义整个 RPC 管道,您不再需要将您的“微服务团队”与您的“客户端团队”放在一起。客户端-后端交互只是其他 gRPC 层中的一层。
  • 轻松生成客户端库 — 使用 gRPC-Web,与“外部”世界交互的服务器,即连接你的后端堆栈和互联网的膜,现在是一个 gRPC 服务器而不是 HTTP 服务器,这意味着你所有服务的客户端库都可以是 gRPC 库。需要 Ruby、Python、Java 和其他 4 种语言的客户端库?你不再需要为所有这些语言编写 HTTP 客户端了。

gRPC-Web 示例

上一节说明了 gRPC-Web 在大型应用程序中的一些高层次优势。现在让我们通过一个示例更深入地了解一下:一个简单的 TODO 应用程序。在 gRPC-Web 中,你可以从一个简单的 todos.proto 定义开始,如下所示

syntax = "proto3";

package todos;

message Todo {
  string content = 1;
  bool finished = 2;
}

message GetTodoRequest {
  int32 id = 1;
}

service TodoService {
  rpc GetTodoById (GetTodoRequest) returns (Todo);
}

可以使用以下命令从此 .proto 定义生成 CommonJS 客户端代码

protoc echo.proto \
  --js_out=import_style=commonjs:./output \
  --grpc-web_out=import_style=commonjs:./output

现在,从后端 gRPC 服务获取 TODO 列表就像这样简单

const {GetTodoRequest} = require('./todos_pb.js');
const {TodoServiceClient} = require('./todos_grpc_web_pb.js');

const todoService = new proto.todos.TodoServiceClient('https://127.0.0.1:8080');
const todoId = 1234;

var getTodoRequest = new proto.todos.GetTodoRequest();
getTodoRequest.setId(todoId);

var metadata = {};
var getTodo = todoService.getTodoById(getTodoRequest, metadata, (err, response) => {
  if (err) {
    console.log(err);
  } else {
    const todo = response.todo();
    if (todo == null) {
      console.log(`A TODO with the ID ${todoId} wasn't found`);
    } else {
      console.log(`Fetched TODO with ID ${todoId}: ${todo.content()}`);
    }
  }
});

一旦你声明了数据类型和服务接口,gRPC-Web 就会抽象出所有的样板代码,为你留下一个简洁且人性化的 API(本质上与当前的 Node.js for gRPC API 相同,只是转移到了客户端)。

在后端,gRPC 服务器可以使用任何支持 gRPC 的语言编写,例如 Go、Java、C++、Ruby、Node.js 和其他许多语言。最后一个环节是服务代理。从一开始,gRPC-Web 就将支持 Envoy 作为默认服务代理,它内置了一个 envoy.grpc_web 过滤器,你只需几行配置即可应用。

下一步

正式发布 GA 意味着核心构建模块已经稳固到位,可以用于生产 Web 应用程序。但 gRPC-Web 还有更多内容值得期待。查看 官方路线图,了解核心团队对近期的设想。

如果你有兴趣为 gRPC-Web 做出贡献,我们很乐意社区提供以下方面的帮助

  • 前端框架集成 — 常用的前端框架,如 ReactVueAngular 尚未提供对 gRPC-Web 的官方支持。但我们希望看到这些框架支持它,因为这些前端框架与 gRPC-Web 之间的集成可以成为向应用程序交付用户可感知性能优势的途径。如果你有兴趣构建对这些前端框架的支持,请在 gRPC.io 邮件列表 上告诉我们,在 github 上提交功能请求 或通过下面的功能调查表单。

  • 特定语言的代理支持 — 在 GA 版本中,Envoy 是 gRPC-Web 的默认代理,通过一个特殊的模块提供支持。NGINX 也 受支持。但我们也希望看到为特定语言开发进程内代理,因为它们消除了对特殊代理(如 Envoy 和 nginx)的需求,并使使用 gRPC-Web 更加容易。

我们也希望从社区获得功能请求。目前,提出功能请求的最佳方式是填写 gRPC-Web 路线图功能调查。在填写表格时,列出你希望看到的功能,并在 我想为以下方面做出贡献 部分告诉我们你是否愿意为这些功能的开发做出贡献。gRPC-Web 工程师将在项目开发过程中认真对待这些信息。

最重要的是,我们要感谢过去一年中所有向我们提供反馈、错误报告和拉取请求贡献的 Alpha 和 Beta 用户。我们当然希望保持这种势头,并确保该项目为开发者社区带来切实的利益。