From dfe676fc86befb503c476e84fa6591718e6f9f5b Mon Sep 17 00:00:00 2001 From: Ahoo Wang Date: Tue, 25 May 2021 20:07:07 +0800 Subject: [PATCH] Enhance - Reload script after Redis crash. --- README.md | 32 +++---- README.zh-CN.md | 32 +++---- ...onsistencyRedisConfigServiceBenchmark.java | 4 +- .../config/RedisConfigServiceBenchmark.java | 8 +- .../config/redis/ConfigRedisScripts.java | 16 ++-- .../config/redis/RedisConfigService.java | 40 ++++----- .../core/redis/RedisScriptInitializer.java | 84 +++++++++++++++++++ .../ahoo/govern/core/util/RedisScripts.java | 28 +++++++ ...istencyRedisServiceDiscoveryBenchmark.java | 14 ++-- .../RedisServiceDiscoveryBenchmark.java | 10 ++- .../RedisServiceRegistryBenchmark.java | 12 +-- .../discovery/RenewInstanceService.java | 2 +- .../redis/DiscoveryRedisScripts.java | 44 +++++----- .../redis/RedisServiceDiscovery.java | 65 +++++++------- .../discovery/redis/RedisServiceRegistry.java | 38 ++++----- .../redis/RedisServiceStatistic.java | 5 +- .../ConsistencyRedisServiceDiscoveryTest.java | 1 - .../spring/cloud/GovernAutoConfiguration.java | 7 ++ gradle.properties | 2 +- k8s/deployment/govern-servce-rest-api.yml | 2 +- k8s/docker/rest-api-local/Dockerfile | 6 +- k8s/docker/rest-api/Dockerfile | 6 +- 22 files changed, 284 insertions(+), 174 deletions(-) create mode 100644 govern-core/src/main/java/me/ahoo/govern/core/redis/RedisScriptInitializer.java diff --git a/README.md b/README.md index 3bdc08c3..87770a55 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ consistency between process cache and Redis. > Kotlin DSL ``` kotlin - val governVersion = "0.9.19"; + val governVersion = "0.9.20"; implementation("me.ahoo.govern:spring-cloud-starter-govern-config:${governVersion}") implementation("me.ahoo.govern:spring-cloud-starter-govern-discovery:${governVersion}") ``` @@ -33,7 +33,7 @@ consistency between process cache and Redis. 4.0.0 demo - 0.9.19 + 0.9.20 @@ -77,31 +77,31 @@ logging: #### Option 1:Download the executable file -> Download [govern-rest-api-server](https://github.com/Ahoo-Wang/govern-service/releases/download/0.9.19/govern-rest-api-0.9.19.tar) +> Download [govern-rest-api-server](https://github.com/Ahoo-Wang/govern-service/releases/download/0.9.20/govern-rest-api-0.9.20.tar) -> tar *govern-rest-api-0.9.19.tar* +> tar *govern-rest-api-0.9.20.tar* ```shell -cd govern-rest-api-0.9.19 -# Working directory: govern-rest-api-0.9.19 +cd govern-rest-api-0.9.20 +# Working directory: govern-rest-api-0.9.20 bin/govern-rest-api --server.port=8080 --govern.redis.uri=redis://localhost:6379 ``` #### Option 2:Run On Docker ```shell -docker pull ahoowang/govern-service:0.9.19 -docker run --name govern-service -d -p 8080:8080 --link redis -e GOVERN_REDIS_URI=redis://redis:6379 ahoowang/govern-service:0.9.19 +docker pull ahoowang/govern-service:0.9.20 +docker run --name govern-service -d -p 8080:8080 --link redis -e GOVERN_REDIS_URI=redis://redis:6379 ahoowang/govern-service:0.9.20 ``` --- > MacBook Pro (M1) > -> Please use *ahoowang/govern-service:0.9.19-armv7* +> Please use *ahoowang/govern-service:0.9.20-armv7* ```shell -docker pull ahoowang/govern-service:0.9.19-armv7 -docker run --name govern-service -d -p 8080:8080 --link redis -e GOVERN_REDIS_URI=redis://redis:6379 ahoowang/govern-service:0.9.19-armv7 +docker pull ahoowang/govern-service:0.9.20-armv7 +docker run --name govern-service -d -p 8080:8080 --link redis -e GOVERN_REDIS_URI=redis://redis:6379 ahoowang/govern-service:0.9.20-armv7 ``` #### Option 3:Run On Kubernetes @@ -127,7 +127,7 @@ spec: value: standalone - name: GOVERN_REDIS_URI value: redis://redis-uri:6379 - image: ahoowang/govern-service:0.9.19 + image: ahoowang/govern-service:0.9.20 name: govern-service resources: limits: @@ -250,7 +250,9 @@ spec: ### ConfigService ``` shell -gradle config:jmh +gradle govern-config:jmh +# or +java -jar govern-config/build/libs/govern-config-0.9.20-jmh.jar -bm thrpt -t 25 -wi 1 -rf json -f 1 ``` ``` @@ -274,7 +276,9 @@ RedisConfigServiceBenchmark.setConfig thrpt 103659.132 ### ServiceDiscovery ``` shell -gradle discovery:jmh +gradle govern-discovery:jmh +# or +java -jar govern-discovery/build/libs/govern-discovery-0.9.20-jmh.jar -bm thrpt -t 25 -wi 1 -rf json -f 1 ``` ``` diff --git a/README.zh-CN.md b/README.zh-CN.md index cc47df53..a873e755 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -11,7 +11,7 @@ > Kotlin DSL ``` kotlin - val governVersion = "0.9.19"; + val governVersion = "0.9.20"; implementation("me.ahoo.govern:spring-cloud-starter-govern-config:${governVersion}") implementation("me.ahoo.govern:spring-cloud-starter-govern-discovery:${governVersion}") ``` @@ -28,7 +28,7 @@ 4.0.0 demo - 0.9.19 + 0.9.20 @@ -72,30 +72,30 @@ logging: #### 方式一:下载可执行文件 -> 下载 [rest-api-server](https://github.com/Ahoo-Wang/govern-service/releases/download/0.9.19/govern-rest-api-0.9.19.tar) +> 下载 [rest-api-server](https://github.com/Ahoo-Wang/govern-service/releases/download/0.9.20/govern-rest-api-0.9.20.tar) -> 解压 *govern-rest-api-0.9.19.tar* +> 解压 *govern-rest-api-0.9.20.tar* ```shell -cd govern-rest-api-0.9.19 -# 工作目录: govern-rest-api-0.9.19 +cd govern-rest-api-0.9.20 +# 工作目录: govern-rest-api-0.9.20 bin/govern-rest-api --server.port=8080 --govern.redis.uri=redis://localhost:6379 ``` #### 方式二:在 Docker 中运行 ```shell -docker pull ahoowang/govern-service:0.9.19 -docker run --name govern-service -d -p 8080:8080 --link redis -e GOVERN_REDIS_URI=redis://redis:6379 ahoowang/govern-service:0.9.19 +docker pull ahoowang/govern-service:0.9.20 +docker run --name govern-service -d -p 8080:8080 --link redis -e GOVERN_REDIS_URI=redis://redis:6379 ahoowang/govern-service:0.9.20 ``` --- > MacBook Pro (M1) > -> 请使用 *ahoowang/govern-service:0.9.19-armv7* +> 请使用 *ahoowang/govern-service:0.9.20-armv7* ```shell -docker pull ahoowang/govern-service:0.9.19-armv7 -docker run --name govern-service -d -p 8080:8080 --link redis -e GOVERN_REDIS_URI=redis://redis:6379 ahoowang/govern-service:0.9.19-armv7 +docker pull ahoowang/govern-service:0.9.20-armv7 +docker run --name govern-service -d -p 8080:8080 --link redis -e GOVERN_REDIS_URI=redis://redis:6379 ahoowang/govern-service:0.9.20-armv7 ``` #### 方式三:在 Kubernetes 中运行 @@ -121,7 +121,7 @@ spec: value: standalone - name: GOVERN_REDIS_URI value: redis://redis-uri:6379 - image: ahoowang/govern-service:0.9.19 + image: ahoowang/govern-service:0.9.20 name: govern-service resources: limits: @@ -245,7 +245,9 @@ spec: ### ConfigService ``` shell -gradle config:jmh +gradle govern-config:jmh +# or +java -jar govern-config/build/libs/govern-config-0.9.20-jmh.jar -bm thrpt -t 25 -wi 1 -rf json -f 1 ``` ``` @@ -269,7 +271,9 @@ RedisConfigServiceBenchmark.setConfig thrpt 103659.132 ### ServiceDiscovery ``` shell -gradle discovery:jmh +gradle govern-discovery:jmh +# or +java -jar govern-discovery/build/libs/govern-discovery-0.9.20-jmh.jar -bm thrpt -t 25 -wi 1 -rf json -f 1 ``` ``` diff --git a/govern-config/src/jmh/java/me/ahoo/govern/config/ConsistencyRedisConfigServiceBenchmark.java b/govern-config/src/jmh/java/me/ahoo/govern/config/ConsistencyRedisConfigServiceBenchmark.java index 08a0b500..91f02615 100644 --- a/govern-config/src/jmh/java/me/ahoo/govern/config/ConsistencyRedisConfigServiceBenchmark.java +++ b/govern-config/src/jmh/java/me/ahoo/govern/config/ConsistencyRedisConfigServiceBenchmark.java @@ -64,7 +64,7 @@ public void tearDown() { } @Benchmark - public void getConfig() { - configService.getConfig(namespace, configId).join(); + public Config getConfig() { + return configService.getConfig(namespace, configId).join(); } } diff --git a/govern-config/src/jmh/java/me/ahoo/govern/config/RedisConfigServiceBenchmark.java b/govern-config/src/jmh/java/me/ahoo/govern/config/RedisConfigServiceBenchmark.java index 0867777e..4666307b 100644 --- a/govern-config/src/jmh/java/me/ahoo/govern/config/RedisConfigServiceBenchmark.java +++ b/govern-config/src/jmh/java/me/ahoo/govern/config/RedisConfigServiceBenchmark.java @@ -53,14 +53,14 @@ public void tearDown() { } @Benchmark - public void setConfig() { + public Boolean setConfig() { String randomConfigId = String.valueOf(atomicInteger.incrementAndGet()); - configService.setConfig(namespace, randomConfigId, configData).join(); + return configService.setConfig(namespace, randomConfigId, configData).join(); } @Benchmark - public void getConfig() { - configService.getConfig(namespace, configId).join(); + public Config getConfig() { + return configService.getConfig(namespace, configId).join(); } } diff --git a/govern-config/src/main/java/me/ahoo/govern/config/redis/ConfigRedisScripts.java b/govern-config/src/main/java/me/ahoo/govern/config/redis/ConfigRedisScripts.java index 879b66ab..04f78bbd 100644 --- a/govern-config/src/main/java/me/ahoo/govern/config/redis/ConfigRedisScripts.java +++ b/govern-config/src/main/java/me/ahoo/govern/config/redis/ConfigRedisScripts.java @@ -1,9 +1,11 @@ package me.ahoo.govern.config.redis; +import io.lettuce.core.RedisFuture; import io.lettuce.core.api.async.RedisScriptingAsyncCommands; import me.ahoo.govern.core.util.RedisScripts; import java.util.concurrent.CompletableFuture; +import java.util.function.Function; /** * @author ahoo wang @@ -13,14 +15,14 @@ public final class ConfigRedisScripts { public static final String CONFIG_REMOVE = "config_remove.lua"; public static final String CONFIG_ROLLBACK = "config_rollback.lua"; - public static CompletableFuture loadConfigSet(RedisScriptingAsyncCommands scriptingCommands) { - return RedisScripts.loadScript(CONFIG_SET, scriptingCommands); + public static CompletableFuture doConfigSet(RedisScriptingAsyncCommands scriptingCommands, Function> doSha) { + return RedisScripts.doEnsureScript(CONFIG_SET, scriptingCommands, doSha); } - - public static CompletableFuture loadConfigRemove(RedisScriptingAsyncCommands scriptingCommands) { - return RedisScripts.loadScript(CONFIG_REMOVE, scriptingCommands); + public static CompletableFuture doConfigRemove(RedisScriptingAsyncCommands scriptingCommands, Function> doSha) { + return RedisScripts.doEnsureScript(CONFIG_REMOVE, scriptingCommands, doSha); } - public static CompletableFuture loadConfigRollback(RedisScriptingAsyncCommands scriptingCommands) { - return RedisScripts.loadScript(CONFIG_ROLLBACK, scriptingCommands); + public static CompletableFuture doConfigRollback(RedisScriptingAsyncCommands scriptingCommands, Function> doSha) { + return RedisScripts.doEnsureScript(CONFIG_ROLLBACK, scriptingCommands, doSha); } + } diff --git a/govern-config/src/main/java/me/ahoo/govern/config/redis/RedisConfigService.java b/govern-config/src/main/java/me/ahoo/govern/config/redis/RedisConfigService.java index 255b3b72..6d205fb9 100644 --- a/govern-config/src/main/java/me/ahoo/govern/config/redis/RedisConfigService.java +++ b/govern-config/src/main/java/me/ahoo/govern/config/redis/RedisConfigService.java @@ -3,7 +3,6 @@ import com.google.common.base.Charsets; import com.google.common.base.Function; import com.google.common.hash.Hashing; -import io.lettuce.core.RedisFuture; import io.lettuce.core.ScriptOutputType; import io.lettuce.core.cluster.api.async.RedisClusterAsyncCommands; import lombok.extern.slf4j.Slf4j; @@ -76,14 +75,11 @@ public CompletableFuture setConfig(String namespace, String configId, S if (log.isInfoEnabled()) { log.info("setConfig - configId:[{}] - hash:[{}] @ namespace:[{}].", configId, hash, namespace); } - - return ConfigRedisScripts.loadConfigSet(redisCommands) - .thenCompose(sha -> { - String[] keys = {namespace}; - String[] values = {configId, data, hash}; - RedisFuture redisFuture = redisCommands.evalsha(sha, ScriptOutputType.BOOLEAN, keys, values); - return redisFuture; - }); + return ConfigRedisScripts.doConfigSet(redisCommands, sha -> { + String[] keys = {namespace}; + String[] values = {configId, data, hash}; + return redisCommands.evalsha(sha, ScriptOutputType.BOOLEAN, keys, values); + }); } @Override @@ -96,14 +92,11 @@ public CompletableFuture removeConfig(String namespace, String configId if (log.isInfoEnabled()) { log.info("removeConfig - configId:[{}] @ namespace:[{}].", configId, namespace); } - - return ConfigRedisScripts.loadConfigRemove(redisCommands) - .thenCompose(sha -> { - String[] keys = {namespace}; - String[] values = {configId}; - RedisFuture redisFuture = redisCommands.evalsha(sha, ScriptOutputType.BOOLEAN, keys, values); - return redisFuture; - }); + return ConfigRedisScripts.doConfigRemove(redisCommands, sha -> { + String[] keys = {namespace}; + String[] values = {configId}; + return redisCommands.evalsha(sha, ScriptOutputType.BOOLEAN, keys, values); + }); } @Override @@ -122,14 +115,11 @@ public CompletableFuture rollback(String namespace, String configId, in if (log.isInfoEnabled()) { log.info("rollback - configId:[{}] - targetVersion:[{}] @ namespace:[{}].", configId, targetVersion, namespace); } - - return ConfigRedisScripts.loadConfigRollback(redisCommands) - .thenCompose(sha -> { - String[] keys = {namespace}; - String[] values = {configId, String.valueOf(targetVersion)}; - RedisFuture redisFuture = redisCommands.evalsha(sha, ScriptOutputType.BOOLEAN, keys, values); - return redisFuture; - }); + return ConfigRedisScripts.doConfigRollback(redisCommands, sha -> { + String[] keys = {namespace}; + String[] values = {configId, String.valueOf(targetVersion)}; + return redisCommands.evalsha(sha, ScriptOutputType.BOOLEAN, keys, values); + }); } private final static int HISTORY_STOP = HISTORY_SIZE - 1; diff --git a/govern-core/src/main/java/me/ahoo/govern/core/redis/RedisScriptInitializer.java b/govern-core/src/main/java/me/ahoo/govern/core/redis/RedisScriptInitializer.java new file mode 100644 index 00000000..c1bf780c --- /dev/null +++ b/govern-core/src/main/java/me/ahoo/govern/core/redis/RedisScriptInitializer.java @@ -0,0 +1,84 @@ +package me.ahoo.govern.core.redis; + +import io.lettuce.core.AbstractRedisClient; +import io.lettuce.core.RedisChannelHandler; +import io.lettuce.core.RedisConnectionStateListener; +import lombok.extern.slf4j.Slf4j; +import lombok.var; +import me.ahoo.govern.core.util.RedisScripts; + +import java.io.Closeable; +import java.io.IOException; +import java.net.SocketAddress; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author ahoo wang + */ +@Slf4j +public class RedisScriptInitializer implements Closeable { + + private final AbstractRedisClient redisClient; + private final RedisStateListener redisStateListener; + + public RedisScriptInitializer(AbstractRedisClient redisClient) { + this.redisClient = redisClient; + this.redisStateListener = new RedisStateListener(); + redisClient.addListener(redisStateListener); + } + + /** + * Closes this stream and releases any system resources associated + * with it. If the stream is already closed then invoking this + * method has no effect. + * + *

