当前位置: 首页 > news >正文

Spring Cloud Zuul 基本原理

Spring Cloud Zuul 底层是基于Servlet实现的,核心是通过一系列的ZuulFilter来完成请求的转发。

1、核心组件注册

1.1. EnableZuulProxy注解

启用Zuul作为微服务网关,需要在Application应用类加上@EnableZuulProxy注解,而该注解核心是利用@Import注解往Spring容器导入了ZuulProxyConfiguration配置类
image.png

1.2. ZuulProxyConfiguration

ZuulProxyConfiguration继承了ZuulConfiguration。

1.2.1. ZuulConfiguration:

ZuulConfuguration主要是利用@Import往Spring容器注入了ServerPropertiesAutoConfiguration配置类(下一小节介绍),并且作为配置类往Spring容器注入了CompositeRouteLocator、SimpleRouteLocator、ZuulController、ZuulHandlerMapping、ZuulServlet等组件,基于Spring DispatcherServlet实现请求转发入口。
image.png
还有ServletDetectionFilter、Servlet30WrapperFilter、SendResponseFilter、SendErrorFilter、SendForwardFilter等pre、post类型的过滤器,是Zuul实现路由转发的核心过滤器。
image.png
还有ZuulRefreshListener监听器,同于监听应用内部事件,设置路由信息状态为dirty,实现动态更新。
image.png

1.2.2. ZuulProxyConfiguration

当然了,ZuulProxyConfiguration本身也注入了实现路由转发的核心过滤器,包含route类型的过滤器:RibbonRoutingFilter、SimpleHostRoutingFilter。
image.png
还有路由定位器DiscoveryClientRouteLocator,先调用父类SimpleRouteLocator获取配置文件中的路由配置,然后再从注册中心中补充路由信息。
image.png
还有一个非常重要的Listener:ZuulDiscoveryRefreshListener,它实现了ApplicationListener接口,主要监听InstanceRegisteredEvent、ParentHearbeatEvent和HeartbeatEvent,根据注册中心发送的事件来更新最新的路由信息(设置路由信息状态为dirty)。
image.png

2、路由配置注册

上面已经提到,Zuul是基于Servlet实现的,而根据请求URL找到对应Handler是利用HandlerMapping完成的,而Zuul也根据此实现了ZuulHandlerMapping实现类。

2.1. ZuulHandlerMapping

DispatcherServlet#initHandlerMappings
image.png

2.2. ZuulHandlerMapping#lookupHandler

在DispatcherServlet在首次请求分发时,就会遍历所有HandlerMapping,然后根据请求去获取对应的Handler(HandlerExecutionChain,包含Handler和拦截器),当遍历到ZuulHandlerMapping时,会调用lookupHandler方法,如果是首次调用,会触发上面的registerHandlers方法,进行路由配置注册。
image.png

2.3. ZuulHandlerMapping#registerHandlers

ZuulHandlerMapping首次根据url查找Handler时,会先找到所有的路由配置,然后遍历注册Handler(ZuulController);这里查找所有路由配置就是上面提到的DiscoveryClientRouteLocator。
image.png

3、请求处理

DispatcherServlet分发请求的流程:

图片拿自网络

image.png

3.1. ZuulController

在2.3.中,ZuulHandlerMapping给路由配置注册Handler时,对应的Handler是ZuulController。ZuulController继承了ServletWrappingController,底层是实现Controller接口。

3.2. SimpleControllerHandlerAdapter

根据上面流程图,找到HandlerMapping后,会继续找到能执行对应Handler的HandlerAdapter;而上面也提到,ZuulController是实现于Controller接口,所以最后定位到的是SimpleControllerHandlerAdapter。
image.png
SimpleControllerAdapter执行请求逻辑非常简单,就是执行Handler的handleRequest方法,即执行ZuulController的handleRequest方法。
image.png

3.3. ZuulController#handleRequest

ZuulController的handleRequest很简单,调用的是父类的handleRequestInternal方法。
但是我们需要注意ZuulController的构造函数,里面给servletClass、servletName和supportedMethods赋值了,其中servletClass尤为关键,因为后续处理就是调用此类实例的方法。
image.png

3.4. ServletWrappingController

ServletWrappingController重写了InitializingBean#afterPropertiesSet方法,在设置实例属性后,根据servletClass实例化了servletInstance对象,这里就是ZuulServlet的实例。
ServletWrappingController的handleRequestInternal方法也很简单,就是调用servletInstance的service方法,这里就是ZuulServlet#service方法。
image.png

