我们正在构建一个新平台,其中 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 接口的示例,或者只是来自广泛使用它的人的反馈,以了解他们认为哪些界面设计模式最有效。
谢谢!