Kubernetes环境下WildFly集群远程EJB调用无负载均衡问题排查
问题描述
我们的项目部署在Kubernetes环境中:
- 后端是3个副本的WildFly StatefulSet,通过JGroups实现集群,远程EJB通过ClusterIP类型的Kubernetes Service对外提供访问
- 客户端是1个副本的Deployment,通过InitialContext调用远程EJB,客户端代码如下:
jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.wildfly.naming.client.WildFlyInitialContextFactory"); jndiProperties.put(Context.PROVIDER_URL, actorConfig.getProvider()); //http-remoting://backend-service:80 jndiProperties.put(Context.SECURITY_PRINCIPAL, actorConfig.getPrincipal()); jndiProperties.put(Context.SECURITY_CREDENTIALS, actorConfig.getCredentials());
当前调用可成功执行,但所有方法调用均仅落到首次被调用的Pod上,集群未实现负载均衡。根据WildFly naming client文档描述,相同远程URL的消费者会共享连接,连接生命周期独立于Context实例,推测客户端复用了与单个Pod的连接。现咨询:在无法升级的WildFly 18版本中,是否缺少服务端或客户端配置,以实现每次方法调用分发至任意一个后端Pod?
解决方案
一、客户端配置调整
WildFly 18的naming client默认复用连接池中的长连接,导致请求固定到单个Pod,可通过以下配置调整:
启用连接池负载均衡策略
在JNDI属性中添加以下配置,让客户端在连接池创建时均衡分配连接到不同后端实例:jndiProperties.put("wildfly.naming.client.connection.provider.create.options.org.xnio.Options.BALANCE_CONNECTIONS", "true"); jndiProperties.put("wildfly.naming.client.connection.pool.size", "3"); // 对应后端Pod副本数 jndiProperties.put("wildfly.naming.client.connect.timeout", "5000");手动指定多后端地址
利用StatefulSet Pod名称固定的特性,直接将所有后端Pod地址以逗号分隔写入PROVIDER_URL,WildFly client会对多个地址做轮询负载:// 替换为实际Pod地址 jndiProperties.put(Context.PROVIDER_URL, "http-remoting://backend-0:80,http-remoting://backend-1:80,http-remoting://backend-2:80");
二、服务端WildFly配置调整
在WildFly 18的standalone.xml或domain.xml中,确保远程连接器和EJB子系统启用集群感知:
配置remoting子系统启用集群
<subsystem xmlns="urn:jboss:domain:remoting:4.0"> <http-connector name="http-remoting-connector" connector-ref="default" security-realm="ApplicationRealm"> <param name="buffer-pool" value="default"/> <param name="cluster" value="true"/> <!-- 开启集群节点发现 --> </http-connector> </subsystem>确认EJB子系统配置集群路由
<subsystem xmlns="urn:jboss:domain:ejb3:6.0"> <cluster> <ejb-protocol connector-ref="http-remoting-connector"/> <!-- 绑定远程连接器 --> </cluster> </subsystem>该配置会让服务端把集群节点信息传递给客户端,让客户端感知所有可用实例。
三、Kubernetes层面配置确认
确保后端Service未启用会话亲和性(默认即为None,可明确配置):
apiVersion: v1 kind: Service metadata: name: backend-service spec: selector: app: backend ports: - port: 80 targetPort: 8080 sessionAffinity: None
避免Service层面将请求固定到单个Pod,配合客户端连接池调整实现负载均衡。
内容的提问来源于stack exchange,提问作者Peter Andreus
相关产品推荐
相关产品推荐

