如何解决FF4J:功能存储的服务器端缓存
我使用 ff4j-spring-boot-starter
和 f4j-store-springjdbc
来设置我的 ff4j 服务器。我所有的其他微服务都使用 ff4j 提供的端点来访问此功能存储,并以 JSON 格式返回响应。
由于数据不会经常更改,并且我们正在尝试保存不必要的数据库调用,因此我正在尝试将我的功能存储缓存在服务器上。此外,如果功能标志 DB 关闭(用于刷新/维护),我们仍然希望其他服务能够使用缓存中的这些值成功启动。
我们在 pom.xml 中导入了 ff4j-store-ehcache
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.RC2</spring-cloud.version>
<ff4j.version>1.8.7</ff4j.version>
<odbc.version>19.6.0.0.0</odbc.version>
</properties>
<dependency>
<groupId>org.ff4j</groupId>
<artifactId>ff4j-spring-boot-starter</artifactId>
<version>${ff4j.version}</version>
</dependency>
<dependency>
<groupId>org.ff4j</groupId>
<artifactId>ff4j-store-springjdbc</artifactId>
<version>${ff4j.version}</version>
</dependency>
<dependency>
<groupId>org.ff4j</groupId>
<artifactId>ff4j-web</artifactId>
<version>${ff4j.version}</version>
</dependency>
<dependency>
<groupId>org.ff4j</groupId>
<artifactId>ff4j-store-ehcache</artifactId>
<version>${ff4j.version}</version>
</dependency>
<dependency>
<groupId>org.ff4j</groupId>
<artifactId>ff4j-webapi-jersey2x</artifactId>
<version>1.8.11</version>
</dependency>
<!-- ff4j dependencies - end -->
我们的 FeatureCacheProviderEhCache 实现在 ff4jConfig.java 中看起来像这样。
@ConditionalOnClass({ ConsoleServlet.class,ff4jdispatcherServlet.class })
public class ff4jConfig extends SpringBootServletinitializer {
@Autowired
private DataSource dataSource;
@Bean
public ServletRegistrationBean<ff4jdispatcherServlet> ff4jdispatcherServletRegistrationBean(
ff4jdispatcherServlet ff4jdispatcherServlet) {
ServletRegistrationBean<ff4jdispatcherServlet> bean = new ServletRegistrationBean<ff4jdispatcherServlet>(
ff4jdispatcherServlet,"/web-console/*");
bean.setName("ff4j-console");
bean.setLoadOnStartup(1);
return bean;
}
@Bean
@ConditionalOnMissingBean
public ff4jdispatcherServlet getff4jdispatcherServlet() {
ff4jdispatcherServlet ff4jConsoleServlet = new ff4jdispatcherServlet();
ff4jConsoleServlet.setff4j(getff4j());
return ff4jConsoleServlet;
}
@Bean
public ff4j getff4j() {
ff4j ff4j = new ff4j();
FF4jcacheManager cacheManager = new FeatureCacheProviderEhCache();
ff4j.setPropertiesstore(new PropertyStoreSpringJdbc(dataSource));
ff4j.setFeatureStore(new FeatureStoreSpringJdbc(dataSource));
ff4j.setEventRepository(new EventRepositorySpringJdbc(dataSource));
ff4j.cache(cacheManager);
// Enable audit mode
ff4j.audit(true);
return ff4j;
}
}
WebConsole 会在提交后立即反映数据库更改,并且似乎没有命中缓存或缓存正在其中存储任何数据。
我希望能够使用这个缓存,而无需每次查找都去数据库。
我们还尝试使用 InMemoryCacheManager 作为 FeatureCacheProviderEhCache 的替代,但结果相同。在这两种实现中,我们确实在网络控制台上看到了清除缓存按钮。
另外,有没有更好的方法来测试我的 api 调用是否实际上是从缓存而不是从数据库获取数据,而不必关闭数据库?
更新:
在实现我们自己的 FeatureCacheProviderEhCache 并登录后,
我试图访问 api/ff4j 并且 featureNames
在该响应中以空的形式出现。
请参考日志:
METHOD=getCacheFeatures,LINENO=160,MSG=getCacheFeatures :: [ name = ff4jcacheFeatures status = STATUS_ALIVE eternal = false overflowTodisk = true maxEntriesLocalHeap = 10000 maxEntriesLocaldisk = 10000000 memoryStoreevictionPolicy = LRU timetoLiveSeconds = 120 timetoIdleSeconds = 120 persistence = LOCALTEMPSWAP diskExpiryThreadIntervalSeconds = 120 cacheEventListeners: ; orderedCacheEventListeners: maxBytesLocalHeap = 0 overflowToOffheap = false maxBytesLocalOffheap = 0 maxBytesLocaldisk = 0 pinned = false ]
METHOD=listCachedFeatureNames,LINENO=59,MSG=listCachedFeatureNames[]
METHOD=getCacheFeatures,MSG=getCacheFeatures :: [ name = ff4jcacheFeatures status = STATUS_ALIVE eternal = false overflowTodisk = true maxEntriesLocalHeap = 10000 maxEntriesLocaldisk = 10000000 memoryStoreevictionPolicy = LRU timetoLiveSeconds = 120 timetoIdleSeconds = 120 persistence = LOCALTEMPSWAP diskExpiryThreadIntervalSeconds = 120 cacheEventListeners: ; orderedCacheEventListeners: maxBytesLocalHeap = 0 overflowToOffheap = false maxBytesLocalOffheap = 0 maxBytesLocaldisk = 0 pinned = false ]
缓存已创建,但未在其中存储任何值。我正在按照第一个答案中所说的方式设置缓存。
我的日志,当我打印 listCachedFeatures() 时,它也打印为空。
我仍然无法在缓存中看到 featureNames
。这部分我不是正确配置?
解决方法
首先我想确认您正确使用缓存。 ff4j.cache(cacheManager)
是您想要做的。这就是正在发生的事情:
public FF4j cache(FF4JCacheManager cm) {
FF4jCacheProxy cp = new FF4jCacheProxy(getFeatureStore(),getPropertiesStore(),cm);
setFeatureStore(cp);
setPropertiesStore(cp);
return this;
}
-
当您通过网络控制台编辑功能或属性值时,
FF4j
知道需要清除缓存并立即更新数据库,(缓存将仅用于读取)。 -
FeatureCacheProviderEhCache
和InMemoryCacheManager
的工作方式相同。第一次使用JSR107。看个人喜好了,也许以后用ehcache可以改用Terracotta这样的分布式缓存。 -
如何知道只使用缓存而不使用数据库(读取时)?您可以使用 AOP 创建通知来装饰类
FeatureCacheProviderEhCache
或更基本的您在项目中复制 the class,使用适当的日志更新方法并将您的类用作 CacheManager。 -
您也可以考虑在您的微服务级别使用缓存(如果用 Java 实现),而不仅仅是在 Web 控制台中。如果这样做,您可以通过不执行 REST 调用来获取 JSON 来节省一些时间。
-
EhCache 和 InMemory 缓存按照内存中的名称工作,这意味着 2 个微服务在缓存中可能具有不同的值。如果您希望在微服务之间实现一致的缓存(非强制性),您希望使用分布式缓存,如 REDIS 或 HAZELCAST。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。