背景: 最近、Yixin が開発した Springboot システムでストレス テストを行っていました。最初にストレス テストを開始したときは、Redis クラスターのデータに正常にアクセスできることがわかりました。しかし、数分間停止すると、その後、jmeter を使用してストレス テストを実行し続けたところ、Redis が突然異常なプロンプトを出し始めたことがわかりました: コマンドは 6 秒後にタイムアウトしました...
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 とメモリの使用率も 20% 未満でした。これをすべて見て、突然長い瞑想に陥ってしまいました。何が問題ですか? Baidu で検索した後、同様の状況を経験した人はたくさんいるようで、タイムアウト設定を変更する必要があると言う人もいました。設定を大きくすればうまくいきます。この解決策に従い、タイムアウト値をより大きな値に設定しましたが、タイムアウトの問題はまだ解決されていません。
このうち、springboot が redis を動作させるための依存関係パッケージは、——
1 <dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-data-redis</artifactId> 4 </dependency>
クラスター構成——
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 をクリックして、レタスの依存関係が含まれています:
springboot1.x はデフォルトで jedis を使用し、springboot2.x はデフォルトでレタスを使用します。 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 }
印刷出力——
测试打印驱动类型:org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory@74ee761e
レタス ドライバー接続が使用されていることがわかります。そこで、以前よく使われていた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 部分を入力できます。##
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 }
1 2 @Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class}) 3
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
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>
このように、RedisAutoConfiguration の import アノテーションを実行すると、lettuce の依存関係が見つからないため、このアノテーション @Import({ LettuceConnectionConfiguration.class (JedisConnectionConfiguration.class の 2 番目の位置にある JedisConnectionConfiguration)) が有効になり、SpringBoot が Redis を操作するためのドライバーとしてコンテナーに登録できるようになりました。
レタスとジェディスの違いは何ですか?
lettuce: 最下層は netty で実装されており、スレッドセーフであり、デフォルトではインスタンスが 1 つだけあります。 jedis: Redis サーバーに直接接続し、接続プールと併用して物理接続を増やすことができます。 次のコードの例外プロンプト lettuceConverters.toBoolean(this.getConnection().zadd(key,score,value)) に従ってエラー メソッドを見つけます——1 <dependency> 2 <groupId>redis.clients</groupId> 3 <artifactId>jedis</artifactId> 4 </dependency>
LettuceConverters.toBoolean() は、long を Boolean に変換します。通常の状況では、追加が成功した場合、this.getConnection().zadd(key,score,value) は 1 を返すため、LettuceConverters.toBoolean(1) は true を取得し、それ以外の場合は、新しい追加が失敗した場合、0 が返されます (LettuceConverters.toBoolean(0))。3 番目のケース、つまり this.getConnection().zaadd(key,score,value) メソッドで例外が発生する場合もあります。え? 例外が発生するとどうなりますか?
接続接続に失敗した場合のはずです。
以上がSpringboot2.x がレタスを統合し、Redis クラスターに接続するときにタイムアウト例外を解決する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。