java - 如果缓存服务器失败,是否可以让应用程序忽略缓存?
问题描述
我有一个具有以下属性的弹簧启动应用程序:
spring.cache.type: redis
spring.redis.host: <hostname>
spring.redis.port: <hostport>
现在,如果远程主机出现故障,应用程序也会因连接错误而失败。在这种情况下,我的缓存不是我的应用程序的核心,但它仅用于性能,我希望 spring 简单地绕过它并转到数据库检索其数据。
我看到这可以通过定义一个自定义的 errorHandler 方法来实现,但为了做到这一点,我必须实现 CachingConfigurer bean……但这也迫使我重写每个方法(例如缓存管理器、缓存解析器、ecc. )。
@Configuration
public class CacheConfiguration implements CachingConfigurer{
@Override
public CacheManager cacheManager() {
// TODO Auto-generated method stub
return null;
}
@Override
public CacheResolver cacheResolver() {
// TODO Auto-generated method stub
return null;
}
...
@Override
public CacheErrorHandler errorHandler() {
// the only method I need, maybe
return null;
}
我想避免这种情况......我只需要一种方法来告诉spring“缓存崩溃了,但没关系:假装你根本没有缓存”
解决方案
@Phate - 绝对!我刚刚回答了一个相关问题(可能),使用 Apache Geode 或 Pivotal GemFire 作为具有 Spring 缓存抽象的 Spring Boot 应用程序中的缓存提供程序。
在那篇文章中,我没有完全禁用缓存,而是将 GemFire/Geode 切换为仅在本地模式下运行(GemFire/Geode 的可能配置)。但是,如果需要,可以应用相同的技术来完全禁用缓存。
本质上,在 Spring Boot 和 Spring 通常开始评估应用程序的配置之前,您需要一个预处理步骤。
在我的示例中,我实现了一个自定义 Spring Condition来检查集群(即服务器)的可用性。然后我将其应用于我Condition
的@Configuration
班级。
在 Spring Boot 的情况下,当 Spring Boot在应用程序的类路径上有效地看到(以及参见此处)Redis 和 Spring Data Redis时,它会为 Redis(作为存储和缓存提供程序)应用自动配置。因此,本质上,Redis 仅在“条件”为true时才作为缓存提供程序启用,主要是
您的应用程序配置声明了一个bean ,您的责任。RedisConnectionFactory
那么,这会是什么样子呢?
像我的 Apache Geode & Pivotal GemFire custom Spring Condition一样,您可以为 Redis 实现类似的 Condition,例如:
static RedisAvailableCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext,
AnnotatedTypeMetadata annotatedTypeMetadata) {
// Check the available of the Redis server, such as by opening a Socket
// connection to the server node.
// NOTE: There might be other, more reliable/robust means of checking
// the availability of a Redis server in the Redis community.
Socket redisServer;
try {
Environment environment = conditionContext.getEnvironment();
String host = environment.getProperty("spring.redis.host");
Integer port = environment.getProperty("spring.redis.port", Integer.class);
SocketAddress redisServerAddress = new InetSocketAddress(host, port);
redisServer = new Socket();
redisServer.connect(redisServerAddress);
return true;
}
catch (Throwable ignore) {
System.setProperty("spring.cache.type", "none");
return false;
}
finally {
// TODO: You need to implement this method yourself.
safeCloseSocket(redisServer);
}
}
}
此外,我还将 设置spring.cache.type
为NONE
,以确保在 Redis 不可用的情况下将缓存呈现为无操作。 在这里NONE
更详细地解释。
当然,您也可以使用备用缓存选项,使用其他一些缓存提供程序(例如简单的ConcurrentHashMap
,但我将其留给您作为练习)。向前...
然后,在定义了RedisConnectionFactory
bean 的 Spring Boot 应用程序配置类中(正如 Spring Boot 的自动配置所期望的那样),Condition
使用 Spring 的@Conditiional
注释添加这个自定义,如下所示:
@Confgiuration
@Conditional(RedisAvailableCondition.class);
class MyRedisConfiguration {
@Bean
RedisConnectionFactory redisConnectionFactory() {
// Construct and return new RedisConnectionFactory
}
}
这应该可以有效地处理 Redis 不可用的情况。
免责声明:我自己没有对此进行测试,但基于我的 Apache Geode/Pivotal GemFire 示例,该示例确实有效。因此,也许,通过一些调整,这将满足您的需求。它也应该给你一些想法。
希望这可以帮助!
干杯!
推荐阅读
- php - Laravel GroupBy 在预定命令中失败
- java - 为什么在 Jenkins 部署期间,JUnit 测试会在中午 12 点到下午 1 点之间失败?
- java - 如果 iCal Vevent 目前处于活动状态,是否有任何包、API 等可以返回布尔值?
- python - python中的棋盘功能
- scala - scala中是否存在非类型模板参数?
- python - 从生成的数据中对三个有偏见的硬币进行建模
- r - R在两个数据帧的列中找到字符串之间的重叠
- docusignapi - 如何获取应用程序磁贴?
- angular - 输入字段很脏并且仅在 IE11 (Angular8) 中显示红色边框验证
- android - 如何打开 Android 应用的 .APK 文件以更新底层代码?