Amazon ECS 上的 Keycloak 集群失败(org.infinispan.commons.CacheException:缓存的初始状态传输超时)
Posted
技术标签:
【中文标题】Amazon ECS 上的 Keycloak 集群失败(org.infinispan.commons.CacheException:缓存的初始状态传输超时)【英文标题】:Keycloak cluster fails on Amazon ECS (org.infinispan.commons.CacheException: Initial state transfer timed out for cache) 【发布时间】:2019-12-19 05:25:39 【问题描述】:我正在尝试使用内置 ECS Service Discovery mecanism(使用 DNS_PING)在 Amazon ECS (Fargate) 上部署 2 个 Keycloak docker images (6.0.1) 的集群。
环境:
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
在这种情况发生之前,我看到一堆故障发现任务怀疑/不怀疑相反的实例:
[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 方面(缓存),一切似乎都正确发生,但我不确定。每个缓存都被“重新平衡”,每个“重新平衡”似乎都以,例如:
[org.infinispan.statetransfer.StateConsumerImpl] (transport-thread--p24-t2) Finished receiving of segments for cache offlineSessions for topology 2.
感觉像是连接问题,但是这两个实例之间的所有端口都是开放的,对于 TCP 和 UDP。
有什么想法吗?有人在 ECS (fargate) 上成功配置这个吗?
更新 1 第二个实例最初关闭不是因为“初始状态传输超时..”错误,而是因为运行状况检查花费的时间超过了配置的宽限期。尽管如此,对于 2 个健康的实例,我每 2 个查询都会收到一次“404 - Not Found”,告诉我确实存在缓存问题。
【问题讨论】:
我没有使用 ECS 的经验,但云提供商经常阻止 UDP。我建议只使用 TCP 堆栈运行。 即使我设置 JGROUPS_TRANSPORT_STACK=tcp,发现使用我认为是 udp 的端口 55200,但我不确定。我在文档中看不到任何其他强制 TCP 的方法。 刚刚找到 issues.jboss.org/browse/KEYCLOAK-10198,它引入了 JGROUPS_TRANSPORT_STACK 变量。将在 Keycloak 7.0.0 中提供。 【参考方案1】:在当前的 keycloak docker 镜像 (6.0.1) 中,默认堆栈是 UDP。根据this 的说法,7.0.0 版本将默认使用 TCP,并且还会引入一个变量来切换堆栈(JGROUPS_TRANSPORT_STACK)。
在 Amazon ECS 中使用 UDP 堆栈将“部分”工作,这意味着发现将工作,集群将形成,但 Infinispan 缓存将无法在实例之间同步,这将产生不稳定的错误。可能有一种方法可以使其“按原样”工作,但在检查 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
将映像标记/推送到 Amazon ECR,并确保您的 Amazon ECS 任务之间的安全组接受端口 7600。
【讨论】:
以上是关于Amazon ECS 上的 Keycloak 集群失败(org.infinispan.commons.CacheException:缓存的初始状态传输超时)的主要内容,如果未能解决你的问题,请参考以下文章
ELB 和 ECS 集群前的 Amazon API Gateway
Amazon ECS 上的 Spring Cloud 数据流
Cloud Foundry 上的 Keycloak 独立集群