From 37db08a2dc2a2b0ceb6c15ee8caedd291d4ff223 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=A9=AC=E5=BA=9C=E5=BC=BA?=
<8569561+fuqiangma@user.noreply.gitee.com>
Date: Sat, 11 Mar 2023 22:27:15 +0800
Subject: [PATCH] =?UTF-8?q?redis=E9=99=90=E6=B5=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
redis限流/pom.xml | 138 ++++++++++++++++++
.../feign/TLogFeignConsumerRunner.java | 19 +++
.../tlog/example/feign/aop/RedisLimit.java | 30 ++++
.../tlog/example/feign/aop/RedisLimitAop.java | 117 +++++++++++++++
.../feign/configuration/Log4j2Rule.java | 41 ++++++
.../feign/configuration/RedisConfig.java | 33 +++++
.../controller/LimitRedisController.java | 29 ++++
.../exception/GlobalExceptionHandler.java | 29 ++++
.../feign/exception/RedisLimitException.java | 12 ++
.../tlog/example/feign/vo/ResultInfo.java | 28 ++++
.../src/main/resources/application.properties | 19 +++
.../src/main/resources/rateLimiter.lua | 16 ++
.../core/config/plugins/Log4j2Plugins.dat | Bin 0 -> 111 bytes
.../target/classes/application.properties | 19 +++
.../feign/TLogFeignConsumerRunner.class | Bin 0 -> 880 bytes
.../tlog/example/feign/aop/RedisLimit.class | Bin 0 -> 658 bytes
.../example/feign/aop/RedisLimitAop.class | Bin 0 -> 4418 bytes
.../feign/configuration/Log4j2Rule.class | Bin 0 -> 1210 bytes
.../feign/configuration/RedisConfig.class | Bin 0 -> 1951 bytes
.../controller/LimitRedisController.class | Bin 0 -> 1239 bytes
.../exception/GlobalExceptionHandler.class | Bin 0 -> 1389 bytes
.../feign/exception/RedisLimitException.class | Bin 0 -> 434 bytes
.../tlog/example/feign/vo/ResultInfo.class | Bin 0 -> 1675 bytes
redis限流/target/classes/rateLimiter.lua | 16 ++
.../tlog-example-logback-feign-consumer.iml | 136 +++++++++++++++++
25 files changed, 682 insertions(+)
create mode 100644 redis限流/pom.xml
create mode 100644 redis限流/src/main/java/com/yomahub/tlog/example/feign/TLogFeignConsumerRunner.java
create mode 100644 redis限流/src/main/java/com/yomahub/tlog/example/feign/aop/RedisLimit.java
create mode 100644 redis限流/src/main/java/com/yomahub/tlog/example/feign/aop/RedisLimitAop.java
create mode 100644 redis限流/src/main/java/com/yomahub/tlog/example/feign/configuration/Log4j2Rule.java
create mode 100644 redis限流/src/main/java/com/yomahub/tlog/example/feign/configuration/RedisConfig.java
create mode 100644 redis限流/src/main/java/com/yomahub/tlog/example/feign/controller/LimitRedisController.java
create mode 100644 redis限流/src/main/java/com/yomahub/tlog/example/feign/exception/GlobalExceptionHandler.java
create mode 100644 redis限流/src/main/java/com/yomahub/tlog/example/feign/exception/RedisLimitException.java
create mode 100644 redis限流/src/main/java/com/yomahub/tlog/example/feign/vo/ResultInfo.java
create mode 100644 redis限流/src/main/resources/application.properties
create mode 100644 redis限流/src/main/resources/rateLimiter.lua
create mode 100644 redis限流/target/classes/META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat
create mode 100644 redis限流/target/classes/application.properties
create mode 100644 redis限流/target/classes/com/yomahub/tlog/example/feign/TLogFeignConsumerRunner.class
create mode 100644 redis限流/target/classes/com/yomahub/tlog/example/feign/aop/RedisLimit.class
create mode 100644 redis限流/target/classes/com/yomahub/tlog/example/feign/aop/RedisLimitAop.class
create mode 100644 redis限流/target/classes/com/yomahub/tlog/example/feign/configuration/Log4j2Rule.class
create mode 100644 redis限流/target/classes/com/yomahub/tlog/example/feign/configuration/RedisConfig.class
create mode 100644 redis限流/target/classes/com/yomahub/tlog/example/feign/controller/LimitRedisController.class
create mode 100644 redis限流/target/classes/com/yomahub/tlog/example/feign/exception/GlobalExceptionHandler.class
create mode 100644 redis限流/target/classes/com/yomahub/tlog/example/feign/exception/RedisLimitException.class
create mode 100644 redis限流/target/classes/com/yomahub/tlog/example/feign/vo/ResultInfo.class
create mode 100644 redis限流/target/classes/rateLimiter.lua
create mode 100644 redis限流/tlog-example-logback-feign-consumer.iml
diff --git a/redis限流/pom.xml b/redis限流/pom.xml
new file mode 100644
index 0000000..f74f39b
--- /dev/null
+++ b/redis限流/pom.xml
@@ -0,0 +1,138 @@
+
+
+
+
+
+ 8
+ 8
+ 2.1.8.RELEASE
+ Greenwich.SR3
+ 2.1.0.RELEASE
+ 1.8
+ 1.7.25
+ 2.12.0
+ 1.2.17
+ 1.6.1
+ 2.7.6
+ 2.8.4
+ 4.0.1
+ 3.4.6
+ 0.1
+ 1.0.0
+ 1.5.0
+
+
+ 4.0.0
+ com.yomahub.tlog.example
+ tlog-example-logback-feign-consumer
+ 1.0
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-logging
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-log4j2
+
+
+
+ com.google.guava
+ guava
+ 30.1-jre
+
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+
+
+
+
+
+
+
+ com.yomahub
+ tlog-feign-spring-boot-starter
+ ${tlog.version}
+
+
+ com.yomahub
+ tlog-web-spring-boot-starter
+ ${tlog.version}
+
+
+ org.projectlombok
+ lombok
+
+
+ junit
+ junit
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ ${spring-boot.version}
+ pom
+ import
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+ com.alibaba.cloud
+ spring-cloud-alibaba-dependencies
+ ${spring-cloud-alibaba.version}
+ pom
+ import
+
+
+
+
+ log4j
+ log4j
+ ${log4j.version}
+
+
+ org.slf4j
+ slf4j-api
+ ${slf4j.version}
+
+
+
+
+
+
diff --git a/redis限流/src/main/java/com/yomahub/tlog/example/feign/TLogFeignConsumerRunner.java b/redis限流/src/main/java/com/yomahub/tlog/example/feign/TLogFeignConsumerRunner.java
new file mode 100644
index 0000000..b44c806
--- /dev/null
+++ b/redis限流/src/main/java/com/yomahub/tlog/example/feign/TLogFeignConsumerRunner.java
@@ -0,0 +1,19 @@
+package com.yomahub.tlog.example.feign;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+@SpringBootApplication
+@EnableFeignClients
+//@EnableDiscoveryClient
+@EnableAsync
+public class TLogFeignConsumerRunner {
+
+ public static void main(String[] args) {
+ SpringApplication.run(TLogFeignConsumerRunner.class, args);
+
+ }
+}
diff --git a/redis限流/src/main/java/com/yomahub/tlog/example/feign/aop/RedisLimit.java b/redis限流/src/main/java/com/yomahub/tlog/example/feign/aop/RedisLimit.java
new file mode 100644
index 0000000..aa83e6a
--- /dev/null
+++ b/redis限流/src/main/java/com/yomahub/tlog/example/feign/aop/RedisLimit.java
@@ -0,0 +1,30 @@
+package com.yomahub.tlog.example.feign.aop;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+@Documented
+public @interface RedisLimit {
+ /**
+ * 资源的key,唯一
+ * 作用:不同的接口,不同的流量控制
+ */
+ String key() default "";
+
+ /**
+ * 最多的访问限制次数
+ */
+ long permitsPerSecond() default 2;
+
+ /**
+ * 过期时间也可以理解为单位时间,单位秒,默认60
+ */
+ long expire() default 60;
+
+
+ /**
+ * 得不到令牌的提示语
+ */
+ String msg() default "系统繁忙,请稍后再试.";
+}
diff --git a/redis限流/src/main/java/com/yomahub/tlog/example/feign/aop/RedisLimitAop.java b/redis限流/src/main/java/com/yomahub/tlog/example/feign/aop/RedisLimitAop.java
new file mode 100644
index 0000000..a739dba
--- /dev/null
+++ b/redis限流/src/main/java/com/yomahub/tlog/example/feign/aop/RedisLimitAop.java
@@ -0,0 +1,117 @@
+package com.yomahub.tlog.example.feign.aop;
+
+import com.yomahub.tlog.example.feign.exception.RedisLimitException;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.data.redis.core.script.DefaultRedisScript;
+import org.springframework.data.redis.core.script.RedisScript;
+import org.springframework.scripting.support.ResourceScriptSource;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Limit AOP
+ */
+@Slf4j
+@Aspect
+@Component
+public class RedisLimitAop {
+
+ @Autowired
+ private StringRedisTemplate stringRedisTemplate;
+
+
+ @Pointcut("@annotation(com.yomahub.tlog.example.feign.aop.RedisLimit)")
+ private void check() {
+
+ }
+
+ private DefaultRedisScript redisScript;
+
+ @PostConstruct
+ public void init() {
+ redisScript = new DefaultRedisScript<>();
+ redisScript.setResultType(Long.class);
+ redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("rateLimiter.lua")));
+ }
+
+
+ @Before("check()")
+ public void before(JoinPoint joinPoint) {
+ MethodSignature signature = (MethodSignature) joinPoint.getSignature();
+ Method method = signature.getMethod();
+
+ //拿到RedisLimit注解,如果存在则说明需要限流
+ RedisLimit redisLimit = method.getAnnotation(RedisLimit.class);
+
+ if (redisLimit != null) {
+ //获取redis的key
+ String key = redisLimit.key();
+ String className = method.getDeclaringClass().getName();
+ String name = method.getName();
+
+ String limitKey = key + className + method.getName();
+
+ log.info(limitKey);
+
+ if (StringUtils.isEmpty(key)) {
+ throw new RedisLimitException("key cannot be null");
+ }
+
+ long limit = redisLimit.permitsPerSecond();
+
+ long expire = redisLimit.expire();
+
+ List keys = new ArrayList<>();
+ keys.add(key);
+
+ Long count = stringRedisTemplate.execute(redisScript, keys, String.valueOf(limit), String.valueOf(expire));
+
+ log.info("Access try count is {} for key={}", count, key);
+
+ if (count != null && count == 0) {
+ log.debug("获取key失败,key为{}", key);
+ throw new RedisLimitException(redisLimit.msg());
+ }
+ }
+
+ }
+
+// /**
+// * 构建redis lua脚本
+// *
+// * @return
+// */
+// private String buildLuaScript() {
+// StringBuilder luaString = new StringBuilder();
+// luaString.append("local key = KEYS[1]");
+// //获取ARGV内参数Limit
+// luaString.append("\nlocal limit = tonumber(ARGV[1])");
+// //获取key的次数
+// luaString.append("\nlocal curentLimit = tonumber(redis.call('get', key) or '0')");
+// luaString.append("\nif curentLimit + 1 > limit then");
+// luaString.append("\nreturn 0");
+// luaString.append("\nelse");
+// //自增长 1
+// luaString.append("\n redis.call('INCRBY', key, 1)");
+// //设置过期时间
+// luaString.append("\nredis.call('EXPIRE', key, ARGV[2])");
+// luaString.append("\nend");
+// return luaString.toString();
+// }
+//
+
+
+}
\ No newline at end of file
diff --git a/redis限流/src/main/java/com/yomahub/tlog/example/feign/configuration/Log4j2Rule.java b/redis限流/src/main/java/com/yomahub/tlog/example/feign/configuration/Log4j2Rule.java
new file mode 100644
index 0000000..701b441
--- /dev/null
+++ b/redis限流/src/main/java/com/yomahub/tlog/example/feign/configuration/Log4j2Rule.java
@@ -0,0 +1,41 @@
+package com.yomahub.tlog.example.feign.configuration;
+
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 现在拦截加密的日志有三类:
+ * 1,身份证
+ * 2,姓名
+ * 3,身份证号
+ * 加密的规则后续可以优化在配置文件中
+ **/
+public class Log4j2Rule {
+
+ /**
+ * 正则匹配 关键词 类别
+ */
+ public static Map regularMap = new HashMap<>();
+ /**
+ * TODO 可配置
+ * 此项可以后期放在配置项中
+ */
+ public static final String USER_NAME_STR = "Name,name,联系人,姓名";
+ public static final String USER_IDCARD_STR = "empCard,idCard,身份证,证件号";
+ public static final String USER_PHONE_STR = "mobile,Phone,phone,电话,手机";
+
+ /**
+ * 正则匹配,自己根据业务要求自定义
+ */
+ private static String IDCARD_REGEXP = "(\\d{17}[0-9Xx]|\\d{14}[0-9Xx])";
+ private static String USERNAME_REGEXP = "[\\u4e00-\\u9fa5]{2,4}";
+ private static String PHONE_REGEXP = "(? redisTemplate(RedisConnectionFactory factory) {
+ RedisTemplate template = new RedisTemplate<>();
+ template.setConnectionFactory(factory);
+ // 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
+ Jackson2JsonRedisSerializer