3.5. ZuulServlet#service

ZuulServlet的service方法逻辑很简单,都是利用ZuulRunner来完成的;在ServletWrappingController实例化servletInstance时,同时调用了servletInstance的init方法,此时ZuulServlet同时会创建一个ZuulRunner实例。
service方法逻辑:

  1. 执行ZuulRunner#init方法,创建请求上下文RequestContext,并将利用HttpServletRequestWrapper和HttpServletResponseWrapper分别将HttpServletRequest和HttpServletResponse包装起来。
  2. 调用ZuulRunner#preRoute方法执行前置过滤器
  3. 调用ZuulRunner#route方法执行路由过滤器
  4. 调用ZuulRunner#postRoute方法执行后置过滤器
  5. 如果步骤2到步骤4出现错误,则执行ZuulRunner的error方法
  6. 最后,清理RequestContext内容(ThreadLocal)

image.png

3.6. ZuulRunner

ZuulRunner实现也是非常简单,底层是利用FilterProcessor来实现的。
image.png

3.7. FilterProcessor

FilterProcessor执行过滤器的逻辑也非常简单,就是根据过滤器类型找到所有的过滤器,然后遍历调用processZuulFilter方法执行,里面只要是执行ZuulFilter的runFilter方法,并且对错误信息和成功信息做统计。
image.png

3.8. FilterLoader和FilterRegistry

FilterProcessor中是利用FilterLoader来完成过滤器的加载的,而FilterLoader最终是利用FilterRegistry来完成过滤器的加载。
image.pngimage.png
FilterLoader和FilterRegistry都是单例,在ZuulFilterConfiguration中创建,并注入到ZuulFilterInitializer中,最后并将ZuulFilterInitializer注入到Spring容器中。
image.png
ZuulFilterInitializer实现了ServletContextListener接口,在Spring容器完成初始化时,会将ZuulFilter集合注入到FilterRregistry中。
image.png

4. 核心过滤器

这里只要分析核心过滤器,不包含所有的过滤器。

4.1. 前置过滤器

4.1.1. ServletDetectionFilter

执行顺序为-3,主要是区分请求是通过Spring的DispatcherServlet处理运行的还是ZuulServlet来处理运行的。
image.png

4.1.2. Servlet30WrapperFilter

执行顺序为-2,主要是将HttpServletRequest包装成Servlet30RequestWrapper。
image.png

4.1.3. FormBodyWrapperFilter

执行顺序为-1,条件要么是Context-Type为application/x-www-form-urlencoded的请求,要么是Context-Type为multipart/form-data,且是由String的DispatcherServlet处理的请求,主要是将HttpServletRequest包装成FormBodyRequestWrapper。
image.png

4.1.4. DebugFilter

执行顺序为1,条件要么配置里指定zuul.debug.request为true,要么请求参数debug为true。主要用来将当前请求上下文中的debugRouting和debugRequest参数设置为true;主要是做到灵活开关debug模式,开启debug模式时,会打印一些日志方便分析问题。
image.png

4.1.5. PreDecorationFilter

执行顺序为5,条件要求请求上下文中不存在forward.do和serviceId参数,主要是做一个预处理,将相关信息存到上下文中,包含路由、后置、错误过滤器的过滤条件判断信息。
image.png

4.2. 路由过滤器

4.2.1. RibbonRoutingFilter

执行顺序为10,条件是请求上下文中routeHost为null并且serviceId不为null,主要是构建Ribbon命令上下文,并且发起请求转发。
image.png
在发起请求转发的时候,需要构建HTTP客户端,这里会根据配置和依赖来选用指定的HTTP客户端。
image.png

4.2.2. SimpleHostRoutingFilter

执行顺序为100,条件是请求上下文中routeHost不为null,主要是直接根据物理地址发送请求,这里是直接调用原生的HttpClient包的客户端。
image.png

image.png

4.2.3. SendForwardFilter

执行顺序为500,条件是请求上下文中forward.do不为null并且sendForwardFilter.ran为false,主要是做本地转发。
image.png

4.3. 后置过滤器

4.3.1. SendResponseFilter

执行顺序为1000,条件是请求上下文中异常为null,并且响应头或响应体不为null,主要是将响应写回给客户端。
image.png

4.4. 错误过滤器

4.4.1 SendErrorFilter

