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

ubuntu 上的 Amazon ECS 代理未启动

Amazon ECS 上的 Spring Cloud 数据流

Cloud Foundry 上的 Keycloak 独立集群

提供最新 amazon-ecs-optimized image 的 ami-id 的脚本或 api

aws ecs 使用copilot快速创建ecs集群环境并部署服务