Heim  >  Artikel  >  Datenbank  >  So lösen Sie die Timeout-Ausnahme, wenn Springboot2.x Salat integriert und eine Verbindung zum Redis-Cluster herstellt

So lösen Sie die Timeout-Ausnahme, wenn Springboot2.x Salat integriert und eine Verbindung zum Redis-Cluster herstellt

PHPz
PHPznach vorne
2023-05-27 19:43:051888Durchsuche

Hintergrund: Ich habe kürzlich einen Stresstest auf einem neu entwickelten Springboot-System durchgeführt. Als ich den Stresstest zum ersten Mal startete, konnte ich jedoch nach ein paar Minuten Pause normal darauf zugreifen Ich habe jmeter weiterhin verwendet, um den Stresstest durchzuführen. Plötzlich tauchte wie verrückt eine ungewöhnliche Meldung auf: Befehl ist nach 6 Sekunden abgelaufen ...

  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

Ich habe eilig den Redis-Cluster überprüft und festgestellt dass alle Knoten im Cluster normal waren und die CPU- und Speicherauslastung weniger als 100 % betrug. Als ich mir das alles ansah, geriet ich plötzlich in eine lange Überlegung, was genau das Problem ist ... Nach der Suche auf Baidu, Ich habe festgestellt, dass viele Leute ähnliche Situationen erlebt haben. Einige Leute sagten, dass das Setzen des Timeouts auf einen größeren Wert das Problem lösen kann. Ich habe diese Lösung befolgt und den Timeout-Wert auf einen größeren Wert gesetzt, aber das Timeout-Problem wurde immer noch nicht gelöst.

Unter diesen ist das Abhängigkeitspaket für Springboot zum Betrieb von Redis –

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

Cluster-Konfiguration – –

  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

Klicken Sie auf Spring-Boot-Starter-Data-Redis und stellen Sie fest, dass es die Abhängigkeit von Salat enthält:

So lösen Sie die Timeout-Ausnahme, wenn Springboot2.x Salat integriert und eine Verbindung zum Redis-Cluster herstellt

springboot1 .x verwendet standardmäßig jedis und Springboot2.x verwendet standardmäßig Salat. Wir können einfach überprüfen, ob in der Redis-Treiberladekonfigurationsklasse die RedisConnectionFactory-Informationen ausgegeben werden:

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

Druckausgabe -

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

Es ist ersichtlich, dass hier die Salattreiberverbindung verwendet wird, also beim Ersetzen durch die vorherige Wenn Wenn mehr Jedis-Treiber angeschlossen sind, ist dieser Befehl nach 6 Sekunden abgelaufen. Das Problem tritt nicht mehr auf.

  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>

Dann ist die Frage, wie Springboot2.x standardmäßig Salat verwendet. Wir müssen einen Teil des darin enthaltenen Codes studieren. Wir können den Redis-Teil von Springboot2 eingeben. Dies bedeutet, dass bei Verwendung der Spring-Boot-Starter-Data-Redis-Abhängigkeit sowohl Salat- als auch Jedis-Treiber automatisch importiert werden können , was wenig Sinn ergibt. Daher ist die Reihenfolge hier sehr wichtig. Warum sagen Sie das?

Geben Sie LettuceConnectionConfiguration.class bzw. JedisConnectionConfiguration.class ein und jeder zeigt den für diesen Artikel erforderlichen Kerncode an:

  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 }

Es ist ersichtlich, dass LettuceConnectionConfiguration.class und JedisConnectionConfiguration.class dieselbe Annotation haben @ConditionalOnMissingBean({RedisConnectionFactory.class } ), bedeutet dies, dass, wenn die RedisConnectionFactory-Bean im Container registriert wurde, andere ähnliche Beans nicht mehr geladen und registriert werden. Einfach ausgedrückt: Fügen Sie die Annotation @ConditionalOnMissingBean({RedisConnectionFactory. class}) hinzu, nur eine davon Zwei können in den Container geladen und registriert werden, der andere wird nicht erneut geladen und registriert.

Dann stellt sich die Frage: Wer wird zuerst registriert?

Dies geht auf den oben genannten Satz zurück, die Reihenfolge im Satz @Import({LettuceConnectionConfiguration.class}) ist entscheidend, was bedeutet, dass LettuceConnectionConfiguration registriert wird.

Es ist ersichtlich, dass Springboot standardmäßig Salat verwendet, um eine Verbindung zu Redis herzustellen.

Wenn wir das Spring-Boot-Starter-Data-Redis-Abhängigkeitspaket einführen, entspricht dies tatsächlich der Einführung des Salatpakets. Zu diesem Zeitpunkt wird der Salattreiber verwendet. Wenn Sie nicht den Standardsalattreiber verwenden möchten , können Sie die Salatabhängigkeit direkt ausschließen.

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

Führen Sie dann die Jedis-Abhängigkeit ein –

  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

Auf diese Weise wird beim Erstellen der Importanmerkung von RedisAutoConfiguration diese Annotation @Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class}) verwendet, da die Salatabhängigkeit nicht gefunden wird die zweite Die JedisConnectionConfiguration am Standort ist gültig und kann im Container als Treiber für Springboot zum Betrieb von Redis registriert werden.

Was ist der Unterschied zwischen Salat und Jedis? Salat: Die unterste Ebene ist in Netty implementiert, threadsicher und verfügt standardmäßig nur über eine Instanz.

jedis: Kann direkt mit dem Redis-Server verbunden und mit dem Verbindungspool verwendet werden, um physische Verbindungen zu erhöhen.

Suchen Sie die Fehlermethode gemäß der Ausnahmeaufforderung. Im folgenden Code soll 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() konvertieren long Es ist boolesch. Unter normalen Umständen gibt this.getConnection().zadd(key, score, value) 1 zurück, wenn die Addition erfolgreich ist, sodass LettuceConverters.toBoolean(1) wahr wird schlägt fehl, dann wird 0 zurückgegeben, das heißt, LettuceConverters.toBoolean(0) Es gibt auch eine dritte Situation, das heißt, unter welchen Umständen tritt eine Ausnahme auf Wird eine Ausnahme auftreten?

Das sollte der Fall sein, wenn die Verbindung fehlschlägt.

Das obige ist der detaillierte Inhalt vonSo lösen Sie die Timeout-Ausnahme, wenn Springboot2.x Salat integriert und eine Verbindung zum Redis-Cluster herstellt. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen