>  기사  >  데이터 베이스  >  Springboot2.x가 양상추를 통합하고 Redis 클러스터에 연결할 때 시간 초과 예외를 해결하는 방법

Springboot2.x가 양상추를 통합하고 Redis 클러스터에 연결할 때 시간 초과 예외를 해결하는 방법

PHPz
PHPz앞으로
2023-05-27 19:43:051884검색

배경: 최근 새로 개발된 Springboot 시스템에서 스트레스 테스트를 하던 중 처음 스트레스 테스트를 시작했을 때 정상적으로 Redis 클러스터의 데이터에 액세스할 수 있다는 것을 발견했습니다. 계속해서 jmeter를 사용하여 스트레스 테스트를 수행했는데, redis가 실패했다는 것을 발견했습니다. 갑자기 미친 듯이 비정상적인 메시지가 나타났습니다: Command timed out after 6 second(s)...

  1 Caused by: io.lettuce.core.RedisCommandTimeoutException: Command timed out after 6 second(s)  2     at io.lettuce.core.ExceptionFactory.createTimeoutException(ExceptionFactory.java:51)  3     at io.lettuce.core.LettuceFutures.awaitOrCancel(LettuceFutures.java:114)  4     at io.lettuce.core.cluster.ClusterFutureSyncInvocationHandler.handleInvocation(ClusterFutureSyncInvocationHandler.java:123)  5     at io.lettuce.core.internal.AbstractInvocationHandler.invoke(AbstractInvocationHandler.java:80)  6     at com.sun.proxy.$Proxy134.mget(Unknown Source)  7     at org.springframework.data.redis.connection.lettuce.LettuceStringCommands.mGet(LettuceStringCommands.java:119)  8     ... 15 common frames omitted

급히 Redis 클러스터를 확인하여 발견했습니다. 클러스터에 있는 모든 노드는 정상이고, CPU와 메모리 사용량은 100% 미만이라는 것을 스물, 이것저것 보다가 문득 뭐가 문제인지 고민에 빠졌습니다... 바이두에서 검색해보니, 많은 사람들이 비슷한 상황을 경험한 것을 발견했습니다. 어떤 사람들은 시간 초과를 더 큰 값으로 설정하면 문제가 해결될 수 있다고 말했습니다. 이 해결 방법에 따라 시간 초과 값을 더 큰 값으로 설정했지만 시간 초과 문제는 여전히 해결되지 않았습니다.

그 중 springboot가 Redis를 운영하기 위한 의존성 패키지는——

  1 <dependency>  2     <groupId>org.springframework.boot</groupId>  3     <artifactId>spring-boot-starter-data-redis</artifactId>  4 </dependency>

Cluster 구성——

  1 redis:  2   timeout: 6000ms  3   cluster:  4     nodes:  5       - xxx.xxx.x.xxx:6379  6       - xxx.xxx.x.xxx:6379  7       - xxx.xxx.x.xxx:6379  8   jedis:  9     pool: 10       max-active: 1000 11       max-idle: 10 12       min-idle: 5 13       max-wait: -1

spring-boot-starter-data-redis를 클릭하고 lettuce의 의존성이 포함되어 있는지 확인하세요.

Springboot2.x가 양상추를 통합하고 Redis 클러스터에 연결할 때 시간 초과 예외를 해결하는 방법

springboot1 .x는 기본적으로 jedis를 사용하고, Springboot2.x는 기본적으로 lettuce를 사용합니다. Redis 드라이버 로딩 구성 클래스에서 RedisConnectionFactory 정보를 출력하는 것을 간단하게 확인할 수 있습니다:

  1 @Configuration  2 @AutoConfigureAfter(RedisAutoConfiguration.class)  3 public class Configuration {  4     @Bean  5     public StringRedisTemplate redisTemplate(RedisConnectionFactory factory) {  6         log.info("测试打印驱动类型:"+factory);  7 }

Print 출력 -

测试打印驱动类型:org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory@74ee761e

여기서는 lettuce 드라이버 연결이 사용되는 것을 볼 수 있으므로 이전 연결로 교체할 때 더 많은 jedis 드라이버가 연결되면 이 명령은 6초 후에 시간 초과 문제가 더 이상 발생하지 않습니다.

  1 <dependency>  2     <groupId>org.springframework.boot</groupId>  3     <artifactId>spring-boot-starter-data-redis</artifactId>  4     <exclusions>  5         <exclusion>  6             <groupId>io.lettuce</groupId>  7             <artifactId>lettuce-core</artifactId>  8         </exclusion>  9     </exclusions> 10 </dependency> 11 <dependency> 12     <groupId>redis.clients</groupId> 13     <artifactId>jedis</artifactId> 14 </dependency>

그럼 질문은 Springboot2.x가 어떻게 기본적으로 상추를 사용하는가 하는 것입니다. 내부 코드 중 일부를 연구해야 합니다. Springboot2의 redis 부분을 입력할 수 있습니다. 이는 spring-boot-starter-data-redis 종속성을 사용할 때 논리적으로 말하면 두 개의 드라이버가 동시에 자동으로 임포트될 수 없음을 의미합니다. , 별로 의미가 없습니다. 따라서 여기의 순서는 매우 중요합니다. 왜 그렇게 말합니까?

LettuceConnectionConfiguration.class 및 JedisConnectionConfiguration.class를 각각 입력하면 각각 이 기사에 필요한 핵심 코드가 표시됩니다.

  1 @Configuration(  2     proxyBeanMethods = false  3 )  4 @ConditionalOnClass({RedisOperations.class})  5 @EnableConfigurationProperties({RedisProperties.class})  6 @Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})  7 public class RedisAutoConfiguration {  8     public RedisAutoConfiguration() {  9    } 10    ......省略 11 }

