java - Kubernetes 上的 Akka 集群心跳延迟

标签 java multithreading scala kubernetes akka

我们的 Scala 应用程序(Kubernetes 部署)不断遇到约 3 秒的 Akka 集群心跳延迟。

有一次我们甚至出现了 200 秒的延迟,如下图所示:

grafana-200s

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

规范

  • Kubernetes 1.12.5
requests.cpu = 16
# limits.cpu not set
  • 斯卡拉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 线程(参与者和远程处理) 所有这些都与心跳问题相关:

jfr-thread-park-1 jfr-thread-park-2

07:05:39 左右没有“心跳延迟”日志,但有以下日志:

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

期间未发现与暂停事件或阻塞线程的相关性 Java 飞行记录 session ,只有两个 Safepoint Begin 事件 接近延误:

jfr-safepoint-begin

CFS 节流

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

单独的调度程序

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

K8s集群

根据我们的观察,这种情况在以下几个 K8s 节点上发生的频率更高: 当我们的应用程序加载不多时,与许多其他应用程序共享一个大型 K8s 集群。

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

最佳答案

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

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

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

关于java - Kubernetes 上的 Akka 集群心跳延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58015699/

相关文章:

java - 在 Android 中将对象转换为 JSON

java - 用Java实现决策树数据库

scala - 在 Scala 中表达有状态过滤器的功能方法

scala - 为什么 Scala 有路径依赖类型?

java - 有没有办法不在 ListView 位置使用 getRef() 来获取当前单击用户的 getKey() ?

java - 无法将 admob 代码添加到我的应用程序中?

c - 线程与 MPI 同步

java - 如何设置 Java DelayQueue 的容量

java - 数组写入竞争条件

scala - 在 scala 中组合变量类型的函数序列