Amazon ECS 上的 Keycloak 集群失败(org.infinispan.commons.CacheException:缓存的初始状态传输超时)
Keycloak cluster fails on Amazon ECS (org.infinispan.commons.CacheException: Initial state transfer timed out for cache)
我正在尝试部署 2 个 Keycloak docker images (6.0.1) on Amazon ECS (Fargate) using the built-in ECS Service Discovery mecanism 的集群(使用 DNS_PING)。
环境:
JGROUPS_DISCOVERY_PROTOCOL=dns.DNS_PING
JGROUPS_DISCOVERY_PROPERTIES=dns_query=my.services.internal,dns_record_type=A
JGROUPS_TRANSPORT_STACK=tcp <---(also tried udp)
实例 IP 从 Route53 私有命名空间正确解析,它们相互发现没有任何问题(x.x.x.138 首先启动,然后 x.x.x.76)。
二审:
[org.jgroups.protocols.dns.DNS_PING] (ServerService Thread Pool -- 58) ip-x.x.x.76: entries collected from DNS (in 3 ms): [x.x.x.76:0, x.x.x.138:0]
[org.jgroups.protocols.dns.DNS_PING] (ServerService Thread Pool -- 58) ip-x.x.x.76: sending discovery requests to hosts [x.x.x.76:0, x.x.x.138:0] on ports [55200 .. 55200]
[org.jgroups.protocols.pbcast.GMS] (ServerService Thread Pool -- 58) ip-x.x.x.76: sending JOIN(ip-x-x-x-76) to ip-x-x-x-138
并且在第一个实例中:
[org.infinispan.CLUSTER] (thread-8,ejb,ip-x-x-x-138) ISPN000094: Received new cluster view for channel ejb: [ip-x-x-x-138|1] (2) [ip-x-x-x-138, ip-172-x-x-x-76]
[org.infinispan.remoting.transport.jgroups.JGroupsTransport] (thread-8,ejb,ip-x-x-x-138) Joined: [ip-x-x-x-76], Left: []
[org.infinispan.CLUSTER] (thread-8,ejb,ip-x-x-x-138) ISPN100000: Node ip-x-x-x-76 joined the cluster
[org.jgroups.protocols.FD_SOCK] (FD_SOCK pinger-12,ejb,ip-x-x-x-76) ip-x-x-x-76: pingable_mbrs=[ip-x-x-x-138, ip-x-x-x-76], ping_dest=ip-x-x-x-138
看来我们有一个工作集群。不幸的是,第二个实例最终失败并出现以下异常:
Caused by: org.infinispan.commons.CacheException: Initial state transfer timed out for cache work on ip-x-x-x-76
在这发生之前,我看到一堆故障发现任务suspecting/unsuspecting相反的实例:
[org.jgroups.protocols.FD_ALL] (Timer runner-1,null,null) haven't received a heartbeat from ip-x-x-x-76 for 60016 ms, adding it to suspect list
[org.jgroups.protocols.FD_ALL] (Timer runner-1,null,null) ip-x-x-x-138: suspecting [ip-x-x-x-76]
[org.jgroups.protocols.FD_ALL] (thread-9,ejb,ip-x-x-x-138) Unsuspecting ip-x-x-x-76
[org.jgroups.protocols.FD_SOCK] (thread-9,ejb,ip-x-x-x-138) ip-x-x-x-138: broadcasting unsuspect(ip-x-x-x-76)
在 Infinispan 端(缓存),一切似乎都正确发生,但我不确定。每个缓存都是 "rebalanced",每个 "rebalance" 似乎都以,例如:
结尾
[org.infinispan.statetransfer.StateConsumerImpl] (transport-thread--p24-t2) Finished receiving of segments for cache offlineSessions for topology 2.
感觉像是连接问题,但是这两个实例之间的所有端口都完全开放,包括 TCP 和 UDP。
有什么想法吗?有人成功地在 ECS (fargate) 上配置了这个吗?
更新 1
第二个实例最初关闭不是因为 "Initial state transfer timed out .." 错误,而是因为健康检查花费的时间比配置的宽限期长。尽管如此,对于 2 个健康的实例,我每 2 个查询收到一次“404 - Not Found”,告诉我确实存在缓存问题。
在当前的keycloak docker镜像(6.0.1)中,默认栈是UDP。根据 this,版本 7.0.0 将默认为 TCP,并且还将引入一个变量来切换堆栈 (JGROUPS_TRANSPORT_STACK)。
在 Amazon ECS 中使用 UDP 堆栈将 "partially" 工作,这意味着发现将工作,集群将形成,但 Infinispan 缓存将无法在实例之间同步,这将产生不稳定的错误.可能有一种方法可以让它工作 "as-is",但在检查 VPC 流日志时我没有看到实例之间有任何阻塞。
解决方法是通过直接在文件 /opt/jboss/keycloak/standalone/configuration/standalone-ha.xml:
中的图像中修改 JGroups 堆栈来切换到 TCP
<subsystem xmlns="urn:jboss:domain:jgroups:6.0">
<channels default="ee">
<channel name="ee" stack="tcp" cluster="ejb"/> <-- set stack to tcp
</channels>
然后提交新镜像:
docker commit -m="TCP cluster stack" CONTAINER_ID jboss/keycloak:6.0.1-tcp-cluster
Tag/Push 将映像发送到 Amazon ECR,并确保在您的 Amazon ECS 任务之间的安全组中接受端口 7600。
我正在尝试部署 2 个 Keycloak docker images (6.0.1) on Amazon ECS (Fargate) using the built-in ECS Service Discovery mecanism 的集群(使用 DNS_PING)。
环境:
JGROUPS_DISCOVERY_PROTOCOL=dns.DNS_PING
JGROUPS_DISCOVERY_PROPERTIES=dns_query=my.services.internal,dns_record_type=A
JGROUPS_TRANSPORT_STACK=tcp <---(also tried udp)
实例 IP 从 Route53 私有命名空间正确解析,它们相互发现没有任何问题(x.x.x.138 首先启动,然后 x.x.x.76)。
二审:
[org.jgroups.protocols.dns.DNS_PING] (ServerService Thread Pool -- 58) ip-x.x.x.76: entries collected from DNS (in 3 ms): [x.x.x.76:0, x.x.x.138:0]
[org.jgroups.protocols.dns.DNS_PING] (ServerService Thread Pool -- 58) ip-x.x.x.76: sending discovery requests to hosts [x.x.x.76:0, x.x.x.138:0] on ports [55200 .. 55200]
[org.jgroups.protocols.pbcast.GMS] (ServerService Thread Pool -- 58) ip-x.x.x.76: sending JOIN(ip-x-x-x-76) to ip-x-x-x-138
并且在第一个实例中:
[org.infinispan.CLUSTER] (thread-8,ejb,ip-x-x-x-138) ISPN000094: Received new cluster view for channel ejb: [ip-x-x-x-138|1] (2) [ip-x-x-x-138, ip-172-x-x-x-76]
[org.infinispan.remoting.transport.jgroups.JGroupsTransport] (thread-8,ejb,ip-x-x-x-138) Joined: [ip-x-x-x-76], Left: []
[org.infinispan.CLUSTER] (thread-8,ejb,ip-x-x-x-138) ISPN100000: Node ip-x-x-x-76 joined the cluster
[org.jgroups.protocols.FD_SOCK] (FD_SOCK pinger-12,ejb,ip-x-x-x-76) ip-x-x-x-76: pingable_mbrs=[ip-x-x-x-138, ip-x-x-x-76], ping_dest=ip-x-x-x-138
看来我们有一个工作集群。不幸的是,第二个实例最终失败并出现以下异常:
Caused by: org.infinispan.commons.CacheException: Initial state transfer timed out for cache work on ip-x-x-x-76
在这发生之前,我看到一堆故障发现任务suspecting/unsuspecting相反的实例:
[org.jgroups.protocols.FD_ALL] (Timer runner-1,null,null) haven't received a heartbeat from ip-x-x-x-76 for 60016 ms, adding it to suspect list
[org.jgroups.protocols.FD_ALL] (Timer runner-1,null,null) ip-x-x-x-138: suspecting [ip-x-x-x-76]
[org.jgroups.protocols.FD_ALL] (thread-9,ejb,ip-x-x-x-138) Unsuspecting ip-x-x-x-76
[org.jgroups.protocols.FD_SOCK] (thread-9,ejb,ip-x-x-x-138) ip-x-x-x-138: broadcasting unsuspect(ip-x-x-x-76)
在 Infinispan 端(缓存),一切似乎都正确发生,但我不确定。每个缓存都是 "rebalanced",每个 "rebalance" 似乎都以,例如:
结尾[org.infinispan.statetransfer.StateConsumerImpl] (transport-thread--p24-t2) Finished receiving of segments for cache offlineSessions for topology 2.
感觉像是连接问题,但是这两个实例之间的所有端口都完全开放,包括 TCP 和 UDP。
有什么想法吗?有人成功地在 ECS (fargate) 上配置了这个吗?
更新 1 第二个实例最初关闭不是因为 "Initial state transfer timed out .." 错误,而是因为健康检查花费的时间比配置的宽限期长。尽管如此,对于 2 个健康的实例,我每 2 个查询收到一次“404 - Not Found”,告诉我确实存在缓存问题。
在当前的keycloak docker镜像(6.0.1)中,默认栈是UDP。根据 this,版本 7.0.0 将默认为 TCP,并且还将引入一个变量来切换堆栈 (JGROUPS_TRANSPORT_STACK)。
在 Amazon ECS 中使用 UDP 堆栈将 "partially" 工作,这意味着发现将工作,集群将形成,但 Infinispan 缓存将无法在实例之间同步,这将产生不稳定的错误.可能有一种方法可以让它工作 "as-is",但在检查 VPC 流日志时我没有看到实例之间有任何阻塞。
解决方法是通过直接在文件 /opt/jboss/keycloak/standalone/configuration/standalone-ha.xml:
中的图像中修改 JGroups 堆栈来切换到 TCP<subsystem xmlns="urn:jboss:domain:jgroups:6.0">
<channels default="ee">
<channel name="ee" stack="tcp" cluster="ejb"/> <-- set stack to tcp
</channels>
然后提交新镜像:
docker commit -m="TCP cluster stack" CONTAINER_ID jboss/keycloak:6.0.1-tcp-cluster
Tag/Push 将映像发送到 Amazon ECR,并确保在您的 Amazon ECS 任务之间的安全组中接受端口 7600。