LettuceConnectionConfiguration.class와 JedisConnectionConfiguration.class 모두 동일한 주석 @ConditionalOnMissingBean({RedisConnectionFactory.class)을 갖고 있음을 알 수 있습니다. }) 이는 RedisConnectionFactory Bean이 컨테이너에 등록된 경우 이와 유사한 다른 Bean은 로드 및 등록되지 않음을 의미합니다. 간단히 말하면 @ConditionalOnMissingBean({RedisConnectionFactory.class}) 주석 중 하나만 추가하면 됩니다. 두 개는 컨테이너에 로드 및 등록될 수 있으며, 다른 하나는 다시 로드 및 등록되지 않습니다.

그렇다면 누가 먼저 등록할 것인가 하는 질문이 생깁니다.

위 문장으로 돌아가서, @Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class}) 문장의 순서가 중요합니다. 이는 LettuceConnectionConfiguration이 등록된다는 의미입니다.

Springboot는 기본적으로 Redis에 연결하기 위해 lettuce를 사용하는 것을 볼 수 있습니다.

spring-boot-starter-data-redis 종속성 패키지를 도입하면 실제로는 lettuce 패키지를 도입하는 것과 같습니다. 이때 기본 lettuce 드라이버를 사용하지 않으려면 lettuce 드라이버가 사용됩니다. , 양상추 종속성을 직접 제외할 수 있습니다.

  1   2 @Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})  3

그런 다음 jedis 종속성을 도입합니다.——

  1 //LettuceConnectionConfiguration  2 @ConditionalOnClass({RedisClient.class})  3 class LettuceConnectionConfiguration extends RedisConnectionConfiguration {  4    ......省略  5     @Bean  6     @ConditionalOnMissingBean({RedisConnectionFactory.class})  7     LettuceConnectionFactory redisConnectionFactory(ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers, ClientResources clientResources) throws UnknownHostException {  8         LettuceClientConfiguration clientConfig = this.getLettuceClientConfiguration(builderCustomizers, clientResources, this.getProperties().getLettuce().getPool());  9         return this.createLettuceConnectionFactory(clientConfig); 10    } 11 } 12 //JedisConnectionConfiguration 13 @ConditionalOnClass({GenericObjectPool.class, JedisConnection.class, Jedis.class}) 14 class JedisConnectionConfiguration extends RedisConnectionConfiguration { 15    ......省略 16     @Bean 17     @ConditionalOnMissingBean({RedisConnectionFactory.class}) 18     JedisConnectionFactory redisConnectionFactory(ObjectProvider<JedisClientConfigurationBuilderCustomizer> builderCustomizers) throws UnknownHostException { 19         return this.createJedisConnectionFactory(builderCustomizers); 20    } 21 } 22

이런 방식으로 RedisAutoConfiguration의 가져오기 주석을 만들 때 양상추 종속성을 찾을 수 없기 때문에 이 주석 @Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})는 다음과 같습니다. 두 번째 위치의 JedisConnectionConfiguration은 유효하며 redis를 작동하기 위한 springboot용 드라이버로 컨테이너에 등록될 수 있습니다.

상추와 제디스의 차이점은 무엇인가요? lettuce: 맨 아래 레이어는 스레드로부터 안전한 netty로 구현되며 기본적으로 인스턴스가 하나만 있습니다.

jedis: Redis 서버에 직접 연결하고 연결 풀과 함께 사용하여 물리적 연결을 늘릴 수 있습니다.

예외 프롬프트에 따라 오류 메서드를 찾으세요. 다음 코드에서 LettuceConverters.toBoolean(this.getConnection().zadd(key, Score, value))——

  1 <dependency>  2     <groupId>org.springframework.boot</groupId>  3     <artifactId>spring-boot-starter-data-redis</artifactId>  4     <exclusions>  5         <exclusion>  6             <groupId>io.lettuce</groupId>  7             <artifactId>lettuce-core</artifactId>  8         </exclusion>  9     </exclusions> 10 </dependency>

LettuceConverters.toBoolean()을 변환하는 것입니다. long 부울입니다. 일반적인 상황에서는 추가가 성공하면 this.getConnection().zadd(key, Score, value)가 1을 반환하므로 반대로 추가가 성공하면 LettuceConverters.toBoolean(1)이 true가 됩니다. 실패하면 0, 즉 LettuceConverters.toBoolean(0)을 반환하고 세 번째 경우, 즉 this.getConnection().zadd(key, Score, value) 메서드에서 예외가 발생하는 경우가 있습니다. 예외가 발생할까요?

연결이 실패했을 때 입니다.

위 내용은 Springboot2.x가 양상추를 통합하고 Redis 클러스터에 연결할 때 시간 초과 예외를 해결하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제