SpringCloud - Zuul路由网关使用详解

简介: SpringCloud - Zuul路由网关使用详解

【1】Zuul是什么

Zuul是从设备和网站到Netflix流应用程序后端的所有请求的前门。作为边缘服务应用程序,Zuul旨在实现动态路由,监控,弹性和安全性。它还可以根据需要将请求路由到多个合适的服务弹性收缩组。

为什么创建Zuul?

Netflix API流量的数量和多样性有时会导致生产问题迅速而且没有任何警告。我们需要一个允许我们快速改变行为的系统,以便对这些情况做出反应。

Zuul使用一系列不同类型的过滤器,使我们能够快速灵活地将功能应用于我们的边缘服务。这些过滤器可帮助我们执行以下功能:

  • 身份验证和安全性 - 识别每个资源的身份验证要求并拒绝不满足这些要求的请求。
  • 洞察和监控 - 在边缘跟踪有意义的数据和统计数据,以便为我们提供准确的生产视图。
  • 动态路由 - 根据需要动态地将请求路由到不同的后端群集。
  • 压力测试 - 逐渐增加群集的流量以衡量性能。
  • Load Shedding - 为每种类型的请求分配容量并删除超过限制的请求。
  • 静态响应处理 - 直接在边缘构建一些响应,而不是将它们转发到内部集群
  • 多区域弹性 - 跨AWS区域路由请求,以使我们的ELB使用多样化,并使我们的优势更接近我们的成员。

综上,Zuul包含了对请求的路由和过滤两个最主要的功能。其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础。而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础。

uul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,也即以后的微服务的访问都是通过Zuul跳转后获得。


【2】Zuul的基本配置

① 创建Module/microservicecloud-zuul-gateway-9527

pom依赖如下:

   <dependencies>
    <!-- zuul路由网关 -->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-zuul</artifactId>
    </dependency>
    <!-- Eureka服务注册 -->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-eureka</artifactId>
    </dependency>
    <!-- actuator监控 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <!-- hystrix熔断 -->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-hystrix</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-config</artifactId>
    </dependency>
    <!-- 日常标配 -->
    <dependency>
      <groupId>com.web.springcloud</groupId>
      <artifactId>microservicecloud-api</artifactId>
      <version>${project.version}</version>
    </dependency>
    <!-- Boot依赖 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jetty</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
    <!-- 热部署插件 -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>springloaded</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-devtools</artifactId>
    </dependency>
  </dependencies>

查看spring-cloud-starter-zuul依赖如下:

<dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-hystrix</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-ribbon</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-archaius</artifactId>
    </dependency>
    <dependency>
      <groupId>com.netflix.zuul</groupId>
      <artifactId>zuul-core</artifactId>
    </dependency>
  </dependencies>
  • spring-cloud-starter-hystrix:该依赖用来在网关服务中实现对微服务转发时候的保护机制,通过线程隔离和断路器,防止微服务的故障引发API网关资源无法释放,从而影响其他应用的对外服务。
  • spring-cloud-starter-ribbon:该依赖用来实现在网关服务进行路由转发时候的客户端负载均衡以及请求重试。
  • spring-boot-starter-actuator:该依赖用来提供常规的微服务管理端点。另外,在Spring Cloud Zuul中还特别提供了/routes端点来返回当前的所有路由规则。

② yml配置文件

server: 
  port: 9527
spring: 
  application:
    name: microservicecloud-zuul-gateway
eureka: 
  client: 
    service-url: 
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka  
  instance:
    instance-id: gateway-9527.com
    prefer-ip-address: true 
info:
  app.name: web-microcloud
  company.name: www.web.com
  build.artifactId: $project.artifactId$
  build.version: $project.version$

③ hosts文件修改

本地域名解析:

# spring cloud eureka
127.0.0.1 eureka7001.com
127.0.0.1 eureka7002.com
127.0.0.1 eureka7003.com
# spring cloud zuul
127.0.0.1 myzuul.com

④ 主启动类如下

