反射

解释了如何使用反射来提高 RPC 的透明性和可解释性。

概述

反射是一种 协议,gRPC 服务器可以使用它来声明通过标准化的 RPC 服务导出的 protobuf 定义的 API,包括请求和响应消息所引用的所有类型。客户端可以利用这些信息以人类可读的方式对请求进行编码并解码响应。

反射在调试工具中得到了广泛应用,例如 grpcurlPostman。来自 REST 世界的人可能会将 gRPC 反射 API 与在 HTTP 服务器上提供的 OpenAPI 文档进行比较,这个文档描述了正在呈现的 REST API。

透明度和可解释性

gRPC 出色的性能很大程度上归功于使用 Protobuf 进行序列化 —— 这是一种二进制且不可读的协议。虽然这大大加快了 RPC 的速度,但它也可能使得与服务器的手动交互变得更加困难。假设,为了手动通过 curl 向服务器发送 gRPC 请求,你需要:

  1. 知道服务器暴露了哪些 RPC 服务。

  2. 知道请求消息及其引用的所有类型的 protobuf 定义。

  3. 知道响应消息及其引用的所有类型的 protobuf 定义。

然后,你必须使用这些知识将请求消息手工构建成二进制格式,并且艰难地解码响应消息。这将是一个费时、令人沮丧且容易出错的过程。相反,反射协议使得工具能够自动化这个过程,从而让这个过程对用户来说是透明的。

在 gRPC 服务器上启用反射

反射在 gRPC 服务器中并不会自动启用。服务器的开发者必须调用一些额外的函数来添加反射服务。根据不同语言的要求,这些 API 调用略有不同,在某些语言中,可能还需要添加一个名为 grpc-reflection 的额外依赖。

请参考以下链接,了解你所使用语言的详细信息:

语言 指南

Java

Java 示例

Go

Go 示例

C++

C++ 示例

Python

Python 示例

Javascript

Javascript 示例

提示

反射与 grpcurl 等工具的配合非常顺畅,以至于很多时候人们甚至没有意识到它正在幕后工作。然而,如果没有暴露反射功能,工具将无法顺利工作,客户端会因错误而失败。很多人在编写 gRPC 服务的路由配置时会遇到这个问题。反射服务必须被正确路由到适当的后端以及应用程序的主 RPC 服务。

如果你的 gRPC API 对外公开,你可能不希望暴露反射服务,因为你可能认为这存在安全问题。最终,你需要做出一个权衡安全性和易用性的决定,找到适合你和你的用户的最佳平衡点。