diff --git a/ruoyi-extend/ruoyi-isc-gateway/pom.xml b/ruoyi-extend/ruoyi-isc-gateway/pom.xml
index d6fc777cf..4df6d0639 100644
--- a/ruoyi-extend/ruoyi-isc-gateway/pom.xml
+++ b/ruoyi-extend/ruoyi-isc-gateway/pom.xml
@@ -20,26 +20,23 @@
org.springframework.boot
spring-boot-starter-data-redis
-
-
- io.lettuce
- lettuce-core
-
-
- redis.clients
- jedis
+ org.redisson
+ redisson-spring-boot-starter
-
-
de.codecentric
spring-boot-admin-starter-client
+
+ org.projectlombok
+ lombok
+
+
+ cn.hutool
+ hutool-all
+
-
\ No newline at end of file
+
diff --git a/ruoyi-extend/ruoyi-isc-gateway/src/main/java/com/ruoyi/gateway/config/GatewayConfig.java b/ruoyi-extend/ruoyi-isc-gateway/src/main/java/com/ruoyi/gateway/config/GatewayConfig.java
index cc0eec028..678d3cb35 100644
--- a/ruoyi-extend/ruoyi-isc-gateway/src/main/java/com/ruoyi/gateway/config/GatewayConfig.java
+++ b/ruoyi-extend/ruoyi-isc-gateway/src/main/java/com/ruoyi/gateway/config/GatewayConfig.java
@@ -1,8 +1,7 @@
package com.ruoyi.gateway.config;
-import com.ruoyi.gateway.config.provider.ComplexRouteDefinitionRepository;
import com.ruoyi.gateway.config.provider.RedisRouteDefinitionRepository;
-import org.springframework.cloud.gateway.route.InMemoryRouteDefinitionRepository;
+import org.redisson.api.RedissonClient;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.context.annotation.Bean;
@@ -21,10 +20,13 @@ import javax.annotation.Resource;
* @date 2021-09-11
*/
@Configuration
-public class GatewayConfig {
+public class GatewayConfig
+{
@Resource
private RedisTemplate redisTemplate;
+ @Resource
+ private RedissonClient redissonClient;
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory)
@@ -40,29 +42,14 @@ public class GatewayConfig {
return template;
}
- @Bean
- public RouteDefinitionRepository complexRouteDefinitionRepository()
- {
- return new ComplexRouteDefinitionRepository(inMemoryRouteDefinitionRepository(), redisRouteDefinitionRepository());
- }
-
- /**
- * 内存 路由仓库
- *
- * @return 本地内存路由仓库
- */
- RouteDefinitionRepository inMemoryRouteDefinitionRepository()
- {
- return new InMemoryRouteDefinitionRepository();
- }
-
/**
* Redis 路由仓库
*
* @return redis路由仓库
*/
- RouteDefinitionRepository redisRouteDefinitionRepository()
+ @Bean
+ public RouteDefinitionRepository redisRouteDefinitionRepository()
{
- return new RedisRouteDefinitionRepository(redisTemplate);
+ return new RedisRouteDefinitionRepository(redissonClient);
}
}
diff --git a/ruoyi-extend/ruoyi-isc-gateway/src/main/java/com/ruoyi/gateway/config/RedisConfig.java b/ruoyi-extend/ruoyi-isc-gateway/src/main/java/com/ruoyi/gateway/config/RedisConfig.java
new file mode 100644
index 000000000..adc4f28da
--- /dev/null
+++ b/ruoyi-extend/ruoyi-isc-gateway/src/main/java/com/ruoyi/gateway/config/RedisConfig.java
@@ -0,0 +1,104 @@
+package com.ruoyi.gateway.config;
+
+import cn.hutool.core.util.StrUtil;
+import com.ruoyi.gateway.config.provider.RedissonProperties;
+import lombok.extern.slf4j.Slf4j;
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.codec.JsonJacksonCodec;
+import org.redisson.config.Config;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
+import org.springframework.cache.annotation.CachingConfigurerSupport;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.core.script.DefaultRedisScript;
+
+import java.io.IOException;
+
+/**
+ * redis配置
+ *
+ * @author Lion Li
+ */
+@Slf4j
+@Configuration
+@EnableCaching
+public class RedisConfig extends CachingConfigurerSupport {
+
+ private static final String REDIS_PROTOCOL_PREFIX = "redis://";
+ private static final String REDISS_PROTOCOL_PREFIX = "rediss://";
+
+ @Autowired
+ private RedisProperties redisProperties;
+
+ @Autowired
+ private RedissonProperties redissonProperties;
+
+ @Bean(destroyMethod = "shutdown")
+ @ConditionalOnMissingBean(RedissonClient.class)
+ public RedissonClient redisson() throws IOException {
+ String prefix = REDIS_PROTOCOL_PREFIX;
+ if (redisProperties.isSsl()) {
+ prefix = REDISS_PROTOCOL_PREFIX;
+ }
+ Config config = new Config();
+ config.setThreads(redissonProperties.getThreads())
+ .setNettyThreads(redissonProperties.getNettyThreads())
+ .setCodec(JsonJacksonCodec.INSTANCE)
+ .setTransportMode(redissonProperties.getTransportMode());
+
+ RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig();
+ // 使用单机模式
+ config.useSingleServer()
+ .setAddress(prefix + redisProperties.getHost() + ":" + redisProperties.getPort())
+ .setConnectTimeout(((Long) redisProperties.getTimeout().toMillis()).intValue())
+ .setDatabase(redisProperties.getDatabase())
+ .setPassword(StrUtil.isNotBlank(redisProperties.getPassword()) ? redisProperties.getPassword() : null)
+ .setTimeout(singleServerConfig.getTimeout())
+ .setRetryAttempts(singleServerConfig.getRetryAttempts())
+ .setRetryInterval(singleServerConfig.getRetryInterval())
+ .setSubscriptionsPerConnection(singleServerConfig.getSubscriptionsPerConnection())
+ .setClientName(singleServerConfig.getClientName())
+ .setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout())
+ .setSubscriptionConnectionMinimumIdleSize(singleServerConfig.getSubscriptionConnectionMinimumIdleSize())
+ .setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize())
+ .setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize())
+ .setConnectionPoolSize(singleServerConfig.getConnectionPoolSize())
+ .setDnsMonitoringInterval(singleServerConfig.getDnsMonitoringInterval());
+ RedissonClient redissonClient = Redisson.create(config);
+ log.info("初始化 redis 配置");
+ return redissonClient;
+ }
+
+ @Bean
+ public DefaultRedisScript limitScript() {
+ DefaultRedisScript redisScript = new DefaultRedisScript<>();
+ redisScript.setScriptText(limitScriptText());
+ redisScript.setResultType(Long.class);
+ return redisScript;
+ }
+
+ /**
+ * 限流脚本
+ */
+ private String limitScriptText() {
+ return StrUtil.builder()
+ .append("local key = KEYS[1]\n")
+ .append("local count = tonumber(ARGV[1])\n")
+ .append("local time = tonumber(ARGV[2])\n")
+ .append("local current = redis.call('get', key);\n")
+ .append("if current and tonumber(current) > count then\n")
+ .append(" return current;\n")
+ .append("end\n")
+ .append("current = redis.call('incr', key)\n")
+ .append("if tonumber(current) == 1 then\n")
+ .append(" redis.call('expire', key, time)\n")
+ .append("end\n")
+ .append("return current;")
+ .toString();
+ }
+
+}
diff --git a/ruoyi-extend/ruoyi-isc-gateway/src/main/java/com/ruoyi/gateway/config/provider/ComplexRouteDefinitionRepository.java b/ruoyi-extend/ruoyi-isc-gateway/src/main/java/com/ruoyi/gateway/config/provider/ComplexRouteDefinitionRepository.java
deleted file mode 100644
index 70af9a671..000000000
--- a/ruoyi-extend/ruoyi-isc-gateway/src/main/java/com/ruoyi/gateway/config/provider/ComplexRouteDefinitionRepository.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.ruoyi.gateway.config.provider;
-
-import org.springframework.cloud.gateway.route.RouteDefinition;
-import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-
-import java.util.List;
-import java.util.Objects;
-
-/**
- * 复合的路由存储器
- *
- * @author Wenchao Gong
- * @date 2021-09-11
- */
-public class ComplexRouteDefinitionRepository implements RouteDefinitionRepository {
-
- private RouteDefinitionRepository localCache;
- private RouteDefinitionRepository remoteReps;
-
- public ComplexRouteDefinitionRepository(RouteDefinitionRepository localCache, RouteDefinitionRepository remoteReps)
- {
- this.localCache = localCache;
- this.remoteReps = remoteReps;
- }
-
-
- @Override
- public Flux getRouteDefinitions()
- {
- final Flux routeDefinitions = localCache.getRouteDefinitions();
- return routeDefinitions.collectList().flatMapIterable(list -> {
- if(list.isEmpty()) {
- final Flux definitions = remoteReps.getRouteDefinitions();
- definitions.collectList().flatMapIterable(routes -> {
- if(!routes.isEmpty()) {
- routes.stream().map(m -> {
- routes.add(m);
- return Mono.just(m);
- }).forEach(m -> {
- localCache.save(m);
- });
- }
- return routes;
- }).filter(l -> Objects.nonNull(l)).map(m -> list.add(m)).collectList();
- }
- return list;
- });
- }
-
- @Override
- public Mono save(Mono route)
- {
- remoteReps.save(route);
- return localCache.save(route);
- }
-
- @Override
- public Mono delete(Mono routeId)
- {
- remoteReps.delete(routeId);
- return localCache.delete(routeId);
- }
-}
diff --git a/ruoyi-extend/ruoyi-isc-gateway/src/main/java/com/ruoyi/gateway/config/provider/RedisRouteDefinitionRepository.java b/ruoyi-extend/ruoyi-isc-gateway/src/main/java/com/ruoyi/gateway/config/provider/RedisRouteDefinitionRepository.java
index fd8fc1beb..e1f1a0726 100644
--- a/ruoyi-extend/ruoyi-isc-gateway/src/main/java/com/ruoyi/gateway/config/provider/RedisRouteDefinitionRepository.java
+++ b/ruoyi-extend/ruoyi-isc-gateway/src/main/java/com/ruoyi/gateway/config/provider/RedisRouteDefinitionRepository.java
@@ -1,40 +1,41 @@
package com.ruoyi.gateway.config.provider;
+import org.redisson.api.RMap;
+import org.redisson.api.RedissonClient;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
-import org.springframework.data.redis.core.RedisTemplate;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
-import java.util.List;
-
/**
* Redis 路由仓库
*
* @author Wenchao Gong
* @date 2021-09-11
*/
-public class RedisRouteDefinitionRepository implements RouteDefinitionRepository {
+public class RedisRouteDefinitionRepository implements RouteDefinitionRepository
+{
public static final String KEY_ROUTES = "ROUTES::";
- private final RedisTemplate redisTemplate;
+ private final RedissonClient redissonClient;
- public RedisRouteDefinitionRepository(RedisTemplate redisTemplate)
+ public RedisRouteDefinitionRepository(RedissonClient redissonClient)
{
- this.redisTemplate = redisTemplate;
+ this.redissonClient = redissonClient;
}
@Override
public Flux getRouteDefinitions()
{
- List values = redisTemplate.opsForHash().values(KEY_ROUTES);
- return Flux.fromIterable(values);
+ RMap map = redissonClient.getMap(KEY_ROUTES);
+ return Flux.fromIterable(map.values());
}
@Override
public Mono save(Mono route)
{
return route.flatMap(definition -> {
- redisTemplate.opsForHash().put(KEY_ROUTES, definition.getId(), definition);
+ RMap map = redissonClient.getMap(KEY_ROUTES);
+ map.put(definition.getId(), definition);
return Mono.empty();
});
}
@@ -43,7 +44,8 @@ public class RedisRouteDefinitionRepository implements RouteDefinitionRepository
public Mono delete(Mono routeId)
{
return routeId.flatMap(id -> {
- redisTemplate.opsForHash().delete(KEY_ROUTES, id);
+ RMap map = redissonClient.getMap(KEY_ROUTES);
+ map.remove(id);
return Mono.empty();
});
}
diff --git a/ruoyi-extend/ruoyi-isc-gateway/src/main/java/com/ruoyi/gateway/config/provider/RedissonProperties.java b/ruoyi-extend/ruoyi-isc-gateway/src/main/java/com/ruoyi/gateway/config/provider/RedissonProperties.java
new file mode 100644
index 000000000..9a74bc703
--- /dev/null
+++ b/ruoyi-extend/ruoyi-isc-gateway/src/main/java/com/ruoyi/gateway/config/provider/RedissonProperties.java
@@ -0,0 +1,134 @@
+package com.ruoyi.gateway.config.provider;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.redisson.config.TransportMode;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * Redisson 配置属性
+ *
+ * @author Lion Li
+ */
+@Data
+@Component
+@ConfigurationProperties(prefix = "redisson")
+public class RedissonProperties
+{
+
+ /**
+ * 线程池数量,默认值 = 当前处理核数量 * 2
+ */
+ private int threads;
+
+ /**
+ * Netty线程池数量,默认值 = 当前处理核数量 * 2
+ */
+ private int nettyThreads;
+
+ /**
+ * 传输模式
+ */
+ private TransportMode transportMode;
+
+ /**
+ * 单机服务配置
+ */
+ private SingleServerConfig singleServerConfig;
+
+ /**
+ * 缓存组
+ */
+ private List cacheGroup;
+
+ @Data
+ @NoArgsConstructor
+ public static class SingleServerConfig {
+
+ /**
+ * 客户端名称
+ */
+ private String clientName;
+
+ /**
+ * 最小空闲连接数
+ */
+ private int connectionMinimumIdleSize;
+
+ /**
+ * 连接池大小
+ */
+ private int connectionPoolSize;
+
+ /**
+ * 连接空闲超时,单位:毫秒
+ */
+ private int idleConnectionTimeout;
+
+ /**
+ * 命令等待超时,单位:毫秒
+ */
+ private int timeout;
+
+ /**
+ * 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。
+ */
+ private int retryAttempts;
+
+ /**
+ * 命令重试发送时间间隔,单位:毫秒
+ */
+ private int retryInterval;
+
+ /**
+ * 发布和订阅连接的最小空闲连接数
+ */
+ private int subscriptionConnectionMinimumIdleSize;
+
+ /**
+ * 发布和订阅连接池大小
+ */
+ private int subscriptionConnectionPoolSize;
+
+ /**
+ * 单个连接最大订阅数量
+ */
+ private int subscriptionsPerConnection;
+
+ /**
+ * DNS监测时间间隔,单位:毫秒
+ */
+ private int dnsMonitoringInterval;
+
+ }
+
+ @Data
+ @NoArgsConstructor
+ public static class CacheGroup {
+
+ /**
+ * 组id
+ */
+ private String groupId;
+
+ /**
+ * 组过期时间
+ */
+ private long ttl;
+
+ /**
+ * 组最大空闲时间
+ */
+ private long maxIdleTime;
+
+ /**
+ * 组最大长度
+ */
+ private int maxSize;
+
+ }
+
+}
diff --git a/ruoyi-extend/ruoyi-isc-gateway/src/main/resources/application-dev.yml b/ruoyi-extend/ruoyi-isc-gateway/src/main/resources/application-dev.yml
index c94a3d34f..d1e0c347d 100644
--- a/ruoyi-extend/ruoyi-isc-gateway/src/main/resources/application-dev.yml
+++ b/ruoyi-extend/ruoyi-isc-gateway/src/main/resources/application-dev.yml
@@ -29,6 +29,38 @@ spring:
# 是否开启ssl
ssl: false
+redisson:
+ # 线程池数量
+ threads: 16
+ # Netty线程池数量
+ nettyThreads: 32
+ # 传输模式
+ transportMode: "NIO"
+ # 单节点配置
+ singleServerConfig:
+ # 客户端名称
+ clientName: ${ruoyi.name}
+ # 最小空闲连接数
+ connectionMinimumIdleSize: 32
+ # 连接池大小
+ connectionPoolSize: 64
+ # 连接空闲超时,单位:毫秒
+ idleConnectionTimeout: 10000
+ # 命令等待超时,单位:毫秒
+ timeout: 3000
+ # 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。
+ retryAttempts: 3
+ # 命令重试发送时间间隔,单位:毫秒
+ retryInterval: 1500
+ # 发布和订阅连接的最小空闲连接数
+ subscriptionConnectionMinimumIdleSize: 1
+ # 发布和订阅连接池大小
+ subscriptionConnectionPoolSize: 50
+ # 单个连接最大订阅数量
+ subscriptionsPerConnection: 5
+ # DNS监测时间间隔,单位:毫秒
+ dnsMonitoringInterval: 5000
+
--- # Actuator 监控端点的配置项
management:
endpoints:
@@ -41,4 +73,4 @@ management:
include: @endpoints.include@
endpoint:
logfile:
- external-file: ./logs/sys-console.log
\ No newline at end of file
+ external-file: ./logs/sys-console.log
diff --git a/ruoyi-extend/ruoyi-isc-gateway/src/main/resources/application-local.yml b/ruoyi-extend/ruoyi-isc-gateway/src/main/resources/application-local.yml
new file mode 100644
index 000000000..a59c5c023
--- /dev/null
+++ b/ruoyi-extend/ruoyi-isc-gateway/src/main/resources/application-local.yml
@@ -0,0 +1,76 @@
+--- # 监控配置
+spring:
+ boot:
+ admin:
+ # Spring Boot Admin Client 客户端的相关配置
+ client:
+ # 增加客户端开关
+ enabled: true
+ # 设置 Spring Boot Admin Server 地址
+ url: http://localhost:9090/admin
+ instance:
+ prefer-ip: true # 注册实例时,优先使用 IP
+ username: ruoyi
+ password: 123456
+
+--- # redis 配置
+spring:
+ redis:
+ # 地址
+ host: 127.0.0.1
+ # 端口,默认为6379
+ port: 6379
+ # 数据库索引
+ database: 0
+ # 密码
+ password:
+ # 连接超时时间
+ timeout: 10s
+ # 是否开启ssl
+ ssl: false
+
+redisson:
+ # 线程池数量
+ threads: 16
+ # Netty线程池数量
+ nettyThreads: 32
+ # 传输模式
+ transportMode: "NIO"
+ # 单节点配置
+ singleServerConfig:
+ # 客户端名称
+ clientName: ${ruoyi.name}
+ # 最小空闲连接数
+ connectionMinimumIdleSize: 32
+ # 连接池大小
+ connectionPoolSize: 64
+ # 连接空闲超时,单位:毫秒
+ idleConnectionTimeout: 10000
+ # 命令等待超时,单位:毫秒
+ timeout: 3000
+ # 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。
+ retryAttempts: 3
+ # 命令重试发送时间间隔,单位:毫秒
+ retryInterval: 1500
+ # 发布和订阅连接的最小空闲连接数
+ subscriptionConnectionMinimumIdleSize: 1
+ # 发布和订阅连接池大小
+ subscriptionConnectionPoolSize: 50
+ # 单个连接最大订阅数量
+ subscriptionsPerConnection: 5
+ # DNS监测时间间隔,单位:毫秒
+ dnsMonitoringInterval: 5000
+
+--- # Actuator 监控端点的配置项
+management:
+ endpoints:
+ web:
+ # Actuator 提供的 API 接口的根目录。默认为 /actuator
+ base-path: /actuator
+ exposure:
+ # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
+ # 生产环境不建议放开所有 根据项目需求放开即可
+ include: @endpoints.include@
+ endpoint:
+ logfile:
+ external-file: ./logs/sys-console.log
diff --git a/ruoyi-extend/ruoyi-isc-gateway/src/main/resources/application.yml b/ruoyi-extend/ruoyi-isc-gateway/src/main/resources/application.yml
index 9e1aa773c..99a081b1e 100644
--- a/ruoyi-extend/ruoyi-isc-gateway/src/main/resources/application.yml
+++ b/ruoyi-extend/ruoyi-isc-gateway/src/main/resources/application.yml
@@ -1,3 +1,15 @@
+# 项目相关配置
+ruoyi:
+ # 名称
+ name: RuoYi-Vue-Plus
+ # 版本
+ version: ${ruoyi-vue-plus.version}
+ # 版权年份
+ copyrightYear: 2021
+ # 实例演示开关
+ demoEnabled: true
+ # 获取ip地址开关
+ addressEnabled: true
server:
port: 8090
# Spring配置