【问题标题】:Returning multiple items in gRPC: repeated List or stream single objects?在 gRPC 中返回多个项目:重复列表或流单个对象?
【发布时间】:2020-11-27 21:39:02
【问题描述】:

gRPC 新手。我有一个简单的 api:

Customer getCustomer(int id)
List<Customer> getCustomers()

所以我的原型看起来像这样:

message ListCustomersResponse {
  repeated Customer customer = 1;
}

rpc ListCustomers (google.protobuf.Empty) returns (ListCustomersResponse);
rpc GetCustomer (GetCustomerRequest) returns (Customer);

我试图追随 Google 在风格上的领先。最初我有 returns (stream Customer) 用于 GetCustomers,但 Google 似乎更喜欢 ListxxxResponse 样式。当我生成代码时,它最终是:

public void getCustomers(com.google.protobuf.Empty request,
        StreamObserver<ListCustomersResponse> responseObserver) {

对比:

public void getCustomers(com.google.protobuf.Empty request,
        StreamObserver<Customer> responseObserver) {

我错过了什么吗?当我可以流式传输 Customer 并获得流式传输功能时,为什么还要麻烦创建 ListCustomersResponse?

ListCustomersResponse 只是一次流式传输整个列表,而不是流式传输每个客户。 Google 的偏好似乎是一直返回 ListCustomersResponse 样式。

什么时候使用 ListxxxResponse 与流响应比较合适?

【问题讨论】:

  • 我已经编辑了您的标题,使其对搜索结果更具描述性,但我认为更改您的措辞并不合适。请随时重新编辑或还原。

标签: grpc grpc-java


【解决方案1】:

如果不知道您使用的是什么参考资料,这个问题很难回答。可能存在沟通不畅,或者引用完全错误。

如果您正在查看gRPC Basics tutorial,那么我可能对导致误传的原因有所了解。 如果确实是您的参考,那么它确实建议返回 repeated 字段以获取流式响应;您的直觉是正确的:您只想流式传输单个客户。

它是这样说的(故意截屏):

您可能将 rpc ListFeatures(Rectangle) 理解为 返回特征列表 [名词] 的端点。如果是这样,那就是沟通不畅。该指南实际上意味着一个端点列出 [动词] 功能。如果他们只写 rpc GetFeatures(Rectangle),就不会那么混乱了。

所以,你的原型应该看起来更像这样,

rpc GetCustomers (google.protobuf.Empty) returns (stream Customer);
rpc GetCustomer (GetCustomerRequest) returns (Customer);

准确地生成您怀疑的内容更有意义。


更新

啊,我明白了,所以您正在 googleapis 中查看此示例:

  // Lists shelves. The order is unspecified but deterministic. Newly created
  // shelves will not necessarily be added to the end of this list.
  rpc ListShelves(ListShelvesRequest) returns (ListShelvesResponse) {
    option (google.api.http) = {
      get: "/v1/shelves"
    };
  }

...

// Response message for LibraryService.ListShelves.
message ListShelvesResponse {
  // The list of shelves.
  repeated Shelf shelves = 1;

  // A token to retrieve next page of results.
  // Pass this value in the
  // [ListShelvesRequest.page_token][google.example.library.v1.ListShelvesRequest.page_token]
  // field in the subsequent call to `ListShelves` method to retrieve the next
  // page of results.
  string next_page_token = 2;
}

是的,我想您现在可能已经想到了相同的想法,但这里他们选择使用简单的 RPC,而不是服务器端流式 RPC(请参阅 here) .我强调这一点是因为,我认为重要的选择不是 repeatedstream 之间的风格差异,而是 简单的请求-响应 API 之间的差异 strong> 与更复杂且不那么普遍的流式 API

在上面的 googleapis 示例中,他们定义了一个 API,该 API 返回每个页面的固定和静态数量的项目,例如 10 或 50。这只是过于复杂 使用流式传输,因为分页在软件架构和 REST API 中已经得到了很好的理解和流行。我认为这是他们应该说的,而不是“少数”。因此,流式传输的复杂性(以及您和未来维护者的学习成本)必须证明是合理的,仅此而已。假设您实际上正在为 Point Cloud 获取数千个 (x, y, z) 项目,或者您正在为某些加密货币创建实时更新的买卖可视化工具,例如

然后你会开始问自己,“简单的请求-响应 API 是我最好的选择吗?” 所以往往需要返回的项目数量越多,越多的流式 API 开始变得有意义。这可能是出于概念上的原因,例如这些项目是 time 中的实时更新流,就像上面的加密示例或架构,例如开始在 UI 中将结果作为部分数据流返回会更高效。我认为您阅读的“少量”内容过于简单化了。

【讨论】:

  • 我正在查看 Google 的 grpc API:github.com/googleapis/googleapis/search?q=returns+%28list
  • 您链接的文档说流。 Google apis 说重复大声笑。这就是为什么我问我的问题。唯一真正的“选择这个而不是另一个”是我读到的某个地方“如果重复使用一小部分,如果它是一个巨大的数字然后流”。他们并没有真正说出这个数字是多少。
  • 我现在明白了,谢谢!我编辑了我的答案。 tl; dr - 你读到的东西似乎过于简单化了。这与项目的数量无关,而是哪种 API / 架构对这种情况有意义。只是发生一个简单的请求-响应 API(即您所说的“重复”)对于较少数量的项目足够好,而流式传输越来越多地用作项目数量增加。但这是为了证明架构的复杂性,而不是项目的数量。
  • 长话短说 :),我会说默认为重复项目,除非它在流式传输中有意义。真的,如果你说的是保持 API 简单,你甚至不会使用 gRPC,因为它对于大多数用例来说过于复杂,而且工具仍然是史前的 :)。
  • @SledgeHammer - 真实,真实,在大多数现实世界的情况下。好吧,在我的公司,后端基础设施是基于 gRPC 的,所以即使对于简单的情况,我们也是基于 gRPC 构建的。但我想这并不常见(目前)。
猜你喜欢
  • 2010-09-28
  • 2020-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-06
  • 1970-01-01
  • 1970-01-01
  • 2019-03-17
相关资源
最近更新 更多