Spring Boot 中的 Hazelcast 和 JCache 创建了两个实例
Hazelcast and JCache in Spring Boot creates two instances
看起来默认 Spring 启动自动配置将在使用 JCache 并启用缓存时创建两个 hazelcast 实例 (@EnableCaching
)
完整示例位于:https://github.com/dirkvanrensburg/hazelcast-springboot-jcache
TLDR;
Is there a way to get Spring boot's autoconfiguration to only create one Hazelcast instance when enabling caching through JCache?
我通过添加以下依赖项创建了一个演示 Spring 引导项目:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
</dependency>
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast</artifactId>
</dependency>
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast-spring</artifactId>
<version>${hazelcast.version}</version>
</dependency>
并将 @EnableCaching
添加到应用程序 class,Spring 将自动配置 Hazelcast 但会启动两个 hazelcast 实例,它们加入了一个集群,如日志所示:
Members [2] {
Member [192.168.1.157]:5701 - 3eabbe90-6815-49ff-8d93-9e4b12e67810
Member [192.168.1.157]:5702 - e9c93366-2408-4726-965a-b21dcf897113 this
}
缓存有效,但我不想要两个 Hazelcast 实例。
破解
我通过提供自己的缓存管理器设法让它工作:
@Bean
public CacheManager springHzProvider(HazelcastInstance instance) {
return SpringHazelcastCachingProvider.getCacheManager(instance, null, new Properties());
}
并删除 hazelcast
和 hazelcast-spring
依赖项并添加 hazelcast-all
:
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast-all</artifactId>
<version>${hazelcast.version}</version>
</dependency>
但问题是是否有更好的 'proper' 方法来实现这一点?理想情况下无需定义自定义缓存管理器并添加 hazelcast-all
@dvanrensburg 根据评论,作为临时解决方案,从 auto-configuration 中排除 HazelcastAutoConfiguration
class。我已经记录了 Spring Boot https://github.com/spring-projects/spring-boot/issues/8275 的问题,因为我认为这是根本原因,如果 @EnableCaching
触发了第一个实例的创建,则不应创建第二个实例。
我在上面使用了 Neil 的解决方案,但是 运行 我无法自动装配由 JCache 配置创建的 Hazelcast 实例。看起来该实例是在 Spring 之外创建的,并已在应用程序上下文中注册。
在配置中为实例命名
<instance-name>test</instance-name>
然后添加一个显式挂钩以将实例引入上下文
@Bean
public HazelcastInstance getInstance() {
return Hazelcast.getHazelcastInstanceByName("test");
}
效果很好。 HazelcastAutoconfiguration
不会 运行 因为它的条件是实例不存在。
我唯一担心的是,这在很大程度上依赖于以下事实:对于 Spring 版本 1.5.1 Boot,JCache 配置会创建此实例
在 HazelcastAutoconfiguration 启动之前。
更新
在优秀 Spring 引导社区的@snicoll 的帮助下,我找到了更好的解决方案。
只需明确告诉 Spring 引导使用哪个 hazelcast 配置并命名 Hazelcast 实例。将以下内容放入 application.properties
spring.hazelcast.config=hazelcast.xml
示例见:https://github.com/dirkvanrensburg/hazelcast-springboot-jcache/tree/fixed
看起来默认 Spring 启动自动配置将在使用 JCache 并启用缓存时创建两个 hazelcast 实例 (@EnableCaching
)
完整示例位于:https://github.com/dirkvanrensburg/hazelcast-springboot-jcache
TLDR; Is there a way to get Spring boot's autoconfiguration to only create one Hazelcast instance when enabling caching through JCache?
我通过添加以下依赖项创建了一个演示 Spring 引导项目:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
</dependency>
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast</artifactId>
</dependency>
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast-spring</artifactId>
<version>${hazelcast.version}</version>
</dependency>
并将 @EnableCaching
添加到应用程序 class,Spring 将自动配置 Hazelcast 但会启动两个 hazelcast 实例,它们加入了一个集群,如日志所示:
Members [2] {
Member [192.168.1.157]:5701 - 3eabbe90-6815-49ff-8d93-9e4b12e67810
Member [192.168.1.157]:5702 - e9c93366-2408-4726-965a-b21dcf897113 this
}
缓存有效,但我不想要两个 Hazelcast 实例。
破解
我通过提供自己的缓存管理器设法让它工作:
@Bean
public CacheManager springHzProvider(HazelcastInstance instance) {
return SpringHazelcastCachingProvider.getCacheManager(instance, null, new Properties());
}
并删除 hazelcast
和 hazelcast-spring
依赖项并添加 hazelcast-all
:
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast-all</artifactId>
<version>${hazelcast.version}</version>
</dependency>
但问题是是否有更好的 'proper' 方法来实现这一点?理想情况下无需定义自定义缓存管理器并添加 hazelcast-all
@dvanrensburg 根据评论,作为临时解决方案,从 auto-configuration 中排除 HazelcastAutoConfiguration
class。我已经记录了 Spring Boot https://github.com/spring-projects/spring-boot/issues/8275 的问题,因为我认为这是根本原因,如果 @EnableCaching
触发了第一个实例的创建,则不应创建第二个实例。
我在上面使用了 Neil 的解决方案,但是 运行 我无法自动装配由 JCache 配置创建的 Hazelcast 实例。看起来该实例是在 Spring 之外创建的,并已在应用程序上下文中注册。
在配置中为实例命名
<instance-name>test</instance-name>
然后添加一个显式挂钩以将实例引入上下文
@Bean
public HazelcastInstance getInstance() {
return Hazelcast.getHazelcastInstanceByName("test");
}
效果很好。 HazelcastAutoconfiguration
不会 运行 因为它的条件是实例不存在。
我唯一担心的是,这在很大程度上依赖于以下事实:对于 Spring 版本 1.5.1 Boot,JCache 配置会创建此实例 在 HazelcastAutoconfiguration 启动之前。
更新 在优秀 Spring 引导社区的@snicoll 的帮助下,我找到了更好的解决方案。
只需明确告诉 Spring 引导使用哪个 hazelcast 配置并命名 Hazelcast 实例。将以下内容放入 application.properties
spring.hazelcast.config=hazelcast.xml
示例见:https://github.com/dirkvanrensburg/hazelcast-springboot-jcache/tree/fixed