Zuul动态路由及动态Filter实现
一, Zuul动态路由实现
动态路由需要达到可持久化配置,动态刷新的效果。不仅要能满足从spring的配置文件properties加载路由信息,还需要从Redis加载我们的配置。另外一点是,路由信息在容器启动时就已经加载进入了内存,我们希望配置完成后,实施发布,动态刷新内存中的路由信息,达到不停机维护路由信息的效果。
为了避免Eureka的侵入性设计,这里没有使用spring-cloud的服务的注册与发现的Eureka,而直接使用了Zuul。
需要配置如下属性使Zuul不依赖Eureka:
#关闭zuul的eureka注册
eureka.client.enabled=false
这里采取的方式修改路由定位器,借鉴DiscoveryClientRouteLocator去改造SimpleRouteLocator使其具备刷新能力。
DiscoveryClientRouteLocator比SimpleRouteLocator多了两个功能,第一是从DiscoveryClient(如Eureka)发现路由信息,我们不想使用eureka这种侵入式的网关模块,所以忽略它,第二是实现了RefreshableRouteLocator接口,能够实现动态刷新。
路由定位器的实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
@Override
public void refresh() {
doRefresh();
}
@Override
protected Map<String, ZuulRoute> locateRoutes() {
LinkedHashMap<String, ZuulRoute> routesMap = new LinkedHashMap<String, ZuulRoute>();
//从application.properties中加载路由信息
routesMap.putAll( super .locateRoutes());
//从redis中加载路由信息
routesMap.putAll(locateRoutesFromRedis());
//优化一下配置
LinkedHashMap<String, ZuulRoute> values = new LinkedHashMap<>();
for (Map.Entry<String, ZuulRoute> entry : routesMap.entrySet()) {
String path = entry.getKey();
// Prepend with slash if not already present.
if (!path.startsWith( "/" )) {
path = "/" + path;
}
if (StringUtils.hasText( this .properties.getPrefix())) {
path = this .properties.getPrefix() + path;
if (!path.startsWith( "/" )) {
path = "/" + path;
}
}
values.put(path, entry.getValue());
}
return values;
}
|
locateRoutesFromRedis方法,则是从Redis中获取路由信息。
然后通过调用路由定位器的doRefresh方法,刷新路由。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@Service
public class RefreshRouteService {
@Autowired
ApplicationEventPublisher publisher;
@Autowired
RouteLocator routeLocator;
public void refreshRoute() {
RoutesRefreshedEvent routesRefreshedEvent = new RoutesRefreshedEvent(routeLocator);
publisher.publishEvent(routesRefreshedEvent);
}
}
|
二, Zuul动态Filter实现
Zuul提供了一个框架,可以对过滤器进行动态的加载,编译,运行。过滤器之间没有直接的相互通信。他们是通过一个RequestContext的静态类来进行数据传递的。RequestContext类中有ThreadLocal变量来记录每个Request所需要传递的数据。
过滤器是由Groovy写成。这些过滤器文件被放在Zuul Server上的特定目录下面。Zuul会定期轮询这些目录。修改过的过滤器会动态的加载到Zuul Server中以便于request使用。
需要在启动方法中追加如下代码,动态载入Groovy脚本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
// 启动时加载groovy filter
@Component
public static class GroovyLoadLineRunner implements CommandLineRunner {
private Logger logger = LoggerFactory.getLogger(getClass());
@Value ( "${ecej.groovy.path}" )
private String groovyPath;
@Override
public void run(String... args) throws Exception {
MonitoringHelper.initMocks();
FilterLoader.getInstance().setCompiler( new GroovyCompiler());
try {
FilterFileManager.setFilenameFilter( new GroovyFileFilter());
logger.info(groovyPath);
FilterFileManager.init( 1 , groovyPath + "pre" , groovyPath + "post" );
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
|
FilterFileManager会根据设定的pollingIntervalSeconds,去扫描指定目录的文件到内存中。
在指定目录放入如下的脚本,即可以实现动态Filter的功能。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
package com.ecej.zuul.filter.pre
import org.slf4j.Logger
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
class PreRequest extends ZuulFilter {
private Logger logger = LoggerFactory.getLogger(getClass());
@Override
String filterType() {
return "pre"
}
@Override
int filterOrder() {
return 1000
}
@Override
boolean shouldFilter() {
return true
}
@Override
Object run() {
try {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
logger.info(String.format( "#####Groovy Pre Filter#####send %s request to %s" , request.getMethod(), request.getRequestURL().toString()));
} catch (Exception e) {
logger.error( "" ,e);
}
return null
}
}
|
之后只要修改这个文件,Filter的就会动态跟着改变。
Zuul动态路由及动态Filter实现相关推荐
- 动态路由和动态路由中的RIP协议
动态路由和动态路由中的RIP协议 一.动态路由 1.动态路由的特点 2.选择依据:度量值 3.收敛 4.静态路由与动态路由的比较 二.动态路由协议分类 三.RIP是距离矢量路由选择协议 1.RIP的基 ...
- uniapp 移动端上传文件_基于 uniapp 实现动态路由和动态 Tabbar
本文转载自 字节逆旅 公众号,感谢作者的好文分享✌️,点击阅读原文可以查看作者的掘金链接. uniapp用来开发app还是比较方便快捷的,官网教程[1]挺细致,几乎所有问题都能找到答案.网上也有不少入 ...
- 如何利用Vue3管理系统实现动态路由和动态侧边菜单栏
前言 在做Vue管理系统的时候,都会遇到的一个需求:每个用户的权限是不一样的,那么他可以访问的页面(路由),可以操作的菜单选项是不一样的,如果由后端控制,我们前端需要去实现动态路由,动态渲染侧边菜单栏 ...
- zuul 动态路由mysql_zuul 动态路由 - typistw的个人空间 - OSCHINA - 中文开源技术交流社区...
前言 在微服务架构体系下,随着时间的推移,难免会碰到由于前期服务粒度的划分不能完全满足后续需求的增长,造成"微"服务的二度拆分.拆分不可避免的会导致服务在整个系统中的链路发生变化, ...
- 快速搭建一个网关服务,动态路由、鉴权看完就会(含流程图)
[文章来源]https://sourl.cn/tcbSPi 前 言 本文记录一下我是如何使用Gateway搭建网关服务及实现动态路由的,帮助大家学习如何快速搭建一个网关服务,了解路由相关配置,鉴权的流 ...
- ribbon 配置 动态更新_Netflix开源工具:在SpringBoot实现动态路由
前言 假设你有一个服务A,要调用服务B(有三个实例,B1.B2.B3),如何只调用其中的B1和B2,屏蔽掉B3?实际上解决方法大致分为两类. 一种是外部路由,就是通过网关等组件,在请求链路上进行路由选 ...
- 【计算机网络】网络层 : 路由算法 ( 路由算法分类 | 静态路由算法 | 动态路由算法 | 全局性动态路由算法 | 分散性动态路由算法 | 分层次路由选择协议 )
文章目录 一.路由算法 二.路由算法 分类 三.静态路由算法 四.动态路由算法 五.动态路由算法 分类 六.分层次的路由选择协议 一.路由算法 路由算法 : 选择数传输的 "最佳路由&quo ...
- 4.2.1 路由算法与路由协议概述(静态路由和动态路由---距离-向量路由算法---链路状态路由算法、层次路由)
文章目录 0.思维导图 1.路由算法分类与路由表 2.静态路由和动态路由 3.动态路由的两种算法:链路状态路由算法和距离向量路由算法 4.层次路由 0.思维导图 1.路由算法分类与路由表 路由器转发分 ...
- 配置单臂路由、三层交换技术以及动态路由
实验05:配置单臂路由 一. 实验目标 通过Cisco Packet Tracer来配置单臂路由. 二.实验环境和拓扑 window 7操作系统,Cisco Packet Tracer软件. 拓扑结构 ...
最新文章
- 将编译器pass添加到Relay
- .NET中的异步编程(四)- IO完成端口以及FileStream.BeginRead
- 为什么python不出结果_Python 的 Checksum 为什么结果是一长串数字而不是如下效果...
- 《模式识别导论》特性选择与特征提取概要
- c++ 预处理命令 #error 用法
- CurrentHashMap源码剖析
- C语言指针和数组概述
- 如何暴露内网主机到外网
- PDE5 method of characteristics
- 第四课--AMP架构双核应用程序开发和软中断处理(二)
- 写给想做好社区网站人员的一本书
- STP实验(指定特定交换机为根桥)
- hdu1385 最短路字典序
- [JNI] 开发基础(4)函数指针及指针函数
- Linux安装字体库
- Springboot之QueryDSL增强JPA操作
- 秒开路由sam1_野狼SAM机架精编版V1.0官方版-独木成林
- 安卓手机怎么投屏台式计算机WIN7,手机怎么投屏到win7电脑
- 学做衣服论坛 -服装DIY教程,缤纷服装网,裁剪教程,家用缝纫机,买布料
- 海外云服务器备份和恢复的6种最佳做法
热门文章
- 单片机进阶---HLK-W801硬件开发之制作PCB
- b站老是服务器中断,​B站就服务器故障致歉,服务器连接失败原因与解决方法...
- 【 C++ 技术】 C++ 高性能服务器网络框架设计细节
- win10使用python的strftime有错误_win10系统提示werfault.exe应用程序错误如何解决
- 什么叫数字化服务-数字化转型网
- Problem B: 薪酬计算
- java项目中数据查询慢问题
- v-for与v-if可以一起使用吗?如果同时使用v-for和v-if会存在什么样的问题?
- 网络安全审计之CMS代码审计
- 人品与能力的心态问题