【Spring Cloud系列】Spring Cloud-网关Zuul详解与实战

简介: 笔记

一、概述


Spring Cloud Zuul 是 Spring Cloud Netflix 子项目的核心组件之一,是netflix开源的一个API Gateway服务器,本质上有一个Web Servlet应用,可以作为微服务架构中的 API 网关使用,支持动态路由与过滤功能;网关为微服务提供统一的访问入口;网关的定义类似设计模式中的门面模式,相当于微服务中的门面,客户端访问微服务都是通过它进行路由及过滤。它提供请求路由,负载均衡、校验过滤、服务容错、服务聚合等功能。


二、 Zuul功能和作用


Zuul可以通过加载动态过滤机制,从而实现以下各项功能:

▪验证与安全保障: 识别面向各类资源的验证要求并拒绝那些与要求不符的请求。

▪审查与监控: 在边缘位置追踪有意义数据及统计结果,从而为我们带来准确的生产状态结论。

▪路由转发: 以动态方式根据需要将请求路由至不同后端集群处。

▪压力测试: 逐渐增加指向集群的负载流量,从而计算性能水平。

▪负载均衡: 为每一种负载类型分配对应容量,并弃用超出限定值的请求。

▪静态响应处理: 在边缘位置直接建立部分响应,从而避免其流入内部集群。

▪多区域弹性: 跨越AWS区域进行请求路由,旨在实现ELB使用多样化并保证边缘位置与使用者尽可能接近。


除以上功能之外,Netflix公司还利用Zuul的功能通过金丝雀版本实现精确路由与压力测试。

在Spring Cloud中,可用通过添加Zuul的依赖和配置文件,快速搭建一个网关,方便统一管理和维护各个微服务,实现更好的服务治理。


三、Zuul网关工作原理


3.1 网关主要组件:

Zuul网关主要由一下几个组件构成:


▪Filter:过滤器,可以在请求被路由前或者之后添加一些处理逻辑。

▪Route:路由,将请求路由到不同的后端服务上。

▪Ribbon:负载均衡器,Zuul 默认使用 Ribbon 进行负载均衡。

▪Hystrix:容错处理器,可以实现限流和熔断机制。

Zuul 的过滤器链是整个网关的核心部分,它由多个过滤器构成,每个过滤器都负责不同的处理逻辑,比如请求的鉴权、转发等操作。过滤器链在处理请求的过程中,会依次执行这些过滤器,从而实现对请求的全生命周期管理,具体流程如下图所示。

在图中,我们可以看到 Filter Chain 主要由三部分组成:过滤器、生成路由并发送给后端服务、处理路由响应。下面我们将详细介绍每个部分的处理逻辑。


3.2 Zuul过滤器

过滤器是 Zuul 中最重要的组件之一,它可以拦截和修改请求和响应的内容,实现各种功能。在 Spring Cloud 中,所有的过滤器都必须继承抽象类 ZuulFilter,并实现其中的四个方法:

▪filterType()方法:返回过滤器类型,包括 pre、post、route 和 error 四种类型。

▪filterOrder()方法:返回过滤器执行的顺序,值越小越先执行。

▪shouldFilter()方法:判断过滤器是否需要执行,默认返回 true,表示全部需要执行。

▪run()方法:过滤器的主要业务逻辑,实现具体的过滤逻辑


Filter 类型

Zuul 中不同类型 filter 的执行逻辑核心在 com.netflix.zuul.http.ZuulServlet 类中定义,该类相关代码如下:

@Override
public void service(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) throws ServletException, IOException {
    try {
        init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);
        // Marks this request as having passed through the "Zuul engine", as opposed to servlets
        // explicitly bound in web.xml, for which requests will not have the same data attached
        RequestContext context = RequestContext.getCurrentContext();
        context.setZuulEngineRan();
        try {
            preRoute();
        } catch (ZuulException e) {
            error(e);
            postRoute();
            return;
        }
        try {
            route();
        } catch (ZuulException e) {
            error(e);
            postRoute();
            return;
        }
        try {
            postRoute();
        } catch (ZuulException e) {
            error(e);
            return;
        }
    } catch (Throwable e) {
        error(new ZuulException(e, 500, "UNHANDLED_EXCEPTION_" + e.getClass().getName()));
    } finally {
        RequestContext.getCurrentContext().unset();
    }
}

