一, Zuul动态路由实现

动态路由需要达到可持久化配置,动态刷新的效果。不仅要能满足从spring的配置文件properties加载路由信息,还需要从Redis加载我们的配置。另外一点是,路由信息在容器启动时就已经加载进入了内存,我们希望配置完成后,实施发布,动态刷新内存中的路由信息,达到不停机维护路由信息的效果。

为了避免Eureka的侵入性设计,这里没有使用spring-cloud的服务的注册与发现的Eureka,而直接使用了Zuul。

需要配置如下属性使Zuul不依赖Eureka:

Icon

#关闭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脚本:

动态载入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的功能。

Groovy脚本
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实现相关推荐

  1. 动态路由和动态路由中的RIP协议

    动态路由和动态路由中的RIP协议 一.动态路由 1.动态路由的特点 2.选择依据:度量值 3.收敛 4.静态路由与动态路由的比较 二.动态路由协议分类 三.RIP是距离矢量路由选择协议 1.RIP的基 ...

  2. uniapp 移动端上传文件_基于 uniapp 实现动态路由和动态 Tabbar

    本文转载自 字节逆旅 公众号,感谢作者的好文分享✌️,点击阅读原文可以查看作者的掘金链接. uniapp用来开发app还是比较方便快捷的,官网教程[1]挺细致,几乎所有问题都能找到答案.网上也有不少入 ...

  3. 如何利用Vue3管理系统实现动态路由和动态侧边菜单栏

    前言 在做Vue管理系统的时候,都会遇到的一个需求:每个用户的权限是不一样的,那么他可以访问的页面(路由),可以操作的菜单选项是不一样的,如果由后端控制,我们前端需要去实现动态路由,动态渲染侧边菜单栏 ...

  4. zuul 动态路由mysql_zuul 动态路由 - typistw的个人空间 - OSCHINA - 中文开源技术交流社区...

    前言 在微服务架构体系下,随着时间的推移,难免会碰到由于前期服务粒度的划分不能完全满足后续需求的增长,造成"微"服务的二度拆分.拆分不可避免的会导致服务在整个系统中的链路发生变化, ...

  5. 快速搭建一个网关服务,动态路由、鉴权看完就会(含流程图)

    [文章来源]https://sourl.cn/tcbSPi 前 言 本文记录一下我是如何使用Gateway搭建网关服务及实现动态路由的,帮助大家学习如何快速搭建一个网关服务,了解路由相关配置,鉴权的流 ...

  6. ribbon 配置 动态更新_Netflix开源工具:在SpringBoot实现动态路由

    前言 假设你有一个服务A,要调用服务B(有三个实例,B1.B2.B3),如何只调用其中的B1和B2,屏蔽掉B3?实际上解决方法大致分为两类. 一种是外部路由,就是通过网关等组件,在请求链路上进行路由选 ...

  7. 【计算机网络】网络层 : 路由算法 ( 路由算法分类 | 静态路由算法 | 动态路由算法 | 全局性动态路由算法 | 分散性动态路由算法 | 分层次路由选择协议 )

    文章目录 一.路由算法 二.路由算法 分类 三.静态路由算法 四.动态路由算法 五.动态路由算法 分类 六.分层次的路由选择协议 一.路由算法 路由算法 : 选择数传输的 "最佳路由&quo ...

  8. 4.2.1 路由算法与路由协议概述(静态路由和动态路由---距离-向量路由算法---链路状态路由算法、层次路由)

    文章目录 0.思维导图 1.路由算法分类与路由表 2.静态路由和动态路由 3.动态路由的两种算法:链路状态路由算法和距离向量路由算法 4.层次路由 0.思维导图 1.路由算法分类与路由表 路由器转发分 ...

  9. 配置单臂路由、三层交换技术以及动态路由

    实验05:配置单臂路由 一. 实验目标 通过Cisco Packet Tracer来配置单臂路由. 二.实验环境和拓扑 window 7操作系统,Cisco Packet Tracer软件. 拓扑结构 ...

最新文章

  1. 将编译器pass添加到Relay
  2. .NET中的异步编程(四)- IO完成端口以及FileStream.BeginRead
  3. 为什么python不出结果_Python 的 Checksum 为什么结果是一长串数字而不是如下效果...
  4. 《模式识别导论》特性选择与特征提取概要
  5. c++ 预处理命令 #error 用法
  6. CurrentHashMap源码剖析
  7. C语言指针和数组概述
  8. 如何暴露内网主机到外网
  9. PDE5 method of characteristics
  10. 第四课--AMP架构双核应用程序开发和软中断处理(二)
  11. 写给想做好社区网站人员的一本书
  12. STP实验(指定特定交换机为根桥)
  13. hdu1385 最短路字典序
  14. [JNI] 开发基础(4)函数指针及指针函数
  15. Linux安装字体库
  16. Springboot之QueryDSL增强JPA操作
  17. 秒开路由sam1_野狼SAM机架精编版V1.0官方版-独木成林
  18. 安卓手机怎么投屏台式计算机WIN7,手机怎么投屏到win7电脑
  19. 学做衣服论坛 -服装DIY教程,缤纷服装网,裁剪教程,家用缝纫机,买布料
  20. 海外云服务器备份和恢复的6种最佳做法

热门文章

  1. 单片机进阶---HLK-W801硬件开发之制作PCB
  2. b站老是服务器中断,​B站就服务器故障致歉,服务器连接失败原因与解决方法...
  3. 【 C++ 技术】 C++ 高性能服务器网络框架设计细节
  4. win10使用python的strftime有错误_win10系统提示werfault.exe应用程序错误如何解决
  5. 什么叫数字化服务-数字化转型网
  6. Problem B: 薪酬计算
  7. java项目中数据查询慢问题
  8. v-for与v-if可以一起使用吗?如果同时使用v-for和v-if会存在什么样的问题?
  9. 网络安全审计之CMS代码审计
  10. 人品与能力的心态问题