@SpringBootApplication
@EnableZuulProxy
public class Zuul_9527_StartSpringCloudApp
{
  public static void main(String[] args)
  {
    SpringApplication.run(Zuul_9527_StartSpringCloudApp.class, args);
  }
}

此时整个项目架构如下图:


⑤ 测试

启动三个服务集群、服务提供者8001和路由9527。


不用路由直接测试:http://localhost:8001/dept/get/1

使用路由测试:http://myzuul.com:9527/microservicecloud-dept/dept/get/1

(默认使用服务名进行跳转)


【3】路由映射规则实例

如对访问http://myzuul.com:9527/microservicecloud-dept/dept/get/1请求进行转发和加固。


① 修改yml文件


配置对应的path和serviceId,符合/mydept/**规则的请求都会被转发到microservicecloud-dept服务的实例上。

zuul: 
  routes: 
    mydept.serviceId: microservicecloud-dept
    mydept.path: /mydept/**

此时,请求转变为http://myzuul.com:9527/mydept/dept/get/1。


此时将/microservicecloud-consumer-dept-feign启动,测试如下:

此时两种方式都可以访问:

http://myzuul.com:9527/microservicecloud-dept/dept/get/1

http://myzuul.com:9527/mydept/dept/get/1

上面配置方式就是面向服务的路由,根据配置的映射关系,网关将会转发到某个服务的实例上面。如果某个服务有多个实例,Zuul默认使用轮询的负载均衡策略。

当然也可以直接配置url:

zuul: 
  routes: 
    mydept.url: http://loclhost:8001/
    mydept.path: /mydept/**

该配置定义了发往API网关服务的请求中,所有符合/mydept/**规则的访问都将被路由转发到http://loclhost:8001/地址上。mydept是路由的名字可以任意定义,但是一组path和url映射关系的路由名要相同。不过通常建议使用面向服务的路由。

更简洁的面向服务路由配置

对于面向服务的路由配置,除了使用path与serviceId映射的配置方式之外,还有一种更简洁的配置方式:

    zuul.routes.<serviceId>=<path>

其中serviceId指定路由的具体服务名,path用来配置匹配的请求表达式。

zuul: 
  routes: 
    mydept.serviceId: microservicecloud-dept
    mydept.path: /mydept/**

等价于如下:

zuul.routes.microservicecloud-dept=/mydept/**


② 服务路由的默认规则

当我们为Spring Cloud Zuul构建的API网关服务引入Spring Cloud Eureka之后,它为Eureka中的每个服务都自动创建一个默认路由规则。这些默认路由规则的path会使用serviceId配置的服务名作为请求前缀。

zuul.routes.microservicecloud-dept.path=/microservicecloud-dept/**
zuul.routes.microservicecloud-dept.serviceId=microservicecloud-dept

由于默认情况下所有Eureka上的服务都会被Zuul自动地创建映射关系来进行路由,这会使得一些我们不希望对外开发的服务也可能被外部访问。这时就需要zuul.ignored-services参数来设置一个服务名匹配表达式来定义不自动创建路由的规则。


③ 如何忽略真实服务名?

  • 单服务忽略设置如下:
zuul: 
  ignored-services: microservicecloud-dept
  routes: 
    mydept.serviceId: microservicecloud-dept
    mydept.path: /mydept/**

此时访问http://myzuul.com:9527/microservicecloud-dept/dept/get/1将会出现Error page。http://myzuul.com:9527/mydept/dept/get/1 正常。


  • 忽略所有服务名
zuul: 
  ignored-services: "*"
  routes: 
    mydept.serviceId: microservicecloud-dept
    mydept.path: /mydept/**

这时Zuul将对所有的服务都不自动创建路由规则,在这种情况下,就要在配置文件中逐个为需要路由的服务添加映射规则,只有在配置文件中出现的映射规则会被创建路由,而从Eureka中获取的其他服务,Zuul将不会再为它们创建路由规则。


③ 设置请求统一前缀

zuul: 
  prefix: /web
  ignored-services: "*"
  routes: 
    mydept.serviceId: microservicecloud-dept
    mydept.path: /mydept/**


此时http://myzuul.com:9527/mydept/dept/get/1将不可访问,请求转变为http://myzuul.com:9527/web/mydept/dept/get/1。


④Zuul如何根据服务名找到URL?

其实API网关也是Eureka服务治理下的一个普通的微服务应用,它除了将自己注册到Eureka服务注册中心上之外,也会从注册中心获取所有服务以及它们的实例清单。。所以在Eureka的帮助下,API网关服务本身就已经维护了系统中所有的serviceId与实例地址的映射关系。当有外部请求到达api网关的时候,根据请求的URL路径找到最佳匹配的path规则,api网关就可以知道要将该请求路由到哪个具体的serviceId上去。


由于在API网关中已经知道serviceId对应服务实例的地址清单,那么只需要通过Ribbon的负载均衡策略,直接在这些清单中选择一个具体额实例进行转发就能完成路由工作。


【4】请求过滤

每个客户端用户请求微服务应用提供的接口时,它们的访问权限往往都有一定的限制,系统并不会将所有的微服务接口都对它们开发。为了实现对客户端请求的安全校验和权限控制,最简单的方法就是为每个微服务应用都实现一套用于校验签名和鉴别权限的过滤器或拦截器。而这种方法通常是不可取的,这样的实现方式会使得相似的校验逻辑代码被分散到了各个微服务中去,冗余代码的出现是我们不希望看到的。所以,比较好的做法是将这些校验逻辑剥离出去,构建出一个独立的鉴权服务。


最好的做法是通过前置的网关服务来完成这些非业务性质的校验。在请求到达的时候就完成校验和过滤。Zuul允许开发者在API网关上通过定义过滤器来实现对请求的拦截和过滤,实现的方法非常简单,我们只需要继承ZuulFilter抽象类并实现它定义的4个抽象函数就可以完成对请求的拦截和过滤了。


实例如下:

package com.web.springcloud;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
public class MyZuulFilter extends ZuulFilter {
  private static final Logger log = LoggerFactory.getLogger(MyZuulFilter.class);
/**
过滤器具体逻辑
*/
  @Override
  public Object run() {
    // TODO Auto-generated method stub
    RequestContext currentContext = RequestContext.getCurrentContext();
    HttpServletRequest request = currentContext.getRequest();
    log.info("send {} request to {}",request.getMethod(),request.getRequestURL().toString());
    Object accessToken = request.getParameter("accessToken");
    if (accessToken==null) {
      log.warn("access token is empty");
      currentContext.setSendZuulResponse(false);
      currentContext.setResponseStatusCode(401);
      return null;
    }
    log.info("access token ok");
    return null;
  }
