解決引入Redisson可能會(huì)出現(xiàn)項(xiàng)目啟動(dòng)失敗的問(wèn)題
問(wèn)題1
需要注意Redisson版本和spring-boot版本一致,我使用的是spring-boot 2.1.3 對(duì)應(yīng)的Redisson 3.9.1不然會(huì)報(bào)錯(cuò)
java.lang.NoClassDefFoundError: org/springframework/data/redis/connection/RedisStreamCommands
at org.redisson.spring.data.connection.RedissonConnectionFactory.getConnection(RedissonConnectionFactory.java:111)
at org.springframework.data.redis.core.RedisConnectionUtils.doGetConnection(RedisConnectionUtils.java:132)
at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:95)
at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:82)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:211)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:184)
at org.springframework.data.redis.core.RedisTemplate.hasKey(RedisTemplate.java:769)
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.9.1</version>
</dependency>問(wèn)題2
Redisson自己會(huì)啟動(dòng)一個(gè)Redisson連接池,嘗試連接redis,項(xiàng)目啟動(dòng)的時(shí)候就會(huì)連接,這時(shí)候如果k8s初始化的pod節(jié)點(diǎn)網(wǎng)絡(luò)不通可能會(huì)出現(xiàn)問(wèn)題,因?yàn)閞edis連接不上(說(shuō)是我們的是海外服務(wù)器的原因,網(wǎng)絡(luò)不穩(wěn)定),項(xiàng)目報(bào)錯(cuò),導(dǎo)致起不起來(lái),然后pod會(huì)一直重啟,因?yàn)檫\(yùn)維層次不了解他們?cè)O(shè)置的k8s原理,需要在短時(shí)間解決,提供了下面的方案解決,后來(lái)也沒(méi)有再出現(xiàn)這個(gè)問(wèn)題,啟動(dòng)報(bào)錯(cuò)
1)自己重新空實(shí)現(xiàn)了一個(gè)RedissonClient
/**
* @ClassName RedissonClientTemporary
* @Decription 只是在初始化時(shí)候使用一下,之后就會(huì)被替換
*/
public class RedissonClientTemporary implements RedissonClient{
}2)然后將這個(gè)空實(shí)現(xiàn)注入到spring容器
為了給其它使用到RedissonClient,作為屬性初始化時(shí)候不報(bào)錯(cuò)
@Configuration
public class RedissonConfig {
/**
* 配置一個(gè)臨時(shí)的對(duì)象到spring容器中,不使用
* @return 一個(gè)RedissonClient的實(shí)現(xiàn)
*/
@Bean
public RedissonClient redissonClient() {
RedissonClient redissonClient = new RedissonClientTemporary();
return redissonClient;
}
}?????3)項(xiàng)目啟動(dòng)完成使用一個(gè)監(jiān)聽(tīng)事件
放入Redisson替換RedissonClient的實(shí)現(xiàn),然后初始化一下,這里可能還是會(huì)連接報(bào)錯(cuò)但是不影響,因?yàn)橐呀?jīng)放入了spring容器,如果這里連接失敗,他也就不會(huì)再次嘗試連接了,直到你再次使用它時(shí)候才會(huì)再次調(diào)用創(chuàng)建連接(那會(huì)redis就已經(jīng)可用,其實(shí)redis還不可用,我們使用降級(jí)策略也可以,那會(huì)使用本地緩存或者數(shù)據(jù)庫(kù)等)
/**
* @ClassName ApplicationLoadRedissonListener
* @Decription 項(xiàng)目啟動(dòng)完成,增加一個(gè)監(jiān)聽(tīng)器,替換spring容器里面的redissonClient的對(duì)象,進(jìn)行切換成redisson
*/
@Component
public class ApplicationLoadRedissonListener implements ApplicationListener<ApplicationReadyEvent> {
private static final Logger log = LoggerFactory.getLogger(ApplicationLoadRedissonListener.class);
@Autowired
ConfigurableApplicationContext configurableApplicationContext;
@Autowired
private RedisProperties redisProperties;
@Value("${spring.redis.redisson.singleServerConfig.subscriptionsPerConnection}")
private Integer subscriptionsPerConnection;
@Value("${spring.redis.redisson.singleServerConfig.connectionPoolSize}")
private Integer connectionPoolSize;
@Value("${spring.redis.redisson.singleServerConfig.connectionMinimumIdleSize}")
private Integer connectionMinimumIdleSize;
@Value("${spring.redis.redisson.singleServerConfig.subscriptionConnectionPoolSize}")
private Integer subscriptionConnectionPoolSize;
@Value("${spring.redis.redisson.singleServerConfig.subscriptionConnectionMinimumIdleSize}")
private Integer subscriptionConnectionMinimumIdleSize;
@Override
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
try{
//加載一些基本的redis基礎(chǔ)配置
Config config = new Config();
String address = "redis://" + redisProperties.getHost() + ":" + redisProperties.getPort();
SingleServerConfig serverConfig = config.useSingleServer();
serverConfig.setAddress(address);
serverConfig.setDatabase(redisProperties.getDatabase());
if (!StringUtils.isEmpty(redisProperties.getPassword())) {
serverConfig.setPassword(redisProperties.getPassword());
}
serverConfig.setTimeout((int)redisProperties.getTimeout().toMillis());
//加載redisson一些特殊配置
serverConfig.setConnectionPoolSize(connectionPoolSize);
serverConfig.setConnectionMinimumIdleSize(connectionMinimumIdleSize);
serverConfig.setSubscriptionConnectionMinimumIdleSize(subscriptionConnectionMinimumIdleSize);
serverConfig.setSubscriptionConnectionPoolSize(subscriptionConnectionPoolSize);
serverConfig.setSubscriptionsPerConnection(subscriptionsPerConnection);
log.info("加載 redisson配置信息 {}", JsonUtil.of(serverConfig));
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(Redisson.class);
beanDefinitionBuilder.addConstructorArgValue(config);
String redissonClientName = RedissonClient.class.getSimpleName().substring(0,1).toLowerCase() + RedissonClient.class.getSimpleName().substring(1);
Object redissonClient = configurableApplicationContext.getBean(redissonClientName);
log.info("初次放入的redissonClient實(shí)現(xiàn)對(duì)象:{}", redissonClient.getClass().getName());;
//創(chuàng)建一個(gè)Redisson對(duì)象
BeanDefinitionRegistry beanDefinitionRegistry = (BeanDefinitionRegistry) configurableApplicationContext;
beanDefinitionRegistry.registerBeanDefinition(redissonClientName, beanDefinitionBuilder.getBeanDefinition());
//這里相當(dāng)于初始化加載使用
redissonClient = configurableApplicationContext.getBean(redissonClientName);
log.info("最終放入的redissonClient實(shí)現(xiàn)對(duì)象:{}", redissonClient.getClass().getName());
}catch (Exception e){
log.info("ApplicationLoadRedissonListener/onApplicationEvent/RedissonClient/Exception:[{}]", e.getMessage());
}
}
}# redisson 連接配置 # 單個(gè)連接最大訂閱數(shù)量 spring.redis.redisson.singleServerConfig.subscriptionsPerConnection=5 # 連接池大小 spring.redis.redisson.singleServerConfig.connectionPoolSize=8 # 最小空閑連接數(shù) spring.redis.redisson.singleServerConfig.connectionMinimumIdleSize=4 # 發(fā)布和訂閱連接池大小 spring.redis.redisson.singleServerConfig.subscriptionConnectionPoolSize=8 # 發(fā)布和訂閱連接的最小空閑連接數(shù) spring.redis.redisson.singleServerConfig.subscriptionConnectionMinimumIdleSize=1
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java外部類(lèi)與內(nèi)部類(lèi)的關(guān)系詳解
本文詳細(xì)講解了java外部類(lèi)與內(nèi)部類(lèi)的關(guān)系,用代碼演示了外部類(lèi)調(diào)用內(nèi)部類(lèi)的方法。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-12-12
帶你輕松搞定Java面向?qū)ο蟮木幊?-數(shù)組,集合框架
Java是面向?qū)ο蟮母呒?jí)編程語(yǔ)言,類(lèi)和對(duì)象是 Java程序的構(gòu)成核心。圍繞著Java類(lèi)和Java對(duì)象,有三大基本特性:封裝是Java 類(lèi)的編寫(xiě)規(guī)范、繼承是類(lèi)與類(lèi)之間聯(lián)系的一種形式、而多態(tài)為系統(tǒng)組件或模塊之間解耦提供了解決方案2021-06-06
淺談SpringBoot集成Quartz動(dòng)態(tài)定時(shí)任務(wù)
這篇文章主要介紹了SpringBoot集成Quartz動(dòng)態(tài)定時(shí)任務(wù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
基于Java實(shí)現(xiàn)遍歷文件目錄并去除中文文件名
這篇文章主要為大家詳細(xì)介紹了如何使用Java實(shí)現(xiàn)遍歷文件目錄并去除中文文件名,文中的示例代碼講解詳細(xì),有需要的小伙伴可以參考一下2024-03-03
如何解決SpringBoot 加入AOP后無(wú)法注入的問(wèn)題
這篇文章主要介紹了如何解決SpringBoot 加入AOP后無(wú)法注入的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
使用BufferedReader讀取TXT文件中數(shù)值,并輸出最大值
這篇文章主要介紹了使用BufferedReader讀取TXT文件中數(shù)值,并輸出最大值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
spring bean標(biāo)簽的primary屬性用法講解
這篇文章主要介紹了spring bean標(biāo)簽的primary屬性用法講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09

