Hazelcast 缓存管理器:无法覆盖缓存的 CacheManager

Hazelcast Cache Manager: Cannot overwrite a Cache's CacheManager

在我正在工作的应用程序上,我正在尝试从 Hazelcast 3.6 升级到 3.12.4,我遇到了一些问题,当两个或多个测试一起 运行 时,这些问题很容易重现。这些测试都用 @WebAppConfiguration 注释并包括 Spring 的应用程序配置使用 ContextConfiguration(classes = {AppConfig.class})

作为配置的一部分,我有一个名为 CacheAwareStorage@Bean 启动 CacheManager。初始化非常基本:

public Cache<T, V> initCache(String name, Class<T> type, Class<T> valueType) {
    Cache<T, V> cache = manager.getCache(cacheName, keyType, valueType);
    if (cache != null)
    {
        return cache;
    }
    cache = manager.createCache(cacheName, config);
    return cache;
 }

当作为测试套件的一部分刷新上下文时会出现问题,我认为这是在 AbstractTestNGSpringContextTests 中完成的,因为我没有明确刷新上下文。发生以下错误,导致只有第一个 class 测试通过:

GenericWebApplicationContext: Refreshing org.springframework.web.context.support.GenericWebApplicationContext@6170989a
....
WARN GenericWebApplicationContext: Exception encountered during context initialization - cancelling refresh attempt
....
Factory method 'tokenStore' threw exception
     nested exception is java.lang.IllegalStateException: Cannot overwrite a Cache's CacheManager.

查看更改的内容,我看到 AbstracthazelcastCacheManager 抛出一个来自 Hazelcast CacheProxyIllegalStateException。更准确地说,manager.getCache() -> getCacheUnchecked() -> 在 createCacheProxy() 中创建缓存代理 -> 并将代理的管理器设置为 cacheProxy.setCacheManager() 中的当前管理器。 从 Hazelcast v3.9 开始,一旦设置了管理器,就不再允许这样做。

对此有什么解决方案?可能是 Hazelcast 中存在错误(没有检查正在设置的管理器是否实际上与现有的管理器不同),但是我正在寻找我可以做的事情。为什么 'getCache()' 尝试重新创建代理是我不明白的另一件事。

我假设我必须做一些事情才能不刷新上下文,但是我不知道我该怎么做(如果有的话)。

问题出在缓存管理器 Bean 的创建方式上。我使用了内部 Hazelcast 缓存管理器,每次都会创建一个新实例。如下使用 JCache API,解决了问题

@Bean
public CacheManager cacheManager() {
    HazelcastServerCachingProvider provider = Caching.getCachingProvider(); // or add class name of Hazelcast server caching provider to disambiguate
    return provider.getCacheManager(null, null, HazelcastCachingProvider.propertiesByInstanceItself(HAZELCAST_INSTANCE));
}

Hazelcast 团队在这方面的帮助:https://github.com/hazelcast/hazelcast/issues/16212