我们能够解决导致网络流量激增的问题。详细信息如下。
tl;dr:
我们从 JGroups UDP 堆栈切换到 TCP 堆栈,ISPN 文档提到这对于使用像我们这样的分布式缓存的小型集群来说可以更有效。
重现问题
为了重现该问题,我们执行了以下操作:
-
将清除 ISPN 缓存条目的 Keycloak 后台作业配置为每 60 秒运行一次,这样我们就不必等待该作业以 15 分钟的间隔运行(独立-ha.xml):
<scheduled-task-interval>60</scheduled-task-interval>
生成大量用户会话(我们使用 jmeter)。在我们的测试中,我们最终生成了大约 100,000 个会话。
- 将 Keycloak 中的 SSO Idle 和 Max time TTL 配置为极短,以便所有会话都将过期(60 秒)
- 继续用jmeter给系统施加负载(这部分很重要)
当清除缓存的作业运行时,我们会看到网络流量泛滥(120 MB/s)。发生这种情况时,我们会在集群中的每个节点上看到大量以下错误:
ISPN000476:等待来自的请求 7861 的响应超时
节点2
ISPN000217:从节点 1 收到异常,请参阅远程堆栈的原因
痕迹
Pro-Tip:配置文件存储的钝化以保留您的 ISPN 数据。关闭集群并将“.dat”文件保存在其他位置。使用这些文件可以在测试之间立即恢复 ISPN 集群的状态。
解决问题
使用上述技术,我们能够根据需要重现该问题。因此,我们开始使用下面描述的方法来解决这个问题。
更改 JGroups 堆栈以使用 TCP
我们将 JGroups 堆栈从 UDP 更改为 TCP,并配置了 TCPPing 以进行发现。我们在阅读以下指南中 TCP 堆栈的描述后执行了此操作:
https://infinispan.org/docs/stable/titles/configuring/configuring.html#preconfigured_jgroups_stacks-configuring https://infinispan.org/docs/stable/titles/configuring/configuring.html#preconfigured_jgroups_stacks-configuring
具体来说:
“使用 TCP 进行传输,使用 UDP 多播进行发现。适用于
仅当您使用分布式时,较小的集群(少于 100 个节点)
缓存,因为作为点对点 TCP 比 UDP 更高效
协议。”
这一变化完全消除了我们的问题
我们在standalone-ha.xml中的Wildfly 16配置如下:
<subsystem xmlns="urn:jboss:domain:jgroups:6.0">
<channels default="ee">
<channel name="ee" stack="tcp" cluster="ejb"/>
</channels>
<stacks>
<stack name="udp">
<transport type="UDP" socket-binding="jgroups-udp"/>
<protocol type="PING"/>
<protocol type="MERGE3"/>
<protocol type="FD_SOCK"/>
<protocol type="FD_ALL"/>
<protocol type="VERIFY_SUSPECT"/>
<protocol type="pbcast.NAKACK2"/>
<protocol type="UNICAST3"/>
<protocol type="pbcast.STABLE"/>
<protocol type="pbcast.GMS"/>
<protocol type="UFC"/>
<protocol type="MFC"/>
<protocol type="FRAG3"/>
</stack>
<stack name="tcp">
<transport type="TCP" socket-binding="jgroups-tcp"/>
<socket-protocol type="TCPPING" socket-binding="jgroups-tcp">
<property name="initial_hosts">HOST-X[7600],HOST-Y[7600],HOST-Z[7600]</property>
<property name="port_range">1</property>
</socket-protocol>
<protocol type="MERGE3"/>
<protocol type="FD_SOCK"/>
<protocol type="FD_ALL"/>
<protocol type="VERIFY_SUSPECT"/>
<protocol type="pbcast.NAKACK2"/>
<protocol type="UNICAST3"/>
<protocol type="pbcast.STABLE"/>
<protocol type="pbcast.GMS"/>
<protocol type="MFC"/>
<protocol type="FRAG3"/>
</stack>
</stacks>
</subsystem>
调整 JVM 垃圾收集器参数
我们遵循了 ISPN 调整指南中的一些建议:
https://infinispan.org/docs/stable/titles/tuning/tuning.html https://infinispan.org/docs/stable/titles/tuning/tuning.html
特别是,我们从 JDK 8 的默认 GC 更改为使用 CMS 收集器。具体来说,我们的 Wildfly 服务器现在提供了以下 JVM 参数:
-Xms6144m -Xmx6144m -Xmn1536M -XX:MetaspaceSize=192M -XX:MaxMetaspaceSize=512m -Djava.net.preferIPv4Stack=true -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+DisableExplicitGC
其他变更
我们应用了针对我们的环境的其他更改:
- 在 iptables 级别阻止 IP 多播 + UDP(因为我们想确保我们仅使用 TCP)
- 在网络级别配置带宽上限,以防止 ISPN 群集使网络饱和并影响使用同一链路的其他主机。