3.jpeg

这张经典的官方流程图有些问题,其中 post Filter 抛错之后进入 error Filter,然后再进入 post Filter 是有失偏颇的。实际上 post Filter 抛错分两种情况:

1.在 post Filter 抛错之前,pre、route Filter 没有抛错,此时会进入 ZuulException 的逻辑,打印堆栈信息,然后再返回 status = 500 的 ERROR 信息。

2.在 post Filter 抛错之前,pre、route Filter 已有抛错,此时不会打印堆栈信息,直接返回status = 500 的 ERROR 信息。

这样就比较直观地描述了 Zuul 关于 Filter 的请求生命周期。Zuul 中一共有四种不同生命周期的 Filter,分别是:

1.pre:在 Zuul 按照规则路由到下级服务之前执行。如果需要对请求进行预处理,比如鉴权、限流等,都应考虑在此类 Filter 实现。

2.route:这类 Filter 是 Zuul 路由动作的执行者,是 Apache Http Client 或 Netflix Ribbon 构建和发送原始 HTTP 请求的地方,目前已支持 Okhttp。

3.post:这类 Filter 是在源服务返回结果或者异常信息发生后执行的,如果需要对返回信息做一些处理,则在此类 Filter 进行处理。

4.error:在整个生命周期内如果发生异常,则会进入 error Filter,可做全局异常处理。


实际项目中,需要自实现以上类型的 Filter 来对请求链路进行处理,根据业务的需求,选取相应生命周期的 Filter 来达成目的。在 Filter 之间,通过 com.netflix.zuul.context.RequestContext 类来进行通信,内部采用 ThreadLocal 保存每个请求的一些信息,包括请求路由、错误信息、HttpServletRequest、HttpServletResponse,这使得一些操作是十分可靠的,它还扩展了 ConcurrentHashMap,目的是为了在处理过程中保存任何形式的信息。


3.3 生成路由并发送给后端服务

在Zuul中,可以通过配置ZuulProperties和RouteLocator实现路由转发的功能。其中ZuulProperties主要用于配置Zuul服务的一些相关属性,比如缓存时间、URL的前缀和后缀等;而RouteLocator则用于定义多个路由规则,将请求映射到不同的后端服务上。


当请求进入Zuul网关之后,首先会经过一系列过滤器处理,然后根据路由规则将请求转发到对应的后端服务上,最终返回响应结果。在转发请求时,Zuul可以自动地根据负载均衡策略选择相应的服务器,实现负载均衡的功能。


3.4 处理路由响应

在Zuul中,如果后端服务响应异常或者错误,那么 Zuul 会将这个异常封装成一个 ZuulException 对象,并交给其它的过滤器进行处理。当所有过滤器执行完毕之后,Zuul 会根据 ZuulException 中的状态码和错误消息,返回相应的响应结果。


四、Zuul 网关配置过程


在 Spring Cloud 中,我们可以通过添加一些依赖和配置文件,快速地创建一个 Zuul 网关服务。下面我们将详细介绍如何进行配置。


4.1 添加pom.xml依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

4.2 创建配置类

创建一个配置类,用于配置 Zuul 网关服务的相关属性。

@Configuration
@EnableZuulProxy
public class ZuulConfig {
    // 配置 Zuul 网关服务的相关属性
}

其中注解 @EnableZuulProxy 表示开启 Zuul 的代理功能,可以自动注册到 Eureka 服务中心,并集成 Ribbon 和 Hystrix 等组件。


4.3 配置路由规则

接下来我们需要配置 Zuul 的路由规则,将请求转发到不同的后端服务上。

