负载下微服务之间http调用的时间差异

时间:2018-10-13 02:58:15

标签: docker asp.net-core kubernetes .net-core

Docker / Kubernetes上的Asp.Net Core微服务在调用者和被调用者之间的服务间调用持续时间上存在分歧。

呼叫者日志可以比被呼叫者多显示几毫秒到十整秒的时间。该问题在重负载下加剧,但在轻负载下仍然存在。许多呼叫确实在主叫方和被叫方之间达成了一致,但是这种差异确实经常发生,足以使整体性能下降。

时间戳指示该时间间隔可以是被呼叫者报告其响应已完成的之前之后

示例日志(实时差异中的数字)

ServiceB: [2018-10-11T22:41:41.374Z] S2S request complete to ServiceA, Duration: 11644
ServiceA: [2018-10-11T22:41:29.732Z] Request complete, Duration: 5

呼叫者时间(所有S2S呼叫的通用类)

var timer = Stopwatch.StartNew();
var response = await _httpClientFactory.CreateClient().SendAsync(request);
timer.Stop();
Logger.Info($"S2S request complete to {service}, Duration: {timer.EllapsedMilliseconds}");

Callee Timing(自定义Asp.Net中间件)

var timer = Stopwatch.StartNew();
await _next(context);
timer.Stop();
Logger.Info($"Request complete, Duration: {timer.EllapsedMilliseconds}");

该中间件几乎注册为管道中的第一个(用于日志关联的仅次于ActivityId / TraceId中间件)。

故障排除步骤

  • 无法在Windows开发计算机上重现该问题
  • 受监视的CPU,内存,线程数,GC收集,打开的句柄(全部处于合理水平)
  • 调整后的k8s规格CPU和内存请求/限制(不同级别有一定作用,但不能缓解问题)
  • 使用环境变量COMPlus_gcServer = 1打开服务器GC
  • 问题发生在资源限制内并且不需要自动缩放的服务上
  • 已更改为新的Kestrel套接字传输(而不是libuv)
  • 更改为新的.Net Core 2.1 SocketsHttpHandler

系统拓扑

Asp.Net Core 2.1自托管的Kestrel
.Net Core 2.1.5运行时
Docker / Kubernetes 1.10.5
K8s插件:kube-proxy,weave,etcd,SkyDNS
AWS c5.4xlarge

更新

  1. 发现时间间隔有时可以在被叫方开始/完成之前或之后

1 个答案:

答案 0 :(得分:0)

在这种情况下,此问题已通过删除 k8s spec CPU限制得到解决。

监视container_cpu_cfs_throttled_seconds_total度量标准发现,其中一个服务容器被频繁暂停 。这些暂停主要发生在S2S呼叫的呼叫方。这会增加呼叫者报告的经过时间。

删除k8s规范中的CPU限制可防止k8s通过--cpu-quota--cpu-period docker parameters。哪个控制着容器暂停。