As noted in {@link AutoCloseable#close()}, cases where the + * close may fail require careful attention. It is strongly advised + * to relinquish the underlying resources and to internally + * mark the {@code Closeable} as closed, prior to throwing + * the {@code IOException}. + * + * @throws IOException if an I/O error occurs + */ + @Override + public void close() throws IOException { + this.redisClient.removeListener(redisStateListener); + } + + private static class RedisStateListener implements RedisConnectionStateListener { + + private final Set connectedMap = ConcurrentHashMap.newKeySet(); + + /** + * Event handler for disconnection event. + * + * @param connection Source connection. + */ + @Override + public void onRedisDisconnected(RedisChannelHandler connection) { + } + + @Override + public void onRedisConnected(RedisChannelHandler connection, SocketAddress socketAddress) { + var added = connectedMap.add(connection); + if (!added) { + if (log.isWarnEnabled()) { + log.warn("onRedisConnected - [{}] - [{}] - RedisScripts.clearScript.", connection, socketAddress); + } + RedisScripts.clearScript(); + } + } + + /** + * Event handler for exceptions. + * + * @param connection Source connection. + * @param cause Caught exception. + */ + @Override + public void onRedisExceptionCaught(RedisChannelHandler connection, Throwable cause) { + log.error("onRedisExceptionCaught.", cause); + } + } +} diff --git a/govern-core/src/main/java/me/ahoo/govern/core/util/RedisScripts.java b/govern-core/src/main/java/me/ahoo/govern/core/util/RedisScripts.java index fb81c6b2..645df61e 100644 --- a/govern-core/src/main/java/me/ahoo/govern/core/util/RedisScripts.java +++ b/govern-core/src/main/java/me/ahoo/govern/core/util/RedisScripts.java @@ -3,13 +3,17 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Charsets; import com.google.common.io.Resources; +import io.lettuce.core.RedisFuture; +import io.lettuce.core.RedisNoScriptException; import io.lettuce.core.ScriptOutputType; import io.lettuce.core.api.async.RedisScriptingAsyncCommands; +import io.lettuce.core.internal.Exceptions; import lombok.SneakyThrows; import java.net.URL; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; /** * @author ahoo wang @@ -27,6 +31,10 @@ public static String getScript(String scriptName) { return Resources.toString(url, Charsets.UTF_8); } + public static void clearScript() { + scriptMapSha.clear(); + } + public static CompletableFuture loadScript(String scriptName, RedisScriptingAsyncCommands scriptingCommands) { return scriptMapSha.computeIfAbsent(scriptName, (key) -> { String script = getScript(key); @@ -34,6 +42,13 @@ public static CompletableFuture loadScript(String scriptName, RedisScrip }); } + /** + * 当 Redis 宕机恢复时,lua 脚本需要重新加载 + * + * @param scriptName + * @param scriptingCommands + * @return + */ public static CompletableFuture reloadScript(String scriptName, RedisScriptingAsyncCommands scriptingCommands) { return scriptMapSha.compute(scriptName, (key, result) -> { String script = getScript(key); @@ -41,6 +56,19 @@ public static CompletableFuture reloadScript(String scriptName, RedisScr }); } + public static CompletableFuture doEnsureScript(String scriptName, RedisScriptingAsyncCommands scriptingCommands, Function> doSha) { + return loadScript(scriptName, scriptingCommands).thenCompose(sha -> { + RedisFuture doFuture = doSha.apply(sha); + doFuture.exceptionally(throwable -> { + if (Exceptions.unwrap(throwable) instanceof RedisNoScriptException) { + reloadScript(scriptName, scriptingCommands); + } + throw Exceptions.bubble(throwable); + }); + return doFuture.toCompletableFuture(); + }); + } + /** * only for dev diff --git a/govern-discovery/src/jmh/java/me/ahoo/govern/discovery/ConsistencyRedisServiceDiscoveryBenchmark.java b/govern-discovery/src/jmh/java/me/ahoo/govern/discovery/ConsistencyRedisServiceDiscoveryBenchmark.java index 1e448fe6..8f902332 100644 --- a/govern-discovery/src/jmh/java/me/ahoo/govern/discovery/ConsistencyRedisServiceDiscoveryBenchmark.java +++ b/govern-discovery/src/jmh/java/me/ahoo/govern/discovery/ConsistencyRedisServiceDiscoveryBenchmark.java @@ -9,7 +9,9 @@ import me.ahoo.govern.discovery.redis.RedisServiceRegistry; import org.openjdk.jmh.annotations.*; +import java.util.List; import java.util.Objects; +import java.util.Set; /** * @author ahoo wang @@ -24,7 +26,7 @@ public class ConsistencyRedisServiceDiscoveryBenchmark { @Setup public void setup() { - System.out.println("\n ----- RedisServiceDiscoveryBenchmark setup ----- \n"); + System.out.println("\n ----- ConsistencyRedisServiceDiscoveryBenchmark setup ----- \n"); redisClient = RedisClient.create("redis://localhost:6379"); redisConnection = redisClient.connect(); @@ -38,7 +40,7 @@ public void setup() { @TearDown public void tearDown() { - System.out.println("\n ----- RedisServiceDiscoveryBenchmark tearDown ----- \n"); + System.out.println("\n ----- ConsistencyRedisServiceDiscoveryBenchmark tearDown ----- \n"); if (Objects.nonNull(redisConnection)) { redisConnection.close(); } @@ -55,12 +57,12 @@ public void tearDown() { } @Benchmark - public void getServices() { - serviceDiscovery.getServices(namespace).join(); + public Set getServices() { + return serviceDiscovery.getServices(namespace).join(); } @Benchmark - public void getInstances() { - serviceDiscovery.getInstances(namespace, TestServiceInstance.TEST_FIXED_INSTANCE.getServiceId()).join(); + public List getInstances() { + return serviceDiscovery.getInstances(namespace, TestServiceInstance.TEST_FIXED_INSTANCE.getServiceId()).join(); } } diff --git a/govern-discovery/src/jmh/java/me/ahoo/govern/discovery/RedisServiceDiscoveryBenchmark.java b/govern-discovery/src/jmh/java/me/ahoo/govern/discovery/RedisServiceDiscoveryBenchmark.java index d179a898..878a766e 100644 --- a/govern-discovery/src/jmh/java/me/ahoo/govern/discovery/RedisServiceDiscoveryBenchmark.java +++ b/govern-discovery/src/jmh/java/me/ahoo/govern/discovery/RedisServiceDiscoveryBenchmark.java @@ -6,7 +6,9 @@ import me.ahoo.govern.discovery.redis.RedisServiceRegistry; import org.openjdk.jmh.annotations.*; +import java.util.List; import java.util.Objects; +import java.util.Set; /** * @author ahoo wang @@ -42,12 +44,12 @@ public void tearDown() { } @Benchmark - public void getServices() { - serviceDiscovery.getServices(namespace).join(); + public Set getServices() { + return serviceDiscovery.getServices(namespace).join(); } @Benchmark - public void getInstances() { - serviceDiscovery.getInstances(namespace, TestServiceInstance.TEST_FIXED_INSTANCE.getServiceId()).join(); + public List getInstances() { + return serviceDiscovery.getInstances(namespace, TestServiceInstance.TEST_FIXED_INSTANCE.getServiceId()).join(); } } diff --git a/govern-discovery/src/jmh/java/me/ahoo/govern/discovery/RedisServiceRegistryBenchmark.java b/govern-discovery/src/jmh/java/me/ahoo/govern/discovery/RedisServiceRegistryBenchmark.java index 6d637993..583e9534 100644 --- a/govern-discovery/src/jmh/java/me/ahoo/govern/discovery/RedisServiceRegistryBenchmark.java +++ b/govern-discovery/src/jmh/java/me/ahoo/govern/discovery/RedisServiceRegistryBenchmark.java @@ -40,18 +40,18 @@ public void tearDown() { } @Benchmark - public void register() { - serviceRegistry.register(namespace, TestServiceInstance.TEST_INSTANCE).join(); + public Boolean register() { + return serviceRegistry.register(namespace, TestServiceInstance.TEST_INSTANCE).join(); } @Benchmark - public void deregister() { - serviceRegistry.deregister(namespace, TestServiceInstance.TEST_INSTANCE).join(); + public Boolean deregister() { + return serviceRegistry.deregister(namespace, TestServiceInstance.TEST_INSTANCE).join(); } @Benchmark - public void renew() { - serviceRegistry.renew(namespace, TestServiceInstance.TEST_INSTANCE).join(); + public Boolean renew() { + return serviceRegistry.renew(namespace, TestServiceInstance.TEST_INSTANCE).join(); } } diff --git a/govern-discovery/src/main/java/me/ahoo/govern/discovery/RenewInstanceService.java b/govern-discovery/src/main/java/me/ahoo/govern/discovery/RenewInstanceService.java index a8920732..14e1ca0a 100644 --- a/govern-discovery/src/main/java/me/ahoo/govern/discovery/RenewInstanceService.java +++ b/govern-discovery/src/main/java/me/ahoo/govern/discovery/RenewInstanceService.java @@ -84,7 +84,7 @@ private void renew() { if (log.isWarnEnabled()) { log.warn("renew - failed.", ex); } - return null; + return Boolean.FALSE; }); } CompletableFuture.allOf(renewFutures).thenAccept((nil) -> { diff --git a/govern-discovery/src/main/java/me/ahoo/govern/discovery/redis/DiscoveryRedisScripts.java b/govern-discovery/src/main/java/me/ahoo/govern/discovery/redis/DiscoveryRedisScripts.java index 4c3ed8fd..02629917 100644 --- a/govern-discovery/src/main/java/me/ahoo/govern/discovery/redis/DiscoveryRedisScripts.java +++ b/govern-discovery/src/main/java/me/ahoo/govern/discovery/redis/DiscoveryRedisScripts.java @@ -1,9 +1,11 @@ package me.ahoo.govern.discovery.redis; +import io.lettuce.core.RedisFuture; import io.lettuce.core.api.async.RedisScriptingAsyncCommands; import me.ahoo.govern.core.util.RedisScripts; import java.util.concurrent.CompletableFuture; +import java.util.function.Function; /** * @author ahoo wang @@ -21,46 +23,46 @@ public final class DiscoveryRedisScripts { public static final String INSTANCE_COUNT_STAT = "instance_count_stat.lua"; public static final String SERVICE_STAT = "service_stat.lua"; - public static CompletableFuture loadRegistryRegister(RedisScriptingAsyncCommands scriptingCommands) { - return RedisScripts.loadScript(REGISTRY_REGISTER, scriptingCommands); - } - public static CompletableFuture loadRegistryDeregister(RedisScriptingAsyncCommands scriptingCommands) { - return RedisScripts.loadScript(REGISTRY_DEREGISTER, scriptingCommands); + public static CompletableFuture doRegistryRegister(RedisScriptingAsyncCommands scriptingCommands, Function> doSha) { + return RedisScripts.doEnsureScript(REGISTRY_REGISTER, scriptingCommands, doSha); } - public static CompletableFuture loadRegistryRenew(RedisScriptingAsyncCommands scriptingCommands) { - return RedisScripts.loadScript(REGISTRY_RENEW, scriptingCommands); + public static CompletableFuture doRegistryDeregister(RedisScriptingAsyncCommands scriptingCommands, Function> doSha) { + return RedisScripts.doEnsureScript(REGISTRY_DEREGISTER, scriptingCommands, doSha); } - public static CompletableFuture loadRegistrySetMetadata(RedisScriptingAsyncCommands scriptingCommands) { - return RedisScripts.loadScript(REGISTRY_SET_METADATA, scriptingCommands); + public static CompletableFuture doRegistryRenew(RedisScriptingAsyncCommands scriptingCommands, Function> doSha) { + return RedisScripts.doEnsureScript(REGISTRY_RENEW, scriptingCommands, doSha); } - public static CompletableFuture loadRegistrySetService(RedisScriptingAsyncCommands scriptingCommands) { - return RedisScripts.loadScript(REGISTRY_SET_SERVICE, scriptingCommands); + public static CompletableFuture doRegistrySetMetadata(RedisScriptingAsyncCommands scriptingCommands, Function> doSha) { + return RedisScripts.doEnsureScript(REGISTRY_SET_METADATA, scriptingCommands, doSha); } - public static CompletableFuture loadRegistryRemoveService(RedisScriptingAsyncCommands scriptingCommands) { - return RedisScripts.loadScript(REGISTRY_REMOVE_SERVICE, scriptingCommands); + public static CompletableFuture doRegistrySetService(RedisScriptingAsyncCommands scriptingCommands, Function> doSha) { + return RedisScripts.doEnsureScript(REGISTRY_SET_SERVICE, scriptingCommands, doSha); } - public static CompletableFuture loadDiscoveryGetInstances(RedisScriptingAsyncCommands scriptingCommands) { - return RedisScripts.loadScript(DISCOVERY_GET_INSTANCES, scriptingCommands); + public static CompletableFuture doRegistryRemoveService(RedisScriptingAsyncCommands scriptingCommands, Function> doSha) { + return RedisScripts.doEnsureScript(REGISTRY_REMOVE_SERVICE, scriptingCommands, doSha); } - public static CompletableFuture loadDiscoveryGetInstance(RedisScriptingAsyncCommands scriptingCommands) { - return RedisScripts.loadScript(DISCOVERY_GET_INSTANCE, scriptingCommands); + public static CompletableFuture doDiscoveryGetInstances(RedisScriptingAsyncCommands scriptingCommands, Function> doSha) { + return RedisScripts.doEnsureScript(DISCOVERY_GET_INSTANCES, scriptingCommands, doSha); } - public static CompletableFuture loadDiscoveryGetInstanceTtl(RedisScriptingAsyncCommands scriptingCommands) { - return RedisScripts.loadScript(DISCOVERY_GET_INSTANCE_TTL, scriptingCommands); + public static CompletableFuture doDiscoveryGetInstance(RedisScriptingAsyncCommands scriptingCommands, Function> doSha) { + return RedisScripts.doEnsureScript(DISCOVERY_GET_INSTANCE, scriptingCommands, doSha); } - public static CompletableFuture loadServiceStat(RedisScriptingAsyncCommands scriptingCommands) { - return RedisScripts.loadScript(SERVICE_STAT, scriptingCommands); + public static CompletableFuture doDiscoveryGetInstanceTtl(RedisScriptingAsyncCommands scriptingCommands, Function> doSha) { + return RedisScripts.doEnsureScript(DISCOVERY_GET_INSTANCE_TTL, scriptingCommands, doSha); } + public static CompletableFuture doServiceStat(RedisScriptingAsyncCommands scriptingCommands, Function> doSha) { + return RedisScripts.doEnsureScript(SERVICE_STAT, scriptingCommands, doSha); + } public static CompletableFuture loadInstanceCountStat(RedisScriptingAsyncCommands scriptingCommands) { return RedisScripts.loadScript(INSTANCE_COUNT_STAT, scriptingCommands); } diff --git a/govern-discovery/src/main/java/me/ahoo/govern/discovery/redis/RedisServiceDiscovery.java b/govern-discovery/src/main/java/me/ahoo/govern/discovery/redis/RedisServiceDiscovery.java index 84235951..6d7ee018 100644 --- a/govern-discovery/src/main/java/me/ahoo/govern/discovery/redis/RedisServiceDiscovery.java +++ b/govern-discovery/src/main/java/me/ahoo/govern/discovery/redis/RedisServiceDiscovery.java @@ -1,6 +1,5 @@ package me.ahoo.govern.discovery.redis; -import io.lettuce.core.RedisFuture; import io.lettuce.core.ScriptOutputType; import io.lettuce.core.cluster.api.async.RedisClusterAsyncCommands; import lombok.extern.slf4j.Slf4j; @@ -33,49 +32,43 @@ public CompletableFuture> getInstances(String serviceId) { @Override public CompletableFuture> getInstances(String namespace, String serviceId) { - return DiscoveryRedisScripts.loadDiscoveryGetInstances(redisCommands) - .thenCompose(sha -> { - String[] keys = {namespace}; - String[] values = {serviceId}; - RedisFuture>> redisFuture = redisCommands.evalsha(sha, ScriptOutputType.MULTI, keys, values); - return redisFuture; - }) - .thenApply(instanceGroups -> { - if (Objects.isNull(instanceGroups)) { - return Collections.emptyList(); - } - ArrayList instances = new ArrayList<>(instanceGroups.size()); - instanceGroups.forEach(instanceData -> instances.add(ServiceInstanceCodec.decode(instanceData))); - return instances; - }); + return DiscoveryRedisScripts.doDiscoveryGetInstances(redisCommands, sha -> { + String[] keys = {namespace}; + String[] values = {serviceId}; + return redisCommands.>>evalsha(sha, ScriptOutputType.MULTI, keys, values); + }) + .thenApply(instanceGroups -> { + if (Objects.isNull(instanceGroups)) { + return Collections.emptyList(); + } + ArrayList instances = new ArrayList<>(instanceGroups.size()); + instanceGroups.forEach(instanceData -> instances.add(ServiceInstanceCodec.decode(instanceData))); + return instances; + }); } @Override public CompletableFuture getInstance(String namespace, String serviceId, String instanceId) { - return DiscoveryRedisScripts.loadDiscoveryGetInstance(redisCommands) - .thenCompose(sha -> { - String[] keys = {namespace}; - String[] values = {serviceId, instanceId}; - RedisFuture> redisFuture = redisCommands.evalsha(sha, ScriptOutputType.MULTI, keys, values); - return redisFuture; - }) - .thenApply(instanceData -> { - if (Objects.isNull(instanceData)) { - return null; - } - return ServiceInstanceCodec.decode(instanceData); - }); + return DiscoveryRedisScripts.doDiscoveryGetInstance(redisCommands, sha -> { + String[] keys = {namespace}; + String[] values = {serviceId, instanceId}; + return redisCommands.>evalsha(sha, ScriptOutputType.MULTI, keys, values); + }) + .thenApply(instanceData -> { + if (Objects.isNull(instanceData)) { + return null; + } + return ServiceInstanceCodec.decode(instanceData); + }); } @Override public CompletableFuture getInstanceTtl(String namespace, String serviceId, String instanceId) { - return DiscoveryRedisScripts.loadDiscoveryGetInstanceTtl(redisCommands) - .thenCompose(sha -> { - String[] keys = {namespace}; - String[] values = {serviceId, instanceId}; - RedisFuture redisFuture = redisCommands.evalsha(sha, ScriptOutputType.INTEGER, keys, values); - return redisFuture; - }); + return DiscoveryRedisScripts.doDiscoveryGetInstanceTtl(redisCommands, sha -> { + String[] keys = {namespace}; + String[] values = {serviceId, instanceId}; + return redisCommands.evalsha(sha, ScriptOutputType.INTEGER, keys, values); + }); } @Override diff --git a/govern-discovery/src/main/java/me/ahoo/govern/discovery/redis/RedisServiceRegistry.java b/govern-discovery/src/main/java/me/ahoo/govern/discovery/redis/RedisServiceRegistry.java index 0d7c2611..8dd9bf3e 100644 --- a/govern-discovery/src/main/java/me/ahoo/govern/discovery/redis/RedisServiceRegistry.java +++ b/govern-discovery/src/main/java/me/ahoo/govern/discovery/redis/RedisServiceRegistry.java @@ -30,7 +30,7 @@ public RedisServiceRegistry(RegistryProperties registryProperties, this.redisCommands = redisCommands; } - private CompletableFuture register0(String namespace, String scriptSha, ServiceInstance serviceInstance) { + private RedisFuture register0(String namespace, String scriptSha, ServiceInstance serviceInstance) { /** * KEYS[1] */ @@ -72,8 +72,7 @@ private CompletableFuture register0(String namespace, String scriptSha, String[] values = ServiceInstanceCodec.encodeMetadata(infoArgs, serviceInstance.getMetadata()); - RedisFuture redisFuture = redisCommands.evalsha(scriptSha, ScriptOutputType.BOOLEAN, keys, values); - return redisFuture.toCompletableFuture(); + return redisCommands.evalsha(scriptSha, ScriptOutputType.BOOLEAN, keys, values); } @Override @@ -82,8 +81,8 @@ public CompletableFuture setService(String namespace, String serviceId) log.info("setService - serviceId:[{}] @ namespace:[{}].", serviceId, namespace); } - return DiscoveryRedisScripts.loadRegistrySetService(redisCommands) - .thenCompose(sha -> redisCommands.evalsha(sha, ScriptOutputType.BOOLEAN, new String[]{namespace}, serviceId)); + return DiscoveryRedisScripts.doRegistrySetService(redisCommands, + sha -> redisCommands.evalsha(sha, ScriptOutputType.BOOLEAN, new String[]{namespace}, serviceId)); } @@ -93,8 +92,8 @@ public CompletableFuture removeService(String namespace, String service log.info("removeService - serviceId:[{}] @ namespace:[{}].", serviceId, namespace); } - return DiscoveryRedisScripts.loadRegistryRemoveService(redisCommands) - .thenCompose(sha -> redisCommands.evalsha(sha, ScriptOutputType.BOOLEAN, new String[]{namespace}, serviceId)); + return DiscoveryRedisScripts.doRegistryRemoveService(redisCommands, + sha -> redisCommands.evalsha(sha, ScriptOutputType.BOOLEAN, new String[]{namespace}, serviceId)); } /** @@ -112,8 +111,7 @@ public CompletableFuture register(String namespace, ServiceInstance ser } addEphemeralInstance(namespace, serviceInstance); - return DiscoveryRedisScripts.loadRegistryRegister(redisCommands) - .thenCompose(sha -> register0(namespace, sha, serviceInstance)); + return DiscoveryRedisScripts.doRegistryRegister(redisCommands, sha -> register0(namespace, sha, serviceInstance)); } private void addEphemeralInstance(String namespace, ServiceInstance serviceInstance) { @@ -174,9 +172,8 @@ private CompletableFuture setMetadata0(String namespace, String instanc log.info("setMetadata - instanceId:[{}] @ namespace:[{}].", instanceId, namespace); } String[] keys = {namespace}; - return DiscoveryRedisScripts.loadRegistrySetMetadata(redisCommands) - .thenCompose(sha -> - redisCommands.evalsha(sha, ScriptOutputType.BOOLEAN, keys, args)); + return DiscoveryRedisScripts.doRegistrySetMetadata(redisCommands, sha -> + redisCommands.evalsha(sha, ScriptOutputType.BOOLEAN, keys, args)); } @@ -197,9 +194,8 @@ public CompletableFuture renew(String namespace, ServiceInstance servic } String[] keys = {namespace}; String[] values = {serviceInstance.getInstanceId(), String.valueOf(registryProperties.getInstanceTtl())}; - return DiscoveryRedisScripts.loadRegistryRenew(redisCommands) - .thenCompose(sha -> - redisCommands.evalsha(sha, ScriptOutputType.BOOLEAN, keys, values)); + return DiscoveryRedisScripts.doRegistryRenew(redisCommands, sha -> + redisCommands.evalsha(sha, ScriptOutputType.BOOLEAN, keys, values)); } @@ -219,13 +215,11 @@ public CompletableFuture deregister(String namespace, String serviceId, } private CompletableFuture deregister0(String namespace, String serviceId, String instanceId) { - return DiscoveryRedisScripts.loadRegistryDeregister(redisCommands) - .thenCompose(sha -> { - String[] keys = {namespace}; - String[] values = {serviceId, instanceId}; - RedisFuture redisFuture = redisCommands.evalsha(sha, ScriptOutputType.BOOLEAN, keys, values); - return redisFuture; - }); + return DiscoveryRedisScripts.doRegistryDeregister(redisCommands, sha -> { + String[] keys = {namespace}; + String[] values = {serviceId, instanceId}; + return redisCommands.evalsha(sha, ScriptOutputType.BOOLEAN, keys, values); + }); } @Override diff --git a/govern-discovery/src/main/java/me/ahoo/govern/discovery/redis/RedisServiceStatistic.java b/govern-discovery/src/main/java/me/ahoo/govern/discovery/redis/RedisServiceStatistic.java index b93fba88..f88e5634 100644 --- a/govern-discovery/src/main/java/me/ahoo/govern/discovery/redis/RedisServiceStatistic.java +++ b/govern-discovery/src/main/java/me/ahoo/govern/discovery/redis/RedisServiceStatistic.java @@ -66,9 +66,8 @@ private CompletableFuture statService0(String namespace, String serviceId) } else { values = new String[]{}; } - return DiscoveryRedisScripts.loadServiceStat(redisCommands).thenCompose(sha -> - redisCommands.evalsha(sha, ScriptOutputType.STATUS, keys, values) - ); + return DiscoveryRedisScripts.doServiceStat(redisCommands, sha -> + redisCommands.evalsha(sha, ScriptOutputType.STATUS, keys, values)); } public CompletableFuture countService(String namespace) { diff --git a/govern-discovery/src/test/java/me/ahoo/govern/discovery/ConsistencyRedisServiceDiscoveryTest.java b/govern-discovery/src/test/java/me/ahoo/govern/discovery/ConsistencyRedisServiceDiscoveryTest.java index 319929b3..68b69d29 100644 --- a/govern-discovery/src/test/java/me/ahoo/govern/discovery/ConsistencyRedisServiceDiscoveryTest.java +++ b/govern-discovery/src/test/java/me/ahoo/govern/discovery/ConsistencyRedisServiceDiscoveryTest.java @@ -40,7 +40,6 @@ private void init() { consistencyRedisServiceDiscovery = new ConsistencyRedisServiceDiscovery(redisServiceDiscovery, new RedisMessageListenable(redisClient.connectPubSub())); } - @Test public void getServices() { registerRandomInstanceFinal(namespace, redisServiceRegistry, (instance -> { diff --git a/govern-spring-cloud-core/src/main/java/me/ahoo/govern/spring/cloud/GovernAutoConfiguration.java b/govern-spring-cloud-core/src/main/java/me/ahoo/govern/spring/cloud/GovernAutoConfiguration.java index 83d70348..5fe5eb40 100644 --- a/govern-spring-cloud-core/src/main/java/me/ahoo/govern/spring/cloud/GovernAutoConfiguration.java +++ b/govern-spring-cloud-core/src/main/java/me/ahoo/govern/spring/cloud/GovernAutoConfiguration.java @@ -5,6 +5,7 @@ import me.ahoo.govern.core.NamespacedContext; import me.ahoo.govern.core.listener.MessageListenable; import me.ahoo.govern.core.redis.RedisNamespaceService; +import me.ahoo.govern.core.redis.RedisScriptInitializer; import me.ahoo.govern.spring.cloud.support.RedisClientSupport; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -29,6 +30,12 @@ public AbstractRedisClient redisClient(GovernProperties governProperties) { return RedisClientSupport.redisClient(governProperties.getRedis()); } + @Bean + @ConditionalOnMissingBean + public RedisScriptInitializer redisScriptInitializer(AbstractRedisClient abstractRedisClient) { + return new RedisScriptInitializer(abstractRedisClient); + } + @Bean @ConditionalOnMissingBean public MessageListenable messageListenable(AbstractRedisClient redisClient) { diff --git a/gradle.properties b/gradle.properties index 9c02251a..08fcc9ed 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ group=me.ahoo.govern -version=0.9.19 +version=0.9.20 description=Govern Service On Redis website=https://github.com/Ahoo-Wang/govern-service diff --git a/k8s/deployment/govern-servce-rest-api.yml b/k8s/deployment/govern-servce-rest-api.yml index 29e442de..2e25cdb8 100644 --- a/k8s/deployment/govern-servce-rest-api.yml +++ b/k8s/deployment/govern-servce-rest-api.yml @@ -20,7 +20,7 @@ spec: value: standalone - name: GOVERN_REDIS_URI value: redis://redis-uri:6379 - image: ahoowang/govern-service:0.9.19 + image: ahoowang/govern-service:0.9.20 name: govern-service ports: - containerPort: 8080 diff --git a/k8s/docker/rest-api-local/Dockerfile b/k8s/docker/rest-api-local/Dockerfile index 3176d5a5..e62b527f 100644 --- a/k8s/docker/rest-api-local/Dockerfile +++ b/k8s/docker/rest-api-local/Dockerfile @@ -1,8 +1,8 @@ -# docker buildx build --push --platform linux/arm/v7 --build-arg GOVERN_VERSION=0.9.19 --build-arg JDK_VERSION=armv7l-centos-jdk-11.0.11_9-slim -t ahoowang/govern-service:0.9.19-armv7 . -# docker buildx build --push --platform linux/amd64,linux/arm64 --build-arg GOVERN_VERSION=0.9.19 --build-arg JDK_VERSION=jdk11u-centos-nightly-slim -t ahoowang/govern-service:0.9.19 . +# docker buildx build --push --platform linux/arm/v7 --build-arg GOVERN_VERSION=0.9.20 --build-arg JDK_VERSION=armv7l-centos-jdk-11.0.11_9-slim -t ahoowang/govern-service:0.9.20-armv7 . +# docker buildx build --push --platform linux/amd64,linux/arm64 --build-arg GOVERN_VERSION=0.9.20 --build-arg JDK_VERSION=jdk11u-centos-nightly-slim -t ahoowang/govern-service:0.9.20 . ARG JDK_VERSION=jdk11u-centos-nightly-slim -ARG GOVERN_VERSION=0.9.19 +ARG GOVERN_VERSION=0.9.20 ARG GOVERN_SERVICE_HOME=/govern-service FROM adoptopenjdk/openjdk11:${JDK_VERSION} AS base diff --git a/k8s/docker/rest-api/Dockerfile b/k8s/docker/rest-api/Dockerfile index 2b15872a..a6b47df6 100644 --- a/k8s/docker/rest-api/Dockerfile +++ b/k8s/docker/rest-api/Dockerfile @@ -1,8 +1,8 @@ -# docker buildx build --push --platform linux/arm/v7 --build-arg GOVERN_VERSION=0.9.19 --build-arg JDK_VERSION=armv7l-centos-jdk-11.0.11_9-slim -t ahoowang/govern-service:0.9.19-armv7 . -# docker buildx build --push --platform linux/amd64,linux/arm64 --build-arg GOVERN_VERSION=0.9.19 --build-arg JDK_VERSION=jdk11u-centos-nightly-slim -t ahoowang/govern-service:0.9.19 . +# docker buildx build --push --platform linux/arm/v7 --build-arg GOVERN_VERSION=0.9.20 --build-arg JDK_VERSION=armv7l-centos-jdk-11.0.11_9-slim -t ahoowang/govern-service:0.9.20-armv7 . +# docker buildx build --push --platform linux/amd64,linux/arm64 --build-arg GOVERN_VERSION=0.9.20 --build-arg JDK_VERSION=jdk11u-centos-nightly-slim -t ahoowang/govern-service:0.9.20 . ARG JDK_VERSION=jdk11u-centos-nightly -ARG GOVERN_VERSION=0.9.19 +ARG GOVERN_VERSION=0.9.20 ARG GOVERN_SERVICE_HOME=/govern-service FROM adoptopenjdk/openjdk11:${JDK_VERSION} AS base