3

我已经实现了 2 个服务 A 和 B,其中 A 可以通过 gRPC(在 Mali 中使用 grpc-node)和纯 HTTP REST 调用与 B 对话。

请求大小可以忽略不计。

响应大小为 1000 个项目,如下所示:

{
   "productId": "product-0",
   "description": "some-text",
   "price": {
      "currency": "GBP",
      "value": "12.99"
   },
   "createdAt": "2020-07-12T18:03:46.443Z"
}

A 和 B 都作为服务部署在 GKE 中,它们使用 kube-proxy 通过内部网络进行通信。

我发现 REST 版本比 gRPC 快很多。REST 调用的 p99 小于 1 秒,而 gRPC 的 p99 可以超过 30 秒。

细节

节点版本和操作系统:node:14.7.0-alpine3.12

依赖项:

    "google-protobuf": "^3.12.4",
    "grpc": "^1.24.3",
    "mali": "^0.21.0",

我什至通过设置 gRPC 选项创建了客户端 TCP 池grpc.use_local_subchannel_pool=1,但这似乎没有帮助。

问题似乎出在服务器端,正如我从日志中看到的那样,grpc lib 的call.startBatch调用花费了很多秒来发送大小约为 51kb 的数据。这比 REST 版本慢得多。

我还检查了服务的 CPU 和网络是否健康。REST 版本可以发送 > 2mbps,而 gRPC 版本仅管理 ~150kbps。

在服务 B 上运行netstat(在 gRPC 中)显示了许多 ESTABLISHED TCP 连接(正如预期的那样,因为 TCP 池)。

我怀疑 grpc-core C++ 代码在某种程度上不如 REST 最佳,但我没有证据。

有什么想法我接下来应该看看吗?感谢您的帮助

更新 1

以下是一些基准:

设置

Blazemeter --REST--> services A --gRPC/REST--> service B

  • 请求正文(两个滞后)可以忽略不计
  • service A是节点服务+Koa
  • service B有3个选项:
    • grpc-node: 带有 grpc-node 的节点
    • gRPC + Go: 同一个 gRPC 服务的 Go 实现
    • REST + Koa: 带有 Koa 的节点
  • Blazemeter --> service A:响应负载可以忽略不计,所有测试都相同
  • serivce A --> service B:gRPC/REST 响应负载为 1000 个ProductPrice
message ProductPrice {
  string product_id = 1; // Hard coded to "product-x", x in [0 ... 999]
  string description = 2; // Hard coded to random string, length = 10
  Money price = 3;
  google.protobuf.Timestamp created_at = 4; // Hard coded
}

message Money {
  Currency currency = 1; // Hard coded to GBP
  string value = 2;  // Hard coded to "12.99"
}

enum Currency {
  CURRENCY_UNKNOWN = 0;
  GBP = 1;
}

这些服务在 GCP 中部署到 Kubernetes,

  • 实例类型:n1-highcpu-4
  • 每个服务 5 个 pod
  • 2 个 CPU,每个 pod 1 GB 内存
  • kube-proxy 使用集群 IP(不通过互联网)(我也测试了 headless with clusterIP: None,得到了类似的结果)

加载

50rps

结果

使用 grpc-node 的服务 B

在此处输入图像描述

使用 Go gRPC 的服务 B

在此处输入图像描述

使用 REST 和 Koa 的服务 B

在此处输入图像描述

网络 IO

在此处输入图像描述

观察

  • gRPC + GoREST与(我认为 gRPC 会更快)大致相当
  • grpc-node比慢 4 倍REST
  • 网络不是瓶颈
4

0 回答 0