@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder) {
    return builder.routes()
        .route("service-a", r -> r.path("/service-a/**")
            .filters(f -> f.stripPrefix(1))
            .uri("http://localhost:6060"))
        .route("service-b", r -> r.path("/service-b/**")
            .filters(f -> f.stripPrefix(1))
            .uri("http://localhost:6061"))
        .build();
}

在上面的代码中,我们定义了两个路由规则,分别将请求转发到 http://localhost:8081 和 http://localhost:8082 这两个地址上。其中 stripPrefix(1) 表示去掉 URL 中第一个斜杠之后的内容。


4.4 配置路由规则

最后我们可以添加一些过滤器,实现不同的功能。

@Bean
public MyFilter myFilter() {
    return new MyFilter();
}

其中 MyFilter 是我们自定义的过滤器类,用于实现一些特定的功能。


四、总结


本文从 Zuul 网关的原理、使用场景和配置过程三个方面详细介绍了 Zuul 网关的相关知识。可以看出,Zuul 的过滤器链是整个网关的核心部分,通过添加不同的过滤器,可以实现不同的功能,比如鉴权、转发、限流等。同时,通过合理地配置路由规则,可以将请求快速地转发到相应的后端服务中,实现负载均衡和服务治理的功能。


在实际开发中,我们可以根据不同的需求,灵活地运用 Zuul 网关服务,构建高可用、高并发的分布式应用系统。


相关实践学习
部署高可用架构
本场景主要介绍如何使用云服务器ECS、负载均衡SLB、云数据库RDS和数据传输服务产品来部署多可用区高可用架构。
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
目录
相关文章
|
1月前
|
SpringCloudAlibaba Java 持续交付
【构建一套Spring Cloud项目的大概步骤】&【Springcloud Alibaba微服务分布式架构学习资料】
【构建一套Spring Cloud项目的大概步骤】&【Springcloud Alibaba微服务分布式架构学习资料】
159 0
|
1月前
|
SpringCloudAlibaba Java 网络架构
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(七)Spring Cloud Gateway服务网关
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(七)Spring Cloud Gateway服务网关
105 0
|
4天前
|
Java Nacos 开发者
Java从入门到精通:4.2.1学习新技术与框架——以Spring Boot和Spring Cloud Alibaba为例
Java从入门到精通:4.2.1学习新技术与框架——以Spring Boot和Spring Cloud Alibaba为例
|
26天前
|
开发框架 负载均衡 Java
Spring boot与Spring cloud之间的关系
总之,Spring Boot和Spring Cloud之间的关系是一种构建和扩展的关系,Spring Boot提供了基础,而Spring Cloud在此基础上提供了分布式系统和微服务架构所需的扩展和工具。
19 4
Spring boot与Spring cloud之间的关系
|
1月前
|
SpringCloudAlibaba 负载均衡 Java
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(目录大纲)
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(目录大纲)
67 1
|
1月前
|
Java Nacos Sentinel
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(九)Nacos+Sentinel+Seata
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(九)Nacos+Sentinel+Seata
208 0
|
1月前
|
消息中间件 SpringCloudAlibaba Java
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(八)Config服务配置+bus消息总线+stream消息驱动+Sleuth链路追踪
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(八)Config服务配置+bus消息总线+stream消息驱动+Sleuth链路追踪
785 0
|
1月前
|
SpringCloudAlibaba Java 测试技术
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(六)Hystrix(豪猪哥)的使用
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(六)Hystrix(豪猪哥)的使用
39 1
|
1月前
|
SpringCloudAlibaba 负载均衡 Java
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(五)OpenFeign的使用
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(五)OpenFeign的使用
45 0
|
7月前
|
Dubbo Java 应用服务中间件
深入了解Spring Cloud Alibaba Dubbo
在现代分布式系统开发中,构建高性能、可伸缩性和弹性的微服务架构变得越来越重要。Spring Cloud Alibaba Dubbo(简称Dubbo)是一个开源的分布式服务框架,可以帮助开发者构建强大的微服务架构,具备负载均衡、服务治理、远程调用等强大功能。本文将深入介绍Spring Cloud Alibaba Dubbo,帮助你理解它的核心概念、工作原理以及如何在你的项目中使用它。