我有一个具有以下属性的spring boot应用程序:
spring.cache.type: redis
spring.redis.host: <hostname>
spring.redis.port: <hostport>
现在,如果远程主机失败,则应用程序也会失败,并出现连接错误。 由于在这种情况下,我的缓存不是应用程序的核心,而是仅用于性能,我希望Spring可以简单地绕过缓存并转到数据库以检索其数据。
我看到可以通过定义一个自定义的errorHandler方法来实现,但是为此,我必须实现CachingConfigurer bean ...但是这也迫使我重写每个方法(例如,缓存管理器,缓存解析器) ,等等)。
@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“缓存崩溃了,但是还可以:假装根本没有缓存”
答案 0 :(得分:1)
在任何高速缓存发生故障的情况下,我们可以使用Circuit Breaker实现的任何一种将数据库用作后备选项。使用断路器模式的好处是,一旦缓存启动,请求将自动路由回缓存,因此切换可以无缝进行。
您还可以配置要回退到数据库之前要重试的次数,以及检查缓存是否在线备份的频率。
Spring云为hystrix和Resilience4j断路器实现提供了开箱即用的支持,并且易于与spring boot应用程序集成。
https://spring.io/projects/spring-cloud-circuitbreaker
https://resilience4j.readme.io/docs/circuitbreaker
答案 1 :(得分:0)
@Phate-绝对!我刚刚回答了related question(可能),使用Apache Geode或Pivotal GemFire作为带有Spring的Cache Abstraction的Spring Boot应用程序中的缓存提供程序。
在该发布中,我没有完全禁用缓存,而是将GemFire / Geode切换为仅在本地模式下运行(可能是GemFire / Geode的配置)。但是,如果需要的话,可以使用相同的技术完全禁用缓存。
从本质上讲,在Spring Boot和Spring通常开始评估应用程序的配置之前,您需要一个预处理步骤。
在我的示例中,我实现了custom Spring Condition,用于检查集群(即服务器)的可用性。然后,我将Condition
的{{1}} @Configuration
转到我的RedisConnectionFactory
类。
对于Spring Boot,当Spring Boot有效地applied(以及auto-configuration)Redis和Spring时,它对Redis(作为存储和缓存提供程序)应用sees数据Redis位于应用程序的类路径中。因此,从本质上讲,仅在“条件”为 true 时才将Redis启用为缓存提供程序,主要是
根据您的应用程序配置和职责,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);
}
}
}
bean是sees here。
那么,这会是什么样?
就像我的Apache Geode和Pivotal GemFire declared一样,您可以为Redis实现类似的条件,例如:
spring.cache.type
此外,我还将NON
设置为NONE
,以确保在Redis不可用的情况下将缓存呈现为无操作。 custom Spring Condition会详细说明ConcurrentHashMap
。
当然,您还可以使用后备缓存选项,以及其他一些缓存提供程序(例如简单的RedisConnectionFactory
,但我将其留给您练习)。向前...
然后,在定义了Condition
bean(在Spring Boot的自动配置中已定义)的Spring Boot应用程序配置类中,使用Spring的@Conditiional
添加此自定义@Confgiuration
@Conditional(RedisAvailableCondition.class);
class MyRedisConfiguration {
@Bean
RedisConnectionFactory redisConnectionFactory() {
// Construct and return new RedisConnectionFactory
}
}
注释,就像这样:
app.post('/users/login', function (req, res) {
var email = req.body.email;
var password = req.body.password;
var form = {
email,
password
}
request.post({
url: "https://website.com/users/login",
body: form,
json: true
}, function (error, response, body) {
console.log('error:', error)
console.log('body:', body.errmsg);
console.log(body);
if (body.user) {
let auth = body.token
console.log(auth) //I want to pass this auth to /logout
} else {
res.render('login', {
email,
password
})
}
})
这应该有效地处理Redis不可用的情况。
免责声明:我自己并未对此进行测试,但是基于有效的Apache Geode / Pivotal GemFire示例。因此,也许可以通过一些调整来满足您的需求。它还应该有助于给您一些想法。
希望这会有所帮助!
干杯!
答案 2 :(得分:0)
我必须实现 CachingConfigurer bean...但这也强制 我覆盖每个方法(例如缓存管理器,缓存 解析器,ecc。)
取而代之的是,您可以简单地扩展 frame
并仅覆盖 CachingConfigurerSupport
方法,返回一个自定义 errorHandler()
,其方法实现是无操作的。见https://stackoverflow.com/a/68072419/1527469