✨ 添加新特性。 动态路由 L1 L2 动态更新, redis pub/sub 事件

This commit is contained in:
冷冷 committed 2019-08-25 13:10:13 +08:00
1 parent 5a752c4a1f
commit 0ff2e3d774
8 files changed
+61 -102

No files matched your search

+18 -25
View File
@@ -1,36 +1,29 @@
特别说明: 为了方便其他群友查阅和工程师定位问题
- 以下格式请按要求填写,务必提供回显步骤,修改了什么参数等
- 只有图或者只有文字描述,看图识字 | 阅读理解的直接禁止登录私服
- 问题范围请局限PigX 现有功能范围内,扩展业务问题属于超纲直接关闭
- PigX 使用的组件均为开源组件,去对应组件的issue列表翻翻 可能会有更好的发现
附录: [提问的艺术](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/master/README-zh_CN.md)
> A级 蠢问题:救命啊!我的笔记本电脑不能正常显示了!
> B级 聪明问题:X.org 6.8.1 的鼠标光标会变形,某牌显卡 MV1005 芯片组。
> C级 更聪明问题:X.org 6.8.1 的鼠标光标,在某牌显卡 MV1005 芯片组环境下 - 会变形。
- 工单支持MD 语法格式化,注意可读性喔
- 若问题已经解决,请及时反馈并关闭工单
- 问题范围请局限PigX 现有功能范围内,扩展业务问题直接关闭
---
### 环境信息 (*)
### 版本信息
- pigx版本:
- 是否二开:
- 是否修改包名:
- pigx版本:
- 操作系统:
- 是否修改包名:
- 此描述属于上述哪个等级:
### 报错信息 (截图/日志)
```
这里粘贴代码或者、日志
---
### 问题描述(*)
```
必须提供日志、截图、回显步骤
```
### 问题描述(回显步骤)
---
### 报错信息
```
必须提供日志、截图、回显步骤
```
@@ -40,6 +40,16 @@ public interface CacheConstants {
*/
String ROUTE_KEY = "gateway_route_key";
/**
* redis reload 事件
*/
String ROUTE_REDIS_RELOAD_TOPIC = "gateway_redis_route_reload_topic";
/**
* 内存reload 时间
*/
String ROUTE_JVM_RELOAD_TOPIC = "gateway_jvm_route_reload_topic";
/**
* 参数缓存
*/
@@ -1,50 +0,0 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.common.gateway.cache;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
/**
* @author lengleng
* @date 2019-08-16
* <p>
* redis 消息订阅
*/
@Slf4j
@Component
@AllArgsConstructor
public class DynamicRouteCacheListener implements MessageListener {
private final RedisTemplate<String, String> redisTemplate;
@Override
public void onMessage(Message message, byte[] bytes) {
byte[] body = message.getBody();
byte[] channel = message.getChannel();
String msg = redisTemplate.getStringSerializer().deserialize(body);
String topic = redisTemplate.getStringSerializer().deserialize(channel);
log.info("监听到 {} , 消息内容为 {}", msg, topic);
RouteCacheUtil.removeRouteList();
}
}
@@ -18,7 +18,9 @@
package com.pig4cloud.pigx.common.gateway.configuration;
import com.pig4cloud.pigx.common.core.constant.CacheConstants;
import com.pig4cloud.pigx.common.gateway.cache.DynamicRouteCacheListener;
import com.pig4cloud.pigx.common.gateway.support.RouteCacheHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.config.PropertiesRouteDefinitionLocator;
import org.springframework.context.annotation.Bean;
@@ -34,8 +36,10 @@ import org.springframework.data.redis.listener.RedisMessageListenerContainer;
* <p>
* 动态路由配置类
*/
@Slf4j
@Configuration
@ComponentScan("com.pig4cloud.pigx.common.gateway")
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
public class DynamicRouteAutoConfiguration {
/**
* 配置文件设置为空
@@ -52,21 +56,17 @@ public class DynamicRouteAutoConfiguration {
* redis 监听配置
*
* @param redisConnectionFactory redis 配置
* @param cacheListener 业务处理
* @return
*/
@Bean
public RedisMessageListenerContainer redisContainer(RedisConnectionFactory redisConnectionFactory
, DynamicRouteCacheListener cacheListener) {
public RedisMessageListenerContainer redisContainer(RedisConnectionFactory redisConnectionFactory) {
RedisMessageListenerContainer container
= new RedisMessageListenerContainer();
container.setConnectionFactory(redisConnectionFactory);
container.addMessageListener(cacheListener, topic());
container.addMessageListener((message, bytes) -> {
log.warn("接收到重新JVM 重新加载路由事件");
RouteCacheHolder.removeRouteList();
}, new ChannelTopic(CacheConstants.ROUTE_JVM_RELOAD_TOPIC));
return container;
}
@Bean
public ChannelTopic topic() {
return new ChannelTopic(CacheConstants.ROUTE_KEY);
}
}
@@ -19,7 +19,6 @@ package com.pig4cloud.pigx.common.gateway.support;
import cn.hutool.core.collection.CollUtil;
import com.pig4cloud.pigx.common.core.constant.CacheConstants;
import com.pig4cloud.pigx.common.gateway.cache.RouteCacheUtil;
import com.pig4cloud.pigx.common.gateway.vo.RouteDefinitionVo;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -55,7 +54,7 @@ public class RedisRouteDefinitionWriter implements RouteDefinitionRepository {
log.info("保存路由信息{}", vo);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.opsForHash().put(CacheConstants.ROUTE_KEY, r.getId(), vo);
redisTemplate.convertAndSend(CacheConstants.ROUTE_KEY, "新增路由信息,网关缓存更新");
redisTemplate.convertAndSend(CacheConstants.ROUTE_JVM_RELOAD_TOPIC, "新增路由信息,网关缓存更新");
return Mono.empty();
});
}
@@ -67,7 +66,7 @@ public class RedisRouteDefinitionWriter implements RouteDefinitionRepository {
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.opsForHash().delete(CacheConstants.ROUTE_KEY, id);
});
redisTemplate.convertAndSend(CacheConstants.ROUTE_KEY, "删除路由信息,网关缓存更新");
redisTemplate.convertAndSend(CacheConstants.ROUTE_JVM_RELOAD_TOPIC, "删除路由信息,网关缓存更新");
return Mono.empty();
}
@@ -83,7 +82,7 @@ public class RedisRouteDefinitionWriter implements RouteDefinitionRepository {
*/
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
List<RouteDefinitionVo> routeList = RouteCacheUtil.getRouteList();
List<RouteDefinitionVo> routeList = RouteCacheHolder.getRouteList();
if (CollUtil.isNotEmpty(routeList)) {
log.debug("内存 中路由定义条数: {}, {}", routeList.size(), routeList);
return Flux.fromIterable(routeList);
@@ -94,7 +93,7 @@ public class RedisRouteDefinitionWriter implements RouteDefinitionRepository {
List<RouteDefinitionVo> values = redisTemplate.opsForHash().values(CacheConstants.ROUTE_KEY);
log.debug("redis 中路由定义条数: {}, {}", values.size(), values);
RouteCacheUtil.setRouteList(values);
RouteCacheHolder.setRouteList(values);
return Flux.fromIterable(values);
}
}
@@ -15,7 +15,7 @@
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.common.gateway.cache;
package com.pig4cloud.pigx.common.gateway.support;
import cn.hutool.cache.Cache;
import cn.hutool.cache.CacheUtil;
@@ -29,10 +29,10 @@ import java.util.List;
* @author lengleng
* @date 2019-08-16
* <p>
* 路由缓存
* 路由缓存工具类
*/
@UtilityClass
public class RouteCacheUtil {
public class RouteCacheHolder {
private Cache<String, RouteDefinitionVo> cache = CacheUtil.newLFUCache(50);
/**
@@ -52,9 +52,7 @@ public class RouteCacheUtil {
* @param routeList 缓存列表
*/
public void setRouteList(List<RouteDefinitionVo> routeList) {
routeList.forEach(route -> {
cache.put(route.getId(), route);
});
routeList.forEach(route -> cache.put(route.getId(), route));
}
/**
@@ -26,15 +26,16 @@ import com.pig4cloud.pigx.common.gateway.vo.RouteDefinitionVo;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.config.PropertiesRouteDefinitionLocator;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.scheduling.annotation.Async;
@@ -80,12 +81,20 @@ public class DynamicRouteInitRunner {
}
/**
* 配置文件设置为空redis 加载的为准
* redis 监听配置,监听 gateway_redis_route_reload_topic,重新加载Redis
*
* @param redisConnectionFactory redis 配置
* @return
*/
@Bean
public PropertiesRouteDefinitionLocator propertiesRouteDefinitionLocator() {
return new PropertiesRouteDefinitionLocator(new GatewayProperties());
public RedisMessageListenerContainer redisContainer(RedisConnectionFactory redisConnectionFactory) {
RedisMessageListenerContainer container
= new RedisMessageListenerContainer();
container.setConnectionFactory(redisConnectionFactory);
container.addMessageListener((message, bytes) -> {
log.warn("接收到重新Redis 重新加载路由事件");
initRoute();
}, new ChannelTopic(CacheConstants.ROUTE_REDIS_RELOAD_TOPIC));
return container;
}
}
@@ -156,7 +156,7 @@ public class SysRouteConfServiceImpl extends ServiceImpl<SysRouteConfMapper, Sys
log.debug("更新网关路由结束 ");
this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
redisTemplate.convertAndSend(CacheConstants.ROUTE_KEY, "UPMS路由信息,网关缓存更新");
redisTemplate.convertAndSend(CacheConstants.ROUTE_JVM_RELOAD_TOPIC, "UPMS路由信息,网关缓存更新");
} catch (Exception e) {
log.error("路由配置解析失败", e);
// 回滚路由,重新加载即可