执行顺序为0,条件是请求上下文中异常不为null,并且sendErrorFilter.ran为false,主要是将异常写回给客户端。
image.png

相关文章:

Spring Cloud Zuul 基本原理

Spring Cloud Zuul 底层是基于Servlet实现的,核心是通过一系列的ZuulFilter来完成请求的转发。 1、核心组件注册 1.1. EnableZuulProxy注解 启用Zuul作为微服务网关,需要在Application应用类加上EnableZuulProxy注解,而该注解核心是利用Im…...

QT实现TCP服务器客户端的实现

ser: widget.cpp: #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//实例化一个服务器server new QTcpServer(this);// 此时&#xf…...

行为型设计模式——责任链模式

摘要 责任链模式(Chain of responsibility pattern): 通过责任链模式, 你可以为某个请求创建一个对象链. 每个对象依序检查此请求并对其进行处理或者将它传给链中的下一个对象。 一、责任链模式意图 职责链模式(Chain Of Responsibility) 是一种行为设…...

window安装压缩版postgresql

环境: window 11 专业版postgresql-16.0-1-windows-x64-binaries.zip 一、下载 1.1 从官网下载 https://www.postgresql.org/download/windows/ 1.2 从百度网盘下载 链接:https://pan.baidu.com/s/1fmQbgWSzX4hN07Lgdzfz0g?pwddzyy 提取码&#…...

数组(数据结构)

优质博文:IT-BLOG-CN 一、简介 数组Array是一种线性表数据结构,它用一组连续的内存空间,存储一组具有相同类型的数据。 数组因具有连续的内存空间的特点,数据拥有非常高效率的“随机访问”,时间复杂度为O(1)。但因要保…...

C/C++ 二分查找面试算法题

1.二分查找&#xff08;有序数组&#xff09; https://blog.csdn.net/qq_63918780/article/details/122527681 1 #include <stdio.h>2 #include <string.h>3 4 int func(int *a,int j,int x)5 {6 int len j - 1,i 0,min;7 while(i<len)8 {9 …...

Linux基本指令(上)——“Linux”

各位CSDN的uu们好呀&#xff0c;今天&#xff0c;小雅兰的内容是Linux啦&#xff01;&#xff01;&#xff01;主要是Linux的一些基本指令和Linux相关的基本概念&#xff08;系统层面&#xff09;&#xff0c;下面&#xff0c;让我们进入Linux的世界吧&#xff01;&#xff01;…...

XSS详解

XSS一些学习记录 XXS短标签、属性、事件、方法短标签属性事件函数弹窗函数一些对于绕过有用的函数一些函数使用payload收集 浏览器编码问题XML实体编码URL编码JS编码混合编码 一些绕过方法利用constructor原型污染链构造弹框空格绕过圆括号过滤绕过其他的一些绕过 参考 XXS短标…...

【图论】判环问题

&#xff08;未更新完、做到相关题再更新相关部分 文章目录 无向图判断有无环并输出环上点 无向图判断有无环并输出环上点 例题&#xff1a;H. Mad City 利用变种拓扑排序&#xff0c;先把度为1的点存入队中&#xff0c;每次取出队头&#xff0c;遍历邻接点&#xff0c;再将该…...

将3D MAX设计模型导入NX1988

将3D MAX设计模型导入NX1988 概述导入流程导出喜欢的模型对模型进行修改模型贴图 概述 一般家装设计都不会用NX之类的产品设计软件&#xff0c;也没有通用的文件格式可以互相转换&#xff0c;本文的目的是将从网上下载的一些设计较好的3D MAX模型导入到NX软件中借用&#xff0…...

操作系统原理实验三:页面调度算法程序

实验三&#xff1a;页面调度算法程序 课程名称&#xff1a;操作系统原理 项目名称&#xff1a;页面调度算法程序 实验&#xff08;实训&#xff09;类型&#xff1a;验证性实验 实验&#xff08;实训&#xff09;课时&#xff1a;2 [目的和要求] 目的&#xff1a; 加深对请…...

QT实现tcp服务器客户端

服务器.cpp #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//实例化一个服务器server new QTcpServer(this);// 此时&#xff0c;服务器已经成功进入监听状态…...

tcp拥塞控制原理

18.3 拥塞控制 我们在向对端发送数据时&#xff0c;并不是一股脑子任意发送&#xff0c;因为TCP建立连接后&#xff0c;就是建立了一根管道&#xff0c;这跟管道上&#xff0c;实际上有很多的工作设备&#xff0c;比如路由器和交换机等等&#xff0c;他们都会对接收到的TCP包进…...

