From dbe5c17d59cdb17ec8069e5f248f24e3d4f01aa1 Mon Sep 17 00:00:00 2001 From: yanghq <1040926235@qq.com> Date: Thu, 21 Nov 2024 14:45:38 +0800 Subject: [PATCH 1/7] 0.5.0-SNAPSHOT --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 76a022c..62e5b6a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ # {x-release-please-start-version} -APP_VERSION=0.4.0 +APP_VERSION=0.5.0-SNAPSHOT # {x-release-please-end-version} APP_GROUP=io.github.guoshiqiufeng.cloud From b48eb9e4358b96399b7edb0a985b61cd10e86065 Mon Sep 17 00:00:00 2001 From: yanghq <1040926235@qq.com> Date: Thu, 19 Dec 2024 17:30:18 +0800 Subject: [PATCH 2/7] dependency: Update SpringCloudStream version to 4.2.0 dependency: Update SpringBoot version to 3.4.0 --- ext.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext.gradle b/ext.gradle index 693b3c1..888aab7 100644 --- a/ext.gradle +++ b/ext.gradle @@ -4,8 +4,8 @@ ext { ] libraries = [ - springBoot3Version = '3.2.11', - springCloudStreamVersion = '4.1.3' + springBoot3Version = '3.4.0', + springCloudStreamVersion = '4.2.0' ] lib = [ From 93f761c8a34c38cae4f57ff624d9fb4f328a87e1 Mon Sep 17 00:00:00 2001 From: yanghq <1040926235@qq.com> Date: Thu, 19 Dec 2024 17:32:41 +0800 Subject: [PATCH 3/7] feat: Adding RedisConnectionFactory Connection Retries --- .../utils/RedisConnectionFactoryUtil.java | 66 ++++++++++++++++--- 1 file changed, 56 insertions(+), 10 deletions(-) diff --git a/binders/spring-cloud-stream-binder-redis-core/src/main/java/io/github/guoshiqiufeng/cloud/stream/binder/redis/utils/RedisConnectionFactoryUtil.java b/binders/spring-cloud-stream-binder-redis-core/src/main/java/io/github/guoshiqiufeng/cloud/stream/binder/redis/utils/RedisConnectionFactoryUtil.java index 3f9812d..8b6212c 100644 --- a/binders/spring-cloud-stream-binder-redis-core/src/main/java/io/github/guoshiqiufeng/cloud/stream/binder/redis/utils/RedisConnectionFactoryUtil.java +++ b/binders/spring-cloud-stream-binder-redis-core/src/main/java/io/github/guoshiqiufeng/cloud/stream/binder/redis/utils/RedisConnectionFactoryUtil.java @@ -15,7 +15,9 @@ */ package io.github.guoshiqiufeng.cloud.stream.binder.redis.utils; +import io.lettuce.core.RedisConnectionException; import lombok.experimental.UtilityClass; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.beans.BeanUtils; import org.springframework.boot.autoconfigure.data.redis.RedisProperties; @@ -35,9 +37,13 @@ * @version 1.0 * @since 2024/8/28 15:52 */ +@Slf4j @UtilityClass public class RedisConnectionFactoryUtil { + private static final int MAX_RETRY_ATTEMPTS = 3; + private static final long RETRY_DELAY_MS = 1000; + /** * get the RedisConnectionFactory * @@ -47,21 +53,61 @@ public class RedisConnectionFactoryUtil { public RedisConnectionFactory getRedisConnectionFactory(@NonNull RedisProperties redisProperties) { Assert.notNull(redisProperties, "'properties' must not be null"); + // add retry + int attempts = 0; + Exception lastException = null; + + while (attempts < MAX_RETRY_ATTEMPTS) { + try { + return createConnectionFactory(redisProperties); + } catch (Exception e) { + lastException = e; + log.warn("Failed to create Redis connection factory, attempt {}/{}", + attempts + 1, MAX_RETRY_ATTEMPTS, e); + + attempts++; + if (attempts < MAX_RETRY_ATTEMPTS) { + try { + Thread.sleep(RETRY_DELAY_MS); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + throw new RedisConnectionException("Connection attempt interrupted", ie); + } + } + } + } + + throw new RedisConnectionException("Failed to create Redis connection after " + + MAX_RETRY_ATTEMPTS + " attempts", lastException); + } + + private RedisConnectionFactory createConnectionFactory(RedisProperties redisProperties) { RedisProperties.ClientType clientType = redisProperties.getClientType(); - if (clientType == RedisProperties.ClientType.JEDIS) { - // 使用 Jedis 作为 Redis 客户端 - JedisConnectionFactory jedisConnectionFactory = configureJedisClient(redisProperties); - jedisConnectionFactory.start(); - return jedisConnectionFactory; - } else { - // 使用 Lettuce 作为 Redis 客户端 - LettuceConnectionFactory lettuceConnectionFactory = configureLettuceClient(redisProperties); - lettuceConnectionFactory.start(); - return lettuceConnectionFactory; + try { + if (clientType == RedisProperties.ClientType.JEDIS) { + // use jedis client + JedisConnectionFactory factory = configureJedisClient(redisProperties); + factory.start(); + validateConnection(factory); + return factory; + } else { + // use lettuce client + LettuceConnectionFactory factory = configureLettuceClient(redisProperties); + factory.start(); + validateConnection(factory); + return factory; + } + } catch (Exception e) { + throw new RedisConnectionException("Error creating Redis connection factory", e); } } + private void validateConnection(RedisConnectionFactory factory) { + try (RedisConnection connection = factory.getConnection()) { + connection.ping(); + } + } private JedisConnectionFactory configureJedisClient(RedisProperties redisProperties) { JedisClientConfiguration clientConfiguration = JedisClientConfiguration.builder() From aa5d9bfe0f8316b1bb8c40f35c8b9828e7b8a289 Mon Sep 17 00:00:00 2001 From: yanghq <1040926235@qq.com> Date: Mon, 30 Dec 2024 17:51:43 +0800 Subject: [PATCH 4/7] fix: jedis password [#11] --- .../stream/binder/redis/utils/RedisConnectionFactoryUtil.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/binders/spring-cloud-stream-binder-redis-core/src/main/java/io/github/guoshiqiufeng/cloud/stream/binder/redis/utils/RedisConnectionFactoryUtil.java b/binders/spring-cloud-stream-binder-redis-core/src/main/java/io/github/guoshiqiufeng/cloud/stream/binder/redis/utils/RedisConnectionFactoryUtil.java index 8b6212c..79b689e 100644 --- a/binders/spring-cloud-stream-binder-redis-core/src/main/java/io/github/guoshiqiufeng/cloud/stream/binder/redis/utils/RedisConnectionFactoryUtil.java +++ b/binders/spring-cloud-stream-binder-redis-core/src/main/java/io/github/guoshiqiufeng/cloud/stream/binder/redis/utils/RedisConnectionFactoryUtil.java @@ -88,13 +88,13 @@ private RedisConnectionFactory createConnectionFactory(RedisProperties redisProp if (clientType == RedisProperties.ClientType.JEDIS) { // use jedis client JedisConnectionFactory factory = configureJedisClient(redisProperties); - factory.start(); + factory.afterPropertiesSet(); validateConnection(factory); return factory; } else { // use lettuce client LettuceConnectionFactory factory = configureLettuceClient(redisProperties); - factory.start(); + factory.afterPropertiesSet(); validateConnection(factory); return factory; } From 04371736b8e32ff1b8b12002351eb58edb6d92c2 Mon Sep 17 00:00:00 2001 From: yanghq <1040926235@qq.com> Date: Mon, 30 Dec 2024 17:54:20 +0800 Subject: [PATCH 5/7] feat: Monitoring Metrics Add Connection Pooling Configuration --- .../converter/MessagingMessageConverter.java | 2 +- .../build.gradle | 3 ++ .../health/RedisBinderHealthIndicator.java | 45 +++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/binders/spring-cloud-stream-binder-redis-core/src/main/java/io/github/guoshiqiufeng/cloud/stream/binder/redis/support/converter/MessagingMessageConverter.java b/binders/spring-cloud-stream-binder-redis-core/src/main/java/io/github/guoshiqiufeng/cloud/stream/binder/redis/support/converter/MessagingMessageConverter.java index 3e05c53..da369f7 100644 --- a/binders/spring-cloud-stream-binder-redis-core/src/main/java/io/github/guoshiqiufeng/cloud/stream/binder/redis/support/converter/MessagingMessageConverter.java +++ b/binders/spring-cloud-stream-binder-redis-core/src/main/java/io/github/guoshiqiufeng/cloud/stream/binder/redis/support/converter/MessagingMessageConverter.java @@ -15,7 +15,7 @@ */ package io.github.guoshiqiufeng.cloud.stream.binder.redis.support.converter; -import org.jetbrains.annotations.NotNull; +import jakarta.validation.constraints.NotNull; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHeaders; diff --git a/binders/spring-cloud-stream-binder-redis/build.gradle b/binders/spring-cloud-stream-binder-redis/build.gradle index 5c3cb0b..1005e51 100644 --- a/binders/spring-cloud-stream-binder-redis/build.gradle +++ b/binders/spring-cloud-stream-binder-redis/build.gradle @@ -5,6 +5,9 @@ dependencies { annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" annotationProcessor "org.springframework.boot:spring-boot-autoconfigure" + implementation 'io.lettuce:lettuce-core' + implementation 'redis.clients:jedis' + testImplementation 'io.lettuce:lettuce-core' testImplementation 'redis.clients:jedis' testImplementation "org.springframework.boot:spring-boot-starter-test" diff --git a/binders/spring-cloud-stream-binder-redis/src/main/java/io/github/guoshiqiufeng/cloud/stream/binder/redis/health/RedisBinderHealthIndicator.java b/binders/spring-cloud-stream-binder-redis/src/main/java/io/github/guoshiqiufeng/cloud/stream/binder/redis/health/RedisBinderHealthIndicator.java index 34c35dc..dee1529 100644 --- a/binders/spring-cloud-stream-binder-redis/src/main/java/io/github/guoshiqiufeng/cloud/stream/binder/redis/health/RedisBinderHealthIndicator.java +++ b/binders/spring-cloud-stream-binder-redis/src/main/java/io/github/guoshiqiufeng/cloud/stream/binder/redis/health/RedisBinderHealthIndicator.java @@ -15,8 +15,15 @@ */ package io.github.guoshiqiufeng.cloud.stream.binder.redis.health; +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.boot.actuate.data.redis.RedisHealthIndicator; +import org.springframework.boot.actuate.health.Health; import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.jedis.JedisClientConfiguration; +import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration; /** * Health indicator for Redis binder. @@ -27,7 +34,45 @@ */ public class RedisBinderHealthIndicator extends RedisHealthIndicator { + private final RedisConnectionFactory connectionFactory; + public RedisBinderHealthIndicator(RedisConnectionFactory connectionFactory) { super(connectionFactory); + this.connectionFactory = connectionFactory; + } + + @Override + protected void doHealthCheck(Health.Builder builder) throws Exception { + try { + // 基础连接检查 + super.doHealthCheck(builder); + + // 连接池状态检查 + checkConnectionPoolStatus(builder); + + } catch (Exception e) { + builder.down().withException(e); + } + } + + private void checkConnectionPoolStatus(Health.Builder builder) { + if (connectionFactory instanceof LettuceConnectionFactory lettuceFactory) { + LettuceClientConfiguration clientConfiguration = lettuceFactory.getClientConfiguration(); + if (clientConfiguration instanceof LettucePoolingClientConfiguration poolConfig) { + GenericObjectPoolConfig pool = poolConfig.getPoolConfig(); + builder.withDetail("pool.maxTotal", pool.getMaxTotal()) + .withDetail("pool.maxIdle", pool.getMaxIdle()) + .withDetail("pool.minIdle", pool.getMinIdle()); + } else { + builder.withDetail("pool", "Lettuce connection pool is not configured."); + } + } else if (connectionFactory instanceof JedisConnectionFactory jedisFactory) { + JedisClientConfiguration clientConfiguration = jedisFactory.getClientConfiguration(); + clientConfiguration.getPoolConfig().ifPresent(pool -> { + builder.withDetail("pool.maxTotal", pool.getMaxTotal()) + .withDetail("pool.maxIdle", pool.getMaxIdle()) + .withDetail("pool.minIdle", pool.getMinIdle()); + }); + } } } From 5b536b02dc915a73eb31b2a7b48a6cdc94cb26cf Mon Sep 17 00:00:00 2001 From: yanghq <1040926235@qq.com> Date: Mon, 30 Dec 2024 17:59:47 +0800 Subject: [PATCH 6/7] doc: update config actuator --- docs/en/guide/actuator.md | 7 +++++-- docs/en/guide/config.md | 25 +++++++++++++++++++++++++ docs/guide/actuator.md | 7 +++++-- docs/guide/config.md | 25 +++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 4 deletions(-) diff --git a/docs/en/guide/actuator.md b/docs/en/guide/actuator.md index b92c287..a71c80b 100644 --- a/docs/en/guide/actuator.md +++ b/docs/en/guide/actuator.md @@ -42,7 +42,10 @@ Example: "redis": { "status": "UP", "details": { - "version": "7.1.2" + "version": "7.1.2", + "pool.maxTotal": 8, + "pool.maxIdle": 8, + "pool.minIdle": 0 } } } @@ -52,4 +55,4 @@ Example: } } } -``` \ No newline at end of file +``` diff --git a/docs/en/guide/config.md b/docs/en/guide/config.md index 7007e06..2cdf695 100644 --- a/docs/en/guide/config.md +++ b/docs/en/guide/config.md @@ -55,6 +55,31 @@ spring: The default is to use the `lettuce` client, if you need to switch to the jedis client, you can add a jedis dependency to do so, with the same configuration parameters as spring-boot-starter-data-redis. +- jedis dependencies + + + +```xml:no-line-numbers:no-v-pre + + redis.clients + jedis + +``` + + + + + +```groovy:no-line-numbers:no-v-pre +dependencies { + implementation platform("redis.clients:jedis") +} +``` + + + + +- configuration ```yaml:no-line-numbers spring: cloud: diff --git a/docs/guide/actuator.md b/docs/guide/actuator.md index 9b4fb20..f7f410d 100644 --- a/docs/guide/actuator.md +++ b/docs/guide/actuator.md @@ -42,7 +42,10 @@ management: "redis": { "status": "UP", "details": { - "version": "7.1.2" + "version": "7.1.2", + "pool.maxTotal": 8, + "pool.maxIdle": 8, + "pool.minIdle": 0 } } } @@ -52,4 +55,4 @@ management: } } } -``` \ No newline at end of file +``` diff --git a/docs/guide/config.md b/docs/guide/config.md index 4cebc65..ce648fe 100644 --- a/docs/guide/config.md +++ b/docs/guide/config.md @@ -54,6 +54,31 @@ spring: 默认与 使用`lettuce`客户端,如需切换 jedis 客户端,可以添加 jedis 依赖 即可,配置参数与 spring-boot-starter-data-redis 一致。 +- jedis依赖 + + + +```xml:no-line-numbers:no-v-pre + + redis.clients + jedis + +``` + + + + + +```groovy:no-line-numbers:no-v-pre +dependencies { + implementation platform("redis.clients:jedis") +} +``` + + + + +- 配置 ```yaml:no-line-numbers spring: cloud: From cc98856f99bfa71ec1f1a7fa7c0f66da07a9988a Mon Sep 17 00:00:00 2001 From: yanghq <1040926235@qq.com> Date: Mon, 30 Dec 2024 18:00:15 +0800 Subject: [PATCH 7/7] release: 0.5.0 --- README-zh.md | 2 +- README.md | 2 +- gradle.properties | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README-zh.md b/README-zh.md index 6c32fbd..fa6fc15 100644 --- a/README-zh.md +++ b/README-zh.md @@ -39,7 +39,7 @@ https://guoshiqiufeng.github.io/spring-cloud-stream-redis/ io.github.guoshiqiufeng.cloud spring-cloud-stream-dependencies - 0.4.0 + 0.5.0 import diff --git a/README.md b/README.md index f3b4b5b..718d2f0 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ https://guoshiqiufeng.github.io/spring-cloud-stream-redis/en/ io.github.guoshiqiufeng.cloud spring-cloud-stream-dependencies - 0.4.0 + 0.5.0 import diff --git a/gradle.properties b/gradle.properties index 62e5b6a..302fd06 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ # {x-release-please-start-version} -APP_VERSION=0.5.0-SNAPSHOT +APP_VERSION=0.5.0 # {x-release-please-end-version} APP_GROUP=io.github.guoshiqiufeng.cloud