3

我们正在构建一个新平台,其中 gRPC 提供消息传递层,最终将公开我们的 API 预期支持的全套功能。

我们正在尝试确定命名接口的最佳模式,以避免重复的消息类型,不得不繁重地处理边缘情况和

我们正在做的一个简单示例涉及创建、更新和检索用户。以下是我们今天的服务的外观示例:

service Users {
  rpc GetUser(UserRequest) returns (core.user.User) {}
  rpc ListUsers(google.protobuf.Empty) returns (ListUsersResponse) {}
  rpc CreateUser(core.user.User) returns (core.user.User) {}
  rpc UpdateUser(core.user.User) returns (core.user.User) {}
}

message UserRequest {
  string id = 1;
}

message ListUsersResponse{
  repeated core.user.User users = 1;
}

GetUser 非常简单——它接收一个简单的 ID 的 UserRequest 消息,并返回一个用户(来自我们的核心包——应用程序中的许多服务将用户消息作为输入,所以我们将它放在一个共享位置)。

我的问题专门针对 Create/Update Users 调用,因为尚不清楚最佳解决方案是什么。这两个函数略有不同,主要是在一种情况下,我们已经有一个用户,因此有一个 ID,而在另一种情况下,我们正在创建一个新用户。在 Create 案例中,我们可能只有 User 上可能存在的可用字段的子集 - 但理想情况下,我们只需在一个地方维护此列表,因为它可能会变得相当大。我们可以:

  • 对于每个呼叫,定义自定义请求/响应消息,并在其中嵌入任何常见消息。这看起来像下面的代码。我担心的是,我们最终每次调用都会有一个消息类型,从可维护性的角度来看,这最终可能会非常繁重。

代码

message CreateUserRequest{ 
  core.User user = 1;
}
message UpdateUserRequest{
  int32 id = 1;
  core.User user = 2;
}
  • 我们可以期待/发送常见的消息类型,并依靠评论或其他反馈机制来鼓励消费者传递正确的值(我最初的实现演示了这一点)。我对这种方法的担忧是,我们最终不得不添加大量验证以确保他们提供的字段是“正确的”。

我正在努力在网上找到许多其他人如何处理此类问题的示例。我提供的示例相当简单,但您可以想象在整个项目中我们会遇到类似的问题。我希望看到有人在实践中完成的相当复杂的 gRPC 接口的示例,或者只是来自广泛使用它的人的反馈,以了解他们认为哪些界面设计模式最有效。

谢谢!

4

2 回答 2

4

我认为您正在寻找的是Google 的网络 API 设计指南。查看命名约定。特别是该页面上的方法名称部分。您将看到与您尝试做的非常相似的示例,这恰好很常见。

有关更具体的示例,请查看这里的 APIetcd是如何编写的。类似于你的and has and 。CreateUserRequestUpdateUserRequest etcdMemberAddRequestMemberUpdateRequest

于 2017-10-11T05:22:35.943 回答
1

您还可以查看 UBER 的在线设计文档,该文档为单独的响应实现提供了理由,并提供了详细的版本控制和命名约定

于 2019-12-18T06:09:57.210 回答