【问题标题】:Akka Cluster heartbeat delays on KubernetesKubernetes 上的 Akka Cluster 心跳延迟
【发布时间】:2020-01-20 18:21:13
【问题描述】:

我们的 Scala 应用程序(Kubernetes 部署)经常遇到约 3 秒的 Akka Cluster 心跳延迟。

我们甚至有 200 秒的延迟,这也体现在下图中:

有人可以提出进一步调查的建议吗?

规格

  • Kubernetes 1.12.5
requests.cpu = 16
# limits.cpu not set
  • Scala 2.12.7
  • Java 11.0.4+11
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:+AlwaysPreTouch
-Xlog:gc*,safepoint,gc+ergo*=trace,gc+age=trace:file=/data/gc.log:time,level,tags:filecount=4,filesize=256M
-XX:+PerfDisableSharedMem
  • Akka 集群 2.5.25

Java 飞行记录

一些例子:

timestamp    delay_ms
06:24:55.743 2693
06:30:01.424 3390
07:31:07.495 2487
07:36:12.775 3758

有 4 个可疑时间点发生了很多 Java Thread Park 事件 同时注册 Akka 线程(actors & remoting) 并且所有这些都与心跳问题有关:

07:05:39 附近没有“心跳延迟”日志,但这是一个:

07:05:39,673 WARN PhiAccrualFailureDetector heartbeat interval is growing too large for address SOME_IP: 3664 millis

期间未发现与停止事件或阻塞线程相关 Java Flight Recording 会话,只有两个 Safepoint Begin 事件 接近延误:

CFS 节流

应用程序 CPU 使用率较低,因此我们认为可能与 how K8s schedule our application node for CPU。 但是关闭 CPU 限制并没有太大改善, 虽然 kubernetes.cpu.cfs.throttled.second 指标消失了。

独立调度员

似乎没有必要使用单独的调度程序,因为即使在 没有负载,我们还构建了一个类似于我们自己的显式应用程序 除了心跳什么都不做,它仍然会遇到这些延迟。

K8s 集群

根据我们的观察,它在几个 K8s 节点上发生的频率更高 当我们的应用加载不多时,与许多其他应用共享的大型 K8s 集群。

单独的 我们的应用程序经过负载测试的专用 K8s 集群几乎没有问题 心跳延迟。

【问题讨论】:

  • 我们在 Kubernetes 和 Akka 集群中遇到了同样的心跳问题。你有没有发现问题是什么?
  • 不,我们只在空闲的 K8s 节点上体验它,几乎从不在负载节点上体验。所以我们刚刚将 K8s 更新到了最新版本,并专门为 Akka Cluster 应用固定了 CPU。

标签: java multithreading scala kubernetes akka


【解决方案1】:

你能排除垃圾收集吗?以我的经验,这是 JVM 分布式系统中延迟心跳的最常见原因(并且 Kubernetes/Mesos 环境中的 CFS 配额可以使 non-Stop-The-World GC 有效地 STW,特别是如果您没有使用真正最近的(晚于 JDK8 的 release 212)版本的 openjdk)。

“安全点开始”之前的每个线程停放确实让我相信 GC 实际上是罪魁祸首。某些 GC 操作(例如重新排列堆)要求每个线程都处于安全点中,因此当没有被阻塞时,线程会经常检查 JVM 是否希望它们进入安全点;如果是这样,线程会自行停驻以到达安全点。

如果您已排除 GC,您是否在云环境中运行(或在无法确定 CPU 或网络没有超额订阅的 VM 上)? akka-cluster 文档建议增加 akka.cluster.failure-detector.threshold 值,该值默认为适合更受控制的 LAN/裸机环境的值:云环境建议使用 12.0。这不会阻止延迟的心跳,但它会减少由于单个长心跳而导致虚假宕机事件的机会(并且还会延迟对真正节点丢失事件的响应)。但是,如果您想容忍心跳间隔时间从 1 秒到 200 秒的峰值,则需要一个非常高的阈值。

【讨论】:

  • 尽管 JFR 没有显示所有暂停事件,但我们启用了 GC 日志记录,并且它显示在心跳延迟附近没有主要 GC,其他的最大持续时间仅为 300 毫秒。
  • 关于 CFS 配额,我们通过在 manifest.yml 中注释掉 resources.limits.cpu 来为我们的 K8s 部署关闭它,尽管我们仍然有 resources.requests.cpu
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-10
  • 2023-04-04
  • 1970-01-01
  • 2021-05-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多