《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》

摘要: 原创出处 https://laoyuan.me/posts/spring-cloud-zuul-gateway-tutorial.html 「老袁」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

目前微服务越来越流行,Spring Cloud算得上目前比较流行的微服务治理框架,从Spring移植应用过来也非常方便。服务多了,对外部调用客户端不可能每个服务都给出一个对外服务的主机地址,很多客户端也不具备加入Spring注册中心的条件,如果服务升级,服务地址变动,则需要通知的客户端太多,且容易出错。 最初对网关的理解来源于Nginx的反向代理,通过修改配置文件实现服务聚合与分流。上述的问题是可以通过Nginx的反向代理聚合服务,修改服务路径,新旧服务版本流量控制,不过每次都需要修改配置文件。 不过Spring Cloud已经提供了对网关(基于Zuul)的支持,那没有理由不去使用Spring Cloud Zuul来实现服务的聚合和管理。对于开发人员来说,动态调整网关代理配置,能动态配置最好,如果每次变动都需要联系运维审批修改Nginx配置来实现,确实太费周章。

前话

Spring Cloud 网关是基于Netflix开发的Zuul组件实现的,Zuul核心的功能就是一堆的过滤器,通过对请求的过滤,则可以实现对权限认证,路由转发,请求参数变更,流量控制等功能。下面是一张官方的Zuul请求生命周期图: Zuul请求生命周期 Zuul的过滤器主要定义了四种不同生命周期的过滤器类型:

类型 描述
pre 可以在请求被路由之前调用
routing 在路由请求时候被调用
post 在routing和error过滤器之后被调用
error 处理请求时发生错误时被调用

每个过滤器主要需要实现如下抽象方法或接口:

/**
* 是否使用此过滤器
*/
boolean shouldFilter();

/**
* 需要执行的过滤操作
*/
Object run();

/**
* 过滤器类型
*/
String filterType();

/**
* 过滤器执行顺序
*/
int filterOrder();

源码分析

Spring Cloud Gateway则对Zuul进行二次封装,对上述的四种生命周期都进行了对应的实现:

  • PRE:
名称 顺序 用途
ServletDetectionFilter -3 判断后续处理的Servlet:DispatcherServlet(Spting)、ZuulServlet(zuul)
Servlet30WrapperFilter -2 将原始的HttpServletRequest封装成Servlet30RequestWrapper对象
FormBodyWrapperFilter -1 将Servlet30RequestWrapper封装成FormBodyRequestWrapper对象
DebugFilter 1 处理请求中是否带debug参数,来开启后续过滤器是否打印调试信息
PreDecorationFilter 5 最核心的也是最后一个PRE过滤器,此处查询路由配置,在请求中设置转发信息
  • ROUTING:
名称 顺序 用途
RibbonRoutingFilter 10 处理Cloud服务类型的路由配置
SimpleHostRoutingFilter 100 处理代理地址连接类型的路由配置
SendForwardFilter 500 处理转发类型的路由配置
  • POST:
名称 顺序 用途
SendErrorFilter 10 返回客户端错误响应
SendResponseFilter 100 返回客户端代理结果响应

启动流程

Spring Cloud提供了网关的自动配置(ZuulProxyConfiguration),自动配置主要实现如下功能:

  • 读取yml中的路由配置

  • 根据路由配置生成RouteLocator,提供给PreDecorationFilter根据URL查找对于的路由配置

  • 初始化上述列表中的各阶段过滤器

    使用教程

  • 配置路由规则

    server:
    port: 4100 #配置网关端口

    spring:
    application:
    name: my-gateway # 指定网关微服务名
    eureka:
    client:
    serviceUrl:
    defaultZone: http://localhost:8010/eureka/ # 指定服务注册中心的地址
    zuul:
    routes: # 配置路由规则,可以配置服务代理规则、本地转发规则、地址代理规则
    service-my-api:
    path: /api/**
    serviceId: my-api
    service-my-api-1:
    path: /api-1/**
    serviceId: my-api-1

  • 启动网关

    @SpringBootApplication
    @EnableZuulProxy //开启网关代理
    public class MyGatewayApplication {
    public static void main(String[] args) {
    SpringApplication.run(MyGatewayApplication.class, args);
    }
    }

扩展

Spring Cloud Zuul提供的默认路由方式,小规模的应用应该足够了,不过对于需要动态路由配置的网关,则不能满足需求,所以需要我们对网关进行扩展,主要有以下扩展思路:

  • 扩展DiscoveryClientRouteLocator,即管理路由规则的类,默认是读取配置文件和注册中心的ServiceId自动生成路由规则,则这里可以修改为基于Zookeeper或Redis的动态配置路由规则定位器。
  • 扩展PreDecorationFilter,即路由匹配设置过滤器,默认是使用DiscoveryClientRouteLocator进行路由规则匹配,则可以扩展为基于正则匹配路由配置等操作。
  • 扩展SendErrorFilter,即代理错误响应过滤器,默认的错误响应或许对前端客户端不友好,则可以扩展封装错误信息。
  • 新增PRE类型的前置过滤器,可以考虑进行客户端调用的权限认证与权限控制,也可以考虑对客户端的调用频率进行限制。

666. 彩蛋

如果你对 Zuul 感兴趣,欢迎加入我的知识星球一起交流。

知识星球

文章目录
  1. 1. 前话
  2. 2. 源码分析
  3. 3. 启动流程
  4. 4. 使用教程
  5. 5. 扩展
  • 666. 彩蛋