Java 17迁移后Spring Boot微服务无法连接Hazelcast集群求助
Spring Boot微服务使用Hazelcast 3.6版本(含hazelcast-client、hazelcast-spring)连接集群,Java 8环境下可正常运行,但迁移至Java 17且未修改代码后,出现连接失败错误:
thread="hz.client_0_obj-cartmap.cluster-listener" category="com.hazelcast.client.spi.ClientClusterService" Unable to get alive cluster connection, try in 8128 ms later, attempt 1 of 1000
经确认集群状态正常,可通过http://obj1.cartmp.intqa102.syseng.tmcs:5701/hazelcast/rest/cluster获取响应,相关配置代码如下:
private static final Logger log = LoggerFactory.getLogger(CartMappingHazelcastConfig.class); @Value("${cart.mapping.cache.local.instanceName}") private String localInstanceName; @Value("${cart.mapping.cache.common.groupName}") private String groupName; @Autowired HazelcastConfigProperties hazelcastConfigProperties; @Bean public CartIdBuilderFactory cartIdBuilderFactory() { return new CartIdBuilderFactory(this.localInstanceName); } @Bean public Serializer cartMappingSerializer() { return new CartMappingKryoSerializer(); } @Bean public Map<String, ClientConfig> hazelCastClientConfigs() { Map<String, ClientConfig> clientConfigsMap = new HashMap<>(); hazelcastConfigProperties.getConfigs().stream() .forEach(cacheProperties -> { clientConfigsMap.put(cacheProperties.getName(), makeClientConfig(cacheProperties)); }); return clientConfigsMap; } @Bean public Map<String, HazelcastInstance> hazelCastInstances() { return this.hazelCastClientConfigs().keySet() .stream() .collect(Collectors.toMap(k->k, k -> HazelcastClient.newHazelcastClient(hazelCastClientConfigs().get(k)))); } @Bean public Map<String, CacheManager> registeredCacheManagers() { return this.hazelCastInstances().keySet() .stream() .collect(Collectors.toMap(k->k, k -> new HazelcastCacheManager(this.hazelCastInstances().get(k)))); } @Bean public CartMappingCacheManager cartMappingCacheManager() { return new HazelcastCartCacheManager(this.registeredCacheManagers(), this.localInstanceName, CartContentsProvider.COMMERCE_API_PROVIDER_ID, cartIdBuilderFactory()); } private ClientConfig makeClientConfig(CacheConfigProperty cacheConfigProperty) { ClientConfig config = new ClientConfig(); config.getGroupConfig().setName("obj-cartmap").setPassword(cacheConfigProperty.getPassword()); config.getNetworkConfig() .setConnectionAttemptLimit(1000) .setSmartRouting(true) .setRedoOperation(true) .setConnectionTimeout(5000) .setConnectionAttemptPeriod(10000); config.getNetworkConfig().addAddress("obj1.cartmp.intqa102.syseng.tmcs"); config.getSerializationConfig() .addSerializerConfig(new SerializerConfig() .setTypeClass(CartMapping.class) .setImplementation(cartMappingSerializer())); return config; }
添加Java 17模块权限配置
Hazelcast 3.6未适配Java 9+的模块系统,需要在JVM启动参数中添加以下内容,开放反射和内部类访问权限:--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED --add-opens java.base/java.nio=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-exports com.sun.nio.sctp=ALL-UNNAMED调整TLS协议兼容配置
Java 17默认启用的TLS版本高于Java 8,而Hazelcast 3.6仅支持旧版协议,可通过JVM参数强制指定兼容版本:-Djdk.tls.client.protocols=TLSv1.2若集群启用SSL,需确保客户端SSL配置与集群一致,且Java 17信任库包含集群证书。
升级Hazelcast版本(优先推荐)
Hazelcast 3.6发布于2016年,完全未适配Java 17,建议升级到4.2.x及以上版本(4.2.x兼容Java 8和17)或5.x版本。升级后无需手动适配模块系统,且修复了大量高版本Java兼容性问题,同时提升性能与安全性。注意升级时需同步调整配置代码,部分ClientConfigAPI可能有变更。优化客户端连接参数
Java 17网络栈行为有变化,可调整连接超时和重试间隔参数:config.getNetworkConfig() .setConnectionTimeout(10000) // 延长连接超时至10秒 .setConnectionAttemptPeriod(5000); // 缩短重试间隔至5秒同时显式指定集群端口(默认5701),避免解析异常:
config.getNetworkConfig().addAddress("obj1.cartmp.intqa102.syseng.tmcs:5701");修复Kryo序列化兼容性
自定义CartMappingKryoSerializer在Java 17下可能存在反射权限问题,可添加JVM参数开放权限:--add-opens java.base/java.lang.reflect=ALL-UNNAMED若Kryo版本过旧,建议升级到支持Java 17的5.x版本。
内容的提问来源于stack exchange,提问作者gaurav bansal

