反射
说明如何使用反射提升 RPC 的透明性与可解读性
概述
反射是一套协议,gRPC 服务端可通过标准 RPC 服务对外声明自身导出的 Protobuf 定义 API,包含请求与响应消息所引用的所有类型。客户端可利用这些信息,以人类可读的方式对请求进行编码、对响应进行解码。
反射被 grpcurl、Postman 等调试工具大量使用。熟悉 REST 开发的开发者可将 gRPC 反射 API 类比为:在 HTTP 服务器上提供一份描述当前 REST API 的 OpenAPI 文档。
透明性与可解读性
gRPC 性能优异的重要原因是使用 Protobuf 进行序列化 ------ 这是一种二进制、人类不可读 的协议。虽然它极大提升了 RPC 速度,但也让手动与服务端交互变得困难。假设要通过 curl 基于 HTTP/2 手动向服务端发送 gRPC 请求,你必须:
- 知晓服务端暴露的 RPC 服务
- 知晓请求消息及其所有关联类型的 Protobuf 定义
- 知晓响应消息及其所有关联类型的 Protobuf 定义
之后还需手动将请求构造成二进制格式,并费力解码响应。这一过程耗时、易出错且令人沮丧。而反射协议让工具自动完成整个流程,对用户无感知。
在 gRPC 服务端启用反射
gRPC 服务端默认不启用 反射。服务端开发者必须调用额外方法注册反射服务。不同语言的 API 略有差异,部分语言还需额外引入名为 grpc-reflection 之类的独立依赖包。
可通过以下链接查看对应语言的详细说明:
| Language | Guide |
|---|---|
| Java | Java example |
| Go | Go example |
| C++ | C++ example |
| Python | Python example |
| Javascript | Javascript example |
使用提示
反射与 grpcurl 等工具配合使用时非常流畅,用户通常不会察觉到它在后台运行。但如果未暴露反射服务,功能将完全无法正常使用,客户端会抛出复杂错误。开发者在编写 gRPC 服务路由配置时经常遇到此问题:反射服务必须与应用主 RPC 服务一同路由到正确的后端。
如果 gRPC API 面向公网用户,不建议暴露反射服务,因为这可能带来安全风险。最终需要在安全性与易用性之间做出权衡,找到最适合自身与用户的平衡点。