gRPC-Web 是一个官方提供的技术标准和相关实现,它允许直接从浏览器中的 JavaScript 应用程序调用 gRPC 服务。我们可以把它看作是 gRPC 在浏览器环境中的适配器。
简单来说,它架起了一座桥梁,让基于浏览器的前端应用也能享受到 gRPC 带来的所有优势。
gRPC-Web 解决了什么问题?
在 gRPC-Web 出现之前,gRPC 主要用在服务端之间(如微服务架构)的通信。浏览器无法直接使用 gRPC,原因主要有两个:
- HTTP/2 的限制:gRPC 构建在 HTTP/2 之上,但浏览器中的
XMLHttpRequest或早期的Fetch API无法提供对 HTTP/2 请求体的足够细粒度的控制,无法发送 gRPC 使用的二进制协议缓冲区载荷。 - 浏览器 API 限制:浏览器环境不允许 JavaScript 代码直接使用 HTTP/2 的某些高级特性(如 trailers,gRPC 用它来传输状态码和错误信息)。
因此,传统的 Web 前端要与后端通信,只能使用 RESTful API 或 GraphQL,并通过 JSON 进行数据交换。虽然这些技术很成熟,但与 gRPC 相比,它们在性能、类型安全和开发效率上有所欠缺。
gRPC-Web 的出现,就是为了让浏览器也能成为 gRPC 生态中的一等公民。
gRPC-Web 的核心工作原理
gRPC-Web 没有试图让浏览器直接理解 gRPC,而是采用了一种“代理”或“转码”的架构:
- 前端客户端:浏览器的 JavaScript 代码使用一个特殊的 gRPC-Web 客户端库。这个库会像普通 gRPC 客户端一样,让我们调用方法、传递强类型的请求对象。
- 编码:gRPC-Web 客户端库将我们的调用和参数编码成一种浏览器友好的格式(通常是二进制
application/grpc-web或文本application/grpc-web+json)。 - 发送 HTTP/1.1 请求:编码后的数据通过标准的浏览器
XMLHttpRequest或Fetch API,以 HTTP/1.1 协议发送出去。 - gRPC-Web 代理/Envoy:请求首先到达一个特殊的代理。这个代理最常见的实现是 Envoy 代理(它内置了
grpc_web过滤器)。代理的作用是“翻译”:它将收到的 HTTP/1.1 gRPC-Web 请求,转换为后端服务能够理解的纯 gRPC(HTTP/2)请求。 - 后端服务:纯 gRPC 请求被路由到真正的 gRPC 后端服务。对于后端服务来说,它完全不知道浏览器的存在,它认为自己只是在和一个普通的 gRPC 客户端通信。
- 响应路径:后端返回的纯 gRPC 响应,被代理再次“翻译”成浏览器可以理解的 gRPC-Web 格式,并通过 HTTP/1.1 返回给浏览器端的 gRPC-Web 客户端。
主要特点和优势
- 强类型和代码生成:和 gRPC 一样,我们需要使用
.proto文件定义服务接口,然后通过工具生成客户端存根代码。这保证了前后端数据类型的一致性,避免了手动解析 JSON 可能出现的错误。 - 高性能、载荷小:默认使用 Protocol Buffers 进行二进制序列化,相比 JSON 体积更小,序列化/反序列化速度更快,节省带宽,提升性能。
- 双向流:gRPC-Web 规范支持客户端流、服务器端流和双向流。虽然浏览器实现上对流的支持在不断完善,但它已经能够实现类似实时消息推送的功能。
- 现代化的开发体验:与 TypeScript 结合得天衣无缝,提供了极佳的代码自动补全和类型检查体验。
- 生态系统集成:可以自然地融入基于 gRPC 的微服务生态系统,前端可以直接调用微服务后端的接口,而无需再为前端专门编写一层 RESTful API 网关。
与普通 gRPC 和 REST 的对比
| 特性 | gRPC-Web | 普通 gRPC | REST/JSON |
|---|---|---|---|
| 传输协议 | HTTP/1.1 或 HTTP/2 | HTTP/2 | HTTP/1.1 |
| 数据格式 | Protocol Buffers (二进制) | Protocol Buffers (二进制) | JSON (文本) |
| 浏览器支持 | 是,通过特定客户端库 | 否 | 是,原生支持 |
| 强类型接口 | 是,通过 .proto 文件 |
是,通过 .proto 文件 |
否,依赖文档和约定 |
| 流式通信 | 支持 (客户端/服务端/双向) | 支持 (客户端/服务端/双向) | 有限 (主要通过 SSE/WebSockets) |
| 性能 | 高 (二进制,载荷小) | 非常高 (二进制,HTTP/2) | 中等 (文本,载荷大) |
总结
gRPC-Web 是一项关键技术,它成功地将 gRPC 的强大功能引入了浏览器环境。 它通过一个轻量级的代理“翻译”层,解决了浏览器与 gRPC 协议之间的兼容性问题。
如果你正在构建一个前后端分离的现代 Web 应用,并且后端已经或计划使用 gRPC,那么 gRPC-Web 是一个非常值得考虑的方案。它能为你带来更好的性能、更强的类型安全性和更高的开发效率。
声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
Author: mengbin
blog: mengbin
Github: mengbin92
腾讯云开发者社区:孟斯特
—