带你实现Zuul 路由规则的动态管理以及相关源码解读

本文详细介绍了Zuul的请求流程和内置路由拦截器的源码,重点在于如何实现Zuul路由规则的动态管理。通过自定义RouteLocator,从数据库加载路由规则,替代原有从properties配置的方式。文中还展示了如何实现路由的添加,并验证了动态路由管理的效果。
摘要由CSDN通过智能技术生成

本文篇幅较长,前面一、二部分主要讲原理跟源码,需要直接看实现的小伙伴可以直接通过目录跳转到第三部分


目录

1. Zuul请求流程

2. Zuul内置路由拦截器源码解读

2.1 框架拦截器说明

2.2 源码剖析

3.实现

3.1自定义RouteLocator

3.2 实现路由管理

3.3 效果展示

4.总结


1. Zuul请求流程

Zuul是一个基于Servlet的的网关组件,Zuul定义了四种类型的拦截器,分别是前置拦截器(pre)、路由拦截器(route)、后置拦截器(post)、异常拦截器(error)

而框架本身的路由功能也是基于拦截器实现的
当开启@EnableZuulProxy时,框架会在服务启动时向容器中注入一批内置的拦截器,其中就包括路由相关的拦截器。

当一个请求进来时,会依次进入这些拦截器,并由拦截器实现请求的转发。

下面是在路由功能中,一个请求的大致请求流程

zuul请求简易流程

 

可以看到,一个请求进来之后,它首先会在前置拦截器中被判断是否符合已存在的路由规则,如果请求路径与路由规则相匹配,那么这个请求会被打上一些相关的标记,然后在进入框架由内置的route拦截器时实现请求的转发

这里涉及到一个很重要的点,那就是:前置拦截器在对请求进行路由规则匹配时,首先要先获取到路由规则列表,所以说,这个前置拦截器一定要从某处加载路由规则。所以,要想实现路由规则的动态管理,我们主要的思路就在于

  1. 找到Zuul在何处加载路由规则
  2. 复写它的加载逻辑,使其可以从我们定义的数据源加载路由

所以要先看一下Zuul它内置了什么拦截器,以及拦截器是如何生效的

2. Zuul内置路由拦截器源码解读

2.1 框架拦截器说明

Zuul实现请求路由主要依靠以下三个拦截器:

org.springframework.cloud.netflix.zuul.filters.pre.PreDecorationFilter

前置拦截器,判断请求是否与现有路由规则相匹配,如果匹配则往请求容器中注入相关路由信息,以便在实际进行路由时能获取到目标路由地址


org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter

从注册中心上自动发现的服务路由规则以及配置的服务路由,都由该路由拦截器进行转发。

例:

zuul:
  routes:
    demo1:
      path: /demo1/**
      serviceId: demo1
      stripPrefix: false

当访问

http://localhost:8080/demo1/test

时,会进入该拦截器,这个拦截器会去注册中心上寻找服务名为demo1服务,并将请求转发到这个服务上,


org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter

配置了外部链接的路由,则由该路由进行转发,默认实现是调用httpClient向路由地址发送http请求获取响应

例:

zuul:
  routes:
    demo:
      path: /demo/**
      url: http://localhost:8081
      stripPrefix: false

当访问:

  • http://localhost:8080/demo/test

时,就会进入该拦截器,这个拦截器会根据已配置的路由规则向

  • http:localhost:8081/demo/test

发送请求

 


2.2 源码剖析

查看PreDecorationFilter的源码

	@Override
	public Object run() {
        // 获取请求容器(存放于ThreadLocal中,线程独有)
		RequestContext ctx = RequestContext.getCurrentContext();
        // 获取请求uri
		final String requestURI = this.urlPathHelper
				.getPathWithinApplication(ctx.getRequest());
        // 重点:判断请求uri是否与现有路由匹配
		Route route = this.routeLocator.getMatchingRoute(requestURI);
        // 如果匹配上的话,则往请求容器设置一些路由相关的信息,例如路由目标地址,前缀之类的
		if (route != null) {
			String location = route.getLocation();
			if (location != null) {
				ctx.put(REQUEST_URI_KEY, route.getPath());
				ctx.put(PROXY_KEY, route.getId());
            /***********省略一堆非主要代码*************/	
			}
		}
		else {
			log.warn("No route found for uri: " + requestURI);
			String forwardURI 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值