gRPC API 架构建议

gRPC API Architecture advice

现在我正在 Python 中开发微服务应用程序。

基本上就像GUI -(gRPC)-> Server -(gRPC?)-> Workers

GUI 对服务器进行了各种调用,例如所有配置都存储在服务器上。为了性能和简单性,我决定使用#gRPC 作为 API 传输。

我已经实现了客户端和服务器类,现在我有一个两难选择:

  1. Performance best practices 告诉我们 Always re-use stubs and channels when possible. 出于这个原因,我可以制作通用的 rpc 通道,如:
UniMsg {
  int32 id = 1;
  string name = 2;
  bytes data = 3;
}

在客户端打包数据
(在某些情况下,不可能在 proto 中创建完整的数据模式。例如配置写成 JSON 以将其传输到 GUI 我要么必须在 proto 中实现所有配置字段,这对我来说似乎有点头疼,或者我可以将 JSON 编码为字节并以这种方式发送。它不会是透明的,但它允许修改配置结构而不需要 modify/compile proto。而且发送编码字节的性能似乎明显更好,我不需要 serialize/deserialize 它。)
,标记为name,根据name字段在服务器端解包处理。这会重用 stub 并将所需的 stubs 数量保持为一个。
唯一的缺点是它有点不是 RPC,它更像是 data bridge.

  1. 我可以创建多个 services,但它们确实需要单独的 stubs 和完整的数据描述。从 API 描述的角度来看这很好(即为了进一步扩展,无需查看 server/client “黑匣子”,您只需查看 proto 文件并根据描述的规则发送消息),但效果较差性能方面,因为我们使用新的 stubs.
syntax = "proto3";

message FilesAndFilters {
    repeated string file = 1;
    repeated string ext = 2;
}

message ResultList {
    repeated string file = 1;
}

//   <ServiceName>
service FList {
    // This is common method, it is described on server and called via stub on client.
    // <MethodName>(<ParamRequest>)
    rpc StreamFiles(FilesAndFilters) returns (ResultList);
}

message Settings {
    int32 profile = 1;
    bytes config = 2;
}

service CCConfig {
    rpc StreamConfig(Settings) returns (Settings);
}

向 gRPC 专家提出的问题:什么是最佳的中间立场来保持一切透明和不言自明并保持性能。

请注意,在某些时候可能会出现争论,即我的应用程序负载很低,性能损失可以忽略不计。我的目标是在将技术投入生产之前分享经验并了解所有怪癖,因此可以在高负载系统上使用相同的方法。

谢谢。

我认为您可能误解了“尽可能 re-use 存根和频道”这句话。本指南旨在避免重复拆卸和重新创建客户端通道,而不是将所有 RPC 服务合并为一个。

简而言之,选择选项 #2。拥有多种服务是惯用的,也是值得鼓励的。