/**
判断该过滤器是否需要被执行,这里返回true,将会对所有请求生效
*/
  @Override
  public boolean shouldFilter() {
    // TODO Auto-generated method stub
    return true;
  }
/**
过滤器的执行顺序。当请求在一个阶段中存在多个过滤器时,需要根据该方法返回的值来依次执行
*/
  @Override
  public int filterOrder() {
    // TODO Auto-generated method stub
    return 0;
  }
  @Override
  public String filterType() {
    // TODO Auto-generated method stub
    return "pre";
  }
}

主启动类添加bean:

@SpringBootApplication
@EnableZuulProxy
public class Zuul_9527_StartSpringCloudApp
{
  public static void main(String[] args)
  {
    SpringApplication.run(Zuul_9527_StartSpringCloudApp.class, args);
  }
  @Bean
  public MyZuulFilter myZuulFilter() {
    return new MyZuulFilter();
  }
}

filterType

过滤器的类型,它决定了过滤器在请求的哪个生命周期中执行。

  • pre:请求被路由之前执行;
  • route : 在路由请求时被调用;
  • error :处理请求时发生错误时被调用
  • post :在routing和error过滤器之后被调用;
  • static:for static responses see StaticResponseFilter。

图示如下:





目录
相关文章
|
监控 Java API
Spring Boot 3.2 结合 Spring Cloud 微服务架构实操指南 现代分布式应用系统构建实战教程
Spring Boot 3.2 + Spring Cloud 2023.0 微服务架构实践摘要 本文基于Spring Boot 3.2.5和Spring Cloud 2023.0.1最新稳定版本,演示现代微服务架构的构建过程。主要内容包括: 技术栈选择:采用Spring Cloud Netflix Eureka 4.1.0作为服务注册中心,Resilience4j 2.1.0替代Hystrix实现熔断机制,配合OpenFeign和Gateway等组件。 核心实操步骤: 搭建Eureka注册中心服务 构建商品
1580 3
|
11月前
|
负载均衡 Java API
《深入理解Spring》Spring Cloud 构建分布式系统的微服务全家桶
Spring Cloud为微服务架构提供一站式解决方案,涵盖服务注册、配置管理、负载均衡、熔断限流等核心功能,助力开发者构建高可用、易扩展的分布式系统,并持续向云原生演进。
|
人工智能 Cloud Native 安全
DeepSeek + Higress AI 网关/Spring AI Alibaba 案例征集
诚挚地感谢每一位持续关注并使用 Higress 和 Spring AI Alibaba 的朋友,DeepSeek + Higress AI 网关/Spring AI Alibaba 案例征集中。
1172 123
|
负载均衡 Dubbo Java
Spring Cloud Alibaba与Spring Cloud区别和联系?
Spring Cloud Alibaba与Spring Cloud区别和联系?
|
前端开发 Java Nacos
🛡️Spring Boot 3 整合 Spring Cloud Gateway 工程实践
本文介绍了如何使用Spring Cloud Alibaba 2023.0.0.0技术栈构建微服务网关,以应对微服务架构中流量治理与安全管控的复杂性。通过一个包含鉴权服务、文件服务和主服务的项目,详细讲解了网关的整合与功能开发。首先,通过统一路由配置,将所有请求集中到网关进行管理;其次,实现了限流防刷功能,防止恶意刷接口;最后,添加了登录鉴权机制,确保用户身份验证。整个过程结合Nacos注册中心,确保服务注册与配置管理的高效性。通过这些实践,帮助开发者更好地理解和应用微服务网关。
2689 0
🛡️Spring Boot 3 整合 Spring Cloud Gateway 工程实践
|
人工智能 安全 Java
AI 时代:从 Spring Cloud Alibaba 到 Spring AI Alibaba
本次分享由阿里云智能集团云原生微服务技术负责人李艳林主讲,主题为“AI时代:从Spring Cloud Alibaba到Spring AI Alibaba”。内容涵盖应用架构演进、AI agent框架发展趋势及Spring AI Alibaba的重磅发布。分享介绍了AI原生架构与传统架构的融合,强调了API优先、事件驱动和AI运维的重要性。同时,详细解析了Spring AI Alibaba的三层抽象设计,包括模型支持、工作流智能体编排及生产可用性构建能力,确保安全合规、高效部署与可观测性。最后,结合实际案例展示了如何利用私域数据优化AI应用,提升业务价值。
1986 4
|
负载均衡 Java 开发者
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
1020 5
|
网络协议 网络安全 数据安全/隐私保护
计算机网络概念:网关,DHCP,IP寻址,ARP欺骗,路由,DDOS等
计算机网络概念:网关,DHCP,IP寻址,ARP欺骗,路由,DDOS等
454 4
|
网络协议 网络安全 数据安全/隐私保护
计算机网络概念:网关,DHCP,IP寻址,ARP欺骗,路由,DDOS等
【10月更文挑战第27天】计算机主机网关的作用类似于小区传达室的李大爷,负责将内部网络的请求转发到外部网络。当小区内的小不点想与外面的小明通话时,必须通过李大爷(网关)进行联系。网关不仅帮助内部设备与外部通信,还负责路由选择,确保数据包高效传输。此外,网关还参与路由表的维护和更新,确保网络路径的准确性。
543 2