From 142c0fff1db7f26def837bef29372d113c483689 Mon Sep 17 00:00:00 2001 From: lijiahang Date: Thu, 25 Apr 2024 19:00:12 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20=E6=B7=BB=E5=8A=A0=E5=88=86?= =?UTF-8?q?=E5=B8=83=E5=BC=8F=E9=94=81=E7=BB=84=E4=BB=B6.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/about/change-log.md | 5 +- docs/quickstart/faq.md | 2 +- .../OrionRedisAutoConfiguration.java | 14 ++++ .../redis/core/lock/RedisLocker.java | 74 +++++++++++++++++++ .../redis/core/utils/RedisLocks.java | 55 ++++++++++++++ .../src/main/resources/application.yaml | 8 +- .../asset/define/config/AppExecLogConfig.java | 8 +- .../CommandSnippetGroupAutoClearTask.java | 25 +------ .../asset/task/ExecLogFileAutoClearTask.java | 28 ++----- .../task/PathBookmarkGroupAutoClearTask.java | 25 +------ .../spring-configuration-metadata.json | 6 +- .../mapper/PathBookmarkMapper.xml | 0 .../module/infra/task/TagAutoClearTask.java | 27 ++----- 13 files changed, 176 insertions(+), 101 deletions(-) create mode 100644 orion-ops-framework/orion-ops-spring-boot-starter-redis/src/main/java/com/orion/ops/framework/redis/core/lock/RedisLocker.java create mode 100644 orion-ops-framework/orion-ops-spring-boot-starter-redis/src/main/java/com/orion/ops/framework/redis/core/utils/RedisLocks.java rename orion-ops-module-asset/orion-ops-module-asset-service/src/main/{java/com/orion/ops/module/asset => resources}/mapper/PathBookmarkMapper.xml (100%) diff --git a/docs/about/change-log.md b/docs/about/change-log.md index 3e117daf..cc7ddf09 100644 --- a/docs/about/change-log.md +++ b/docs/about/change-log.md @@ -11,13 +11,14 @@ * 🩰 修改 命令执行日志 UI 修改 * 🌈 新增 命令执行模板配置默认主机 * 🌈 新增 主机终端书签路径 -* 🌈 新增 命令日志添加状态信息 `app.exec-log.append-status` -* 🌈 新增 定时删除命令日志文件 `app.exec-log.auto-clear` +* 🌈 新增 命令执行日志添加 `ansi` 日志 `app.exec-log.append-ansi` +* 🌈 新增 定时删除命令执行日志文件 `app.exec-log.auto-clear` * 🔨 优化 通用分组模型添加 `userId` * 🔨 优化 退出登录不重定向 * 🔨 优化 动态设置页面标题 * 🔨 优化 终端断开后回车重连 * 🔨 优化 自动删除未使用的命令片段分组 +* 🔨 优化 添加分布式锁工具类 ## v1.0.5 diff --git a/docs/quickstart/faq.md b/docs/quickstart/faq.md index f877a754..0d28dcd9 100644 --- a/docs/quickstart/faq.md +++ b/docs/quickstart/faq.md @@ -19,7 +19,7 @@ > ##### 5. 调度任务、批量执行 的日志文件中如何只保存原始输出? -修改 application.yaml `app.exec-log.append-status` 为 false +修改 application.yaml `app.exec-log.append-ansi` 为 false > ##### 6. 为什么使用秘钥认证还是无法连接机器? diff --git a/orion-ops-framework/orion-ops-spring-boot-starter-redis/src/main/java/com/orion/ops/framework/redis/configuration/OrionRedisAutoConfiguration.java b/orion-ops-framework/orion-ops-spring-boot-starter-redis/src/main/java/com/orion/ops/framework/redis/configuration/OrionRedisAutoConfiguration.java index 09f8803c..f1e52e20 100644 --- a/orion-ops-framework/orion-ops-spring-boot-starter-redis/src/main/java/com/orion/ops/framework/redis/configuration/OrionRedisAutoConfiguration.java +++ b/orion-ops-framework/orion-ops-spring-boot-starter-redis/src/main/java/com/orion/ops/framework/redis/configuration/OrionRedisAutoConfiguration.java @@ -2,7 +2,10 @@ package com.orion.ops.framework.redis.configuration; import com.orion.ops.framework.common.constant.AutoConfigureOrderConst; import com.orion.ops.framework.redis.configuration.config.RedissonConfig; +import com.orion.ops.framework.redis.core.lock.RedisLocker; +import com.orion.ops.framework.redis.core.utils.RedisLocks; import com.orion.ops.framework.redis.core.utils.RedisUtils; +import org.redisson.api.RedissonClient; import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigureOrder; @@ -56,5 +59,16 @@ public class OrionRedisAutoConfiguration { }; } + /** + * @param redissonClient redissonClient + * @return redis 分布式锁 + */ + @Bean + public RedisLocker redisLocker(RedissonClient redissonClient) { + RedisLocker redisLocker = new RedisLocker(redissonClient); + RedisLocks.setRedisLocker(redisLocker); + return redisLocker; + } + } diff --git a/orion-ops-framework/orion-ops-spring-boot-starter-redis/src/main/java/com/orion/ops/framework/redis/core/lock/RedisLocker.java b/orion-ops-framework/orion-ops-spring-boot-starter-redis/src/main/java/com/orion/ops/framework/redis/core/lock/RedisLocker.java new file mode 100644 index 00000000..62d7b210 --- /dev/null +++ b/orion-ops-framework/orion-ops-spring-boot-starter-redis/src/main/java/com/orion/ops/framework/redis/core/lock/RedisLocker.java @@ -0,0 +1,74 @@ +package com.orion.ops.framework.redis.core.lock; + +import com.orion.lang.utils.Exceptions; +import lombok.extern.slf4j.Slf4j; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; + +import java.util.function.Supplier; + +/** + * redis 分布式锁 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2024/4/25 16:42 + */ +@Slf4j +public class RedisLocker { + + private final RedissonClient redissonClient; + + public RedisLocker(RedissonClient redissonClient) { + this.redissonClient = redissonClient; + } + + /** + * 尝试获取锁 + * + * @param key key + * @param run run + * @return 是否获取到锁 + */ + public boolean tryLock(String key, Runnable run) { + // 获取锁 + RLock lock = redissonClient.getLock(key); + // 未获取到直接返回 + if (!lock.tryLock()) { + log.info("RedisLocks.tryLock failed {}", key); + return false; + } + // 执行 + try { + run.run(); + } finally { + lock.unlock(); + } + return true; + } + + /** + * 尝试获取锁 + * + * @param key key + * @param call call + * @param T + * @return 执行结果 + */ + public T tryLock(String key, Supplier call) { + // 获取锁 + RLock lock = redissonClient.getLock(key); + // 未获取到直接返回 + if (!lock.tryLock()) { + log.info("RedisLocks.tryLock failed {}", key); + throw Exceptions.lock(); + } + // 执行 + try { + return call.get(); + } finally { + lock.unlock(); + } + } + +} diff --git a/orion-ops-framework/orion-ops-spring-boot-starter-redis/src/main/java/com/orion/ops/framework/redis/core/utils/RedisLocks.java b/orion-ops-framework/orion-ops-spring-boot-starter-redis/src/main/java/com/orion/ops/framework/redis/core/utils/RedisLocks.java new file mode 100644 index 00000000..40943de0 --- /dev/null +++ b/orion-ops-framework/orion-ops-spring-boot-starter-redis/src/main/java/com/orion/ops/framework/redis/core/utils/RedisLocks.java @@ -0,0 +1,55 @@ +package com.orion.ops.framework.redis.core.utils; + +import com.orion.lang.utils.Exceptions; +import com.orion.ops.framework.redis.core.lock.RedisLocker; +import lombok.extern.slf4j.Slf4j; + +import java.util.function.Supplier; + +/** + * redis 分布式锁工具类 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2024/4/25 16:42 + */ +@Slf4j +public class RedisLocks { + + private static RedisLocker redisLocker; + + private RedisLocks() { + } + + /** + * 尝试获取锁 + * + * @param key key + * @param run run + * @return 是否获取到锁 + */ + public static boolean tryLock(String key, Runnable run) { + return redisLocker.tryLock(key, run); + } + + /** + * 尝试获取锁 + * + * @param key key + * @param call call + * @param T + * @return 执行结果 + */ + public static T tryLock(String key, Supplier call) { + return redisLocker.tryLock(key, call); + } + + public static void setRedisLocker(RedisLocker redisLocker) { + if (RedisLocks.redisLocker != null) { + // unmodified + throw Exceptions.state(); + } + RedisLocks.redisLocker = redisLocker; + } + +} diff --git a/orion-ops-launch/src/main/resources/application.yaml b/orion-ops-launch/src/main/resources/application.yaml index d5d53a71..6a09d409 100644 --- a/orion-ops-launch/src/main/resources/application.yaml +++ b/orion-ops-launch/src/main/resources/application.yaml @@ -179,12 +179,12 @@ app: backup-file-name: bk_${fileName}_${timestamp} # 执行日志 exec-log: - # 是否拼接执行状态 - append-status: true + # 是否拼接 ansi 执行状态日志 + append-ansi: true # 自动清理执行文件 auto-clear: true - # 保留周期 - keep-period: 0 + # 保留周期 (天) + keep-period: 60 # orion framework config orion: diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/define/config/AppExecLogConfig.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/define/config/AppExecLogConfig.java index 3c1493f3..3f6ca69e 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/define/config/AppExecLogConfig.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/define/config/AppExecLogConfig.java @@ -17,9 +17,9 @@ import org.springframework.stereotype.Component; public class AppExecLogConfig { /** - * 是否拼接执行状态 + * 是否拼接 ansi 执行状态日志 */ - private Boolean appendStatus; + private Boolean appendAnsi; /** * 自动清理执行文件 @@ -32,9 +32,9 @@ public class AppExecLogConfig { private Integer keepPeriod; public AppExecLogConfig() { - this.appendStatus = true; + this.appendAnsi = true; this.autoClear = true; - this.keepPeriod = 90; + this.keepPeriod = 60; } } diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/task/CommandSnippetGroupAutoClearTask.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/task/CommandSnippetGroupAutoClearTask.java index 80883151..322a0816 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/task/CommandSnippetGroupAutoClearTask.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/task/CommandSnippetGroupAutoClearTask.java @@ -1,9 +1,8 @@ package com.orion.ops.module.asset.task; +import com.orion.ops.framework.redis.core.utils.RedisLocks; import com.orion.ops.module.asset.service.CommandSnippetGroupService; import lombok.extern.slf4j.Slf4j; -import org.redisson.api.RLock; -import org.redisson.api.RedissonClient; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @@ -25,9 +24,6 @@ public class CommandSnippetGroupAutoClearTask { */ private static final String LOCK_KEY = "clear:csg:lock"; - @Resource - private RedissonClient redissonClient; - @Resource private CommandSnippetGroupService commandSnippetGroupService; @@ -37,22 +33,9 @@ public class CommandSnippetGroupAutoClearTask { @Scheduled(cron = "0 10 2 * * ?") public void clear() { log.info("CommandSnippetGroupAutoClearTask.clear start"); - // 获取锁 - RLock lock = redissonClient.getLock(LOCK_KEY); - // 未获取到直接返回 - if (!lock.tryLock()) { - log.info("CommandSnippetGroupAutoClearTask.clear locked end"); - return; - } - try { - // 清理 - commandSnippetGroupService.clearUnusedGroup(); - log.info("CommandSnippetGroupAutoClearTask.clear finish"); - } catch (Exception e) { - log.error("CommandSnippetGroupAutoClearTask.clear error", e); - } finally { - lock.unlock(); - } + // 获取锁并清理 + RedisLocks.tryLock(LOCK_KEY, commandSnippetGroupService::clearUnusedGroup); + log.info("CommandSnippetGroupAutoClearTask.clear finish"); } } diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/task/ExecLogFileAutoClearTask.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/task/ExecLogFileAutoClearTask.java index 1e2f89ae..04d3ef7c 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/task/ExecLogFileAutoClearTask.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/task/ExecLogFileAutoClearTask.java @@ -4,12 +4,11 @@ import com.orion.lang.utils.Strings; import com.orion.lang.utils.io.Files1; import com.orion.lang.utils.time.Dates; import com.orion.ops.framework.common.file.FileClient; +import com.orion.ops.framework.redis.core.utils.RedisLocks; import com.orion.ops.module.asset.dao.ExecHostLogDAO; import com.orion.ops.module.asset.define.config.AppExecLogConfig; import com.orion.ops.module.asset.entity.domain.ExecHostLogDO; import lombok.extern.slf4j.Slf4j; -import org.redisson.api.RLock; -import org.redisson.api.RedissonClient; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @@ -38,9 +37,6 @@ public class ExecLogFileAutoClearTask { @Resource private AppExecLogConfig appExecLogConfig; - @Resource - private RedissonClient redissonClient; - @Resource private FileClient logsFileClient; @@ -50,26 +46,12 @@ public class ExecLogFileAutoClearTask { /** * 清理 */ - // @Scheduled(cron = "0 0 3 * * ?") - @Scheduled(fixedRate = 20000) + @Scheduled(cron = "0 0 3 * * ?") public void clear() { log.info("ExecLogFileAutoClearTask.clear start"); - // 获取锁 - RLock lock = redissonClient.getLock(LOCK_KEY); - // 未获取到直接返回 - if (!lock.tryLock()) { - log.info("ExecLogFileAutoClearTask.clear locked end"); - return; - } - try { - // 清理 - this.doClearFile(); - log.info("ExecLogFileAutoClearTask.clear finish"); - } catch (Exception e) { - log.error("ExecLogFileAutoClearTask.clear error", e); - } finally { - lock.unlock(); - } + // 获取锁并且执行 + RedisLocks.tryLock(LOCK_KEY, this::doClearFile); + log.info("ExecLogFileAutoClearTask.clear finish"); } /** diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/task/PathBookmarkGroupAutoClearTask.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/task/PathBookmarkGroupAutoClearTask.java index 17fc86f8..7c925892 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/task/PathBookmarkGroupAutoClearTask.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/task/PathBookmarkGroupAutoClearTask.java @@ -1,9 +1,8 @@ package com.orion.ops.module.asset.task; +import com.orion.ops.framework.redis.core.utils.RedisLocks; import com.orion.ops.module.asset.service.PathBookmarkGroupService; import lombok.extern.slf4j.Slf4j; -import org.redisson.api.RLock; -import org.redisson.api.RedissonClient; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @@ -25,9 +24,6 @@ public class PathBookmarkGroupAutoClearTask { */ private static final String LOCK_KEY = "clear:pbg:lock"; - @Resource - private RedissonClient redissonClient; - @Resource private PathBookmarkGroupService pathBookmarkGroupService; @@ -37,22 +33,9 @@ public class PathBookmarkGroupAutoClearTask { @Scheduled(cron = "0 20 2 * * ?") public void clear() { log.info("PathBookmarkGroupAutoClearTask.clear start"); - // 获取锁 - RLock lock = redissonClient.getLock(LOCK_KEY); - // 未获取到直接返回 - if (!lock.tryLock()) { - log.info("PathBookmarkGroupAutoClearTask.clear locked end"); - return; - } - try { - // 清理 - pathBookmarkGroupService.clearUnusedGroup(); - log.info("PathBookmarkGroupAutoClearTask.clear finish"); - } catch (Exception e) { - log.error("PathBookmarkGroupAutoClearTask.clear error", e); - } finally { - lock.unlock(); - } + // 获取锁并清理 + RedisLocks.tryLock(LOCK_KEY, pathBookmarkGroupService::clearUnusedGroup); + log.info("PathBookmarkGroupAutoClearTask.clear finish"); } } diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/resources/META-INF/spring-configuration-metadata.json b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/resources/META-INF/spring-configuration-metadata.json index c8cf99a7..210f2c39 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/resources/META-INF/spring-configuration-metadata.json +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/resources/META-INF/spring-configuration-metadata.json @@ -48,9 +48,9 @@ "defaultValue": "bk_${fileName}_${timestamp}" }, { - "name": "app.exec-log.append-status", + "name": "app.exec-log.append-ansi", "type": "java.lang.Boolean", - "description": "是否拼接执行状态.", + "description": "是否拼接 ansi 执行状态日志.", "defaultValue": "true" }, { @@ -63,7 +63,7 @@ "name": "app.exec-log.keep-period", "type": "java.lang.Integer", "description": "保留周期 (天)", - "defaultValue": "90" + "defaultValue": "60" } ] } \ No newline at end of file diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/mapper/PathBookmarkMapper.xml b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/resources/mapper/PathBookmarkMapper.xml similarity index 100% rename from orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/mapper/PathBookmarkMapper.xml rename to orion-ops-module-asset/orion-ops-module-asset-service/src/main/resources/mapper/PathBookmarkMapper.xml diff --git a/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/task/TagAutoClearTask.java b/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/task/TagAutoClearTask.java index b82abb33..bf622d0e 100644 --- a/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/task/TagAutoClearTask.java +++ b/orion-ops-module-infra/orion-ops-module-infra-service/src/main/java/com/orion/ops/module/infra/task/TagAutoClearTask.java @@ -1,9 +1,8 @@ package com.orion.ops.module.infra.task; +import com.orion.ops.framework.redis.core.utils.RedisLocks; import com.orion.ops.module.infra.service.TagService; import lombok.extern.slf4j.Slf4j; -import org.redisson.api.RLock; -import org.redisson.api.RedissonClient; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @@ -25,34 +24,18 @@ public class TagAutoClearTask { */ private static final String LOCK_KEY = "clear:tag:lock"; - @Resource - private RedissonClient redissonClient; - @Resource private TagService tagService; /** - * 定时清理未引用的 tag + * 清理 */ @Scheduled(cron = "0 0 2 * * ?") public void clear() { log.info("TagAutoClearTask.clear start"); - // 获取锁 - RLock lock = redissonClient.getLock(LOCK_KEY); - // 未获取到直接返回 - if (!lock.tryLock()) { - log.info("TagAutoClearTask.clear locked end"); - return; - } - try { - // 清理 - tagService.clearUnusedTag(); - log.info("TagAutoClearTask.clear finish"); - } catch (Exception e) { - log.error("TagAutoClearTask.clear error", e); - } finally { - lock.unlock(); - } + // 获取锁并清理 + RedisLocks.tryLock(LOCK_KEY, tagService::clearUnusedTag); + log.info("TagAutoClearTask.clear finish"); } }