【C++设计模式之简单工厂模式】分析及示例

简介 简单工厂模式是一种常见的设计模式&#xff0c;用于创建多种相似对象的实例&#xff0c;属于创建型。 它通过一个工厂类来解耦客户端代码和对象的创建过程&#xff0c;使得客户端无需直接和具体的产品类交互&#xff0c;而只需要通过工厂类获取所需的产品实例即可。 原理…...

云原生定义整理

云原生定义整理 Pivotal 是云原生应用的提出者&#xff0c;并推出了 Pivotal Cloud Foundry 云原生应用平台和 Spring 开源 Java 开发框架&#xff0c;成为云原生应用架构中先驱者和探路者。 Pivotal最初的定义 Pivotal公司的Matt Stine在2015年写了一本叫做<<迁移到云…...

华硕X555YI, Win11下无法调节屏幕亮度

翻出一个旧电脑华硕X555YI&#xff0c;装Win11玩&#xff0c;已经估计到会有一些问题。 果然&#xff0c;装完之后&#xff0c;发现屏幕无法调节亮度。试了网上的一些方法&#xff0c;比如修改注册表等&#xff0c;无效。 估计是显卡比较老&#xff0c;哪里没兼容。然后用驱动…...

踩坑 | vue动态绑定img标签src属性的一系列报错

文章目录 踩坑 | vue项目运行后使用require()图片也不显示问题描述vue中动态设置img的src不生效问题的原因require is not defined 解决办法1&#xff1a;src属性直接传入地址解决办法2 踩坑 | vue项目运行后使用require()图片也不显示 问题描述 在网上查阅之后&#xff0c;发…...

强化学习环境 - robogym - 学习 - 1

强化学习环境 - robogym - 学习 - 1 项目地址 https://github.com/openai/robogym 为什么选择 robogym 自己的项目需要做一些机械臂 table-top 级的多任务操作 robogym 基于 mujoco 搭建&#xff0c;构建了一个仿真机械臂桌面物体操作&#xff08;pick-place、stack、rearr…...

如果在 Mac 上的 Safari 浏览器中无法打开网站

使用网络管理员提供的信息更改代理设置。个人建议DNS解析&#xff0c;设置多个例如114.114.114.114 8.8.8.8 8.8.4.4 如果打不开网站&#xff0c;请尝试这些建议。 在 Mac 上的 Safari 浏览器 App 中&#xff0c;检查页面无法打开时出现的信息。 这可能会建议解决问题的…...

力扣练习——链表在线OJ

目录 提示&#xff1a; 一、移除链表元素 题目&#xff1a; 解答&#xff1a; 二、反转链表 题目&#xff1a; 解答&#xff1a; 三、找到链表的中间结点 题目&#xff1a; 解答&#xff1a; 四、合并两个有序链表&#xff08;经典&#xff09; 题目&#xff1a; 解…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

抽象类和接口(全)

一、抽象类 1.概念&#xff1a;如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象&#xff0c;这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法&#xff0c;包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中&#xff0c;⼀个类如果被 abs…...

消防一体化安全管控平台:构建消防“一张图”和APP统一管理

在城市的某个角落&#xff0c;一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延&#xff0c;滚滚浓烟弥漫开来&#xff0c;周围群众的生命财产安全受到严重威胁。就在这千钧一发之际&#xff0c;消防救援队伍迅速行动&#xff0c;而豪越科技消防一体化安全管控平台构建的消防“…...

AxureRP-Pro-Beta-Setup_114413.exe (6.0.0.2887)

Name&#xff1a;3ddown Serial&#xff1a;FiCGEezgdGoYILo8U/2MFyCWj0jZoJc/sziRRj2/ENvtEq7w1RH97k5MWctqVHA 注册用户名&#xff1a;Axure 序列号&#xff1a;8t3Yk/zu4cX601/seX6wBZgYRVj/lkC2PICCdO4sFKCCLx8mcCnccoylVb40lP...

小智AI+MCP

什么是小智AI和MCP 如果还不清楚的先看往期文章 手搓小智AI聊天机器人 MCP 深度解析&#xff1a;AI 的USB接口 如何使用小智MCP 1.刷支持mcp的小智固件 2.下载官方MCP的示例代码 Github&#xff1a;https://github.com/78/mcp-calculator 安这个步骤执行 其中MCP_ENDPOI…...