(第八篇)spring cloud之zuul路由网关

目录

一、概述

二、路由的基本配置

(1)创建模块9527

(2)修改pom文件

(3)添加配置文件

(4)编写启动类

(5)测试

1)不使用路由访问

2)使用路由访问

三、路由访问的映射规则

1、代理名称

(1)修改配置文件

(2)测试

2、忽略服务名

(1)修改配置文件

(2)测试

(3)忽略多个

(4)路由转发和负载均衡

3、设置统一前缀

(1)修改配置文件

(2)测试

四、路由信息查询

五、过滤器

(1)介绍

(2)核心分类

(3)案例实现

1)创建一个过滤器类

2)测试

3)禁用过滤器

4)总结


一、概述

Zuul是一种提供动态路由、监视、弹性、安全性等功能的边缘服务。它是Netflix出品的一个基于JVM路由和服务端的负载均衡器。

API网关为微服务架构中的服务提供了统一的访问入口,客户端通过API网关访问相关服务。API网关的定义类似于设计模式中的门面模式,它相当于整个微服务架构中的门面,所有客户端的访问都通过它来进行路由及过滤。它实现了请求路由、负载均衡、校验过滤、服务容错、服务聚合等功能。

它可以做:路由、过滤、负载均衡、灰度发布

灰度发布(又称金丝雀发布)是一种渐进式软件发布策略,核心是先将新版本推给小部分用户,验证稳定与反馈后逐步扩大范围,最终全量上线,以此降低发布风险、平滑过渡。

它的核心能力包括:

  • 动态路由:将请求转发到指定微服务;
  • 请求过滤:路由前后的请求 / 响应处理(如鉴权、日志、参数校验);
  • 负载均衡:结合 Eureka 实现服务集群的轮询访问;
  • 灰度发布:渐进式发布新版本,降低上线风险。

适用场景:适用于 Spring Cloud Netflix 体系的微服务架构,若为 Spring Cloud Alibaba 体系,可优先选择 Gateway(Zuul 2.x 虽支持异步,但生态不如 Gateway 完善)。

二、路由的基本配置

操作前提

  1. 已搭建 Eureka 注册中心(端口 7001);
  2. 已开发并注册支付服务(cloud-provider-hystrix-payment,端口 8001),且该服务提供/payment/circuit/{id}接口。

(1)创建模块9527

(2)修改pom文件

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.hk.cloudstudy</groupId>
        <artifactId>SecondSpringCloud</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <groupId>com.hk</groupId>
    <artifactId>cloud-zuul-gateway9527</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

(3)添加配置文件

XML 复制代码
server:
  port: 9527

spring:
  application:
    name: cloud-zuul-gateway

eureka:
  client:
    service-url:
      #defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
      defaultZone: http://localhost:7001/eureka
  instance:
    instance-id: gateway-9527.com
    prefer-ip-address: true 

(4)编写启动类

java 复制代码
@SpringBootApplication
@EnableZuulProxy
public class ZuulApp {
    public static void main(String[] args) {
        SpringApplication.run(ZuulApp.class,args);
    }
}

(5)测试

启动一个需要访问的模块8001

1)不使用路由访问

localhost:8001/payment/circuit/-10

2)使用路由访问

访问规则:zuul服务地址+注册中心注册后对外暴露的服务名称+rest调用地址

例如:http://localhost:9527/cloud-provider-hystrix-payment/payment/circuit/10

说明:

http://localhost:9527:zuul服务地址

cloud-provider-hystrix-payment:它是8001服务在eureka上对外暴露的名称

payment/circuit/10:需要请求调用的地址

三、路由访问的映射规则

1、代理名称

(1)修改配置文件

java 复制代码
server:
  port: 9527

spring:
  application:
    name: cloud-zuul-gateway

eureka:
  client:
    service-url:
      #defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
      defaultZone: http://localhost:7001/eureka
  instance:
    instance-id: gateway-9527.com
    prefer-ip-address: true

zuul:
  routes: # 路由映射配置
    mypayment.path: /mypayment/**
    mypayment.serviceId: cloud-provider-hystrix-payment   #注册进eureka服务器的地址

(2)测试

  • 原路径:http://localhost:9527/cloud-provider-hystrix-payment/payment/circuit/10(仍可用);
  • 新路径:http://localhost:9527/mypayment/payment/circuit/10(新增代理路径,访问成功)。

2、忽略服务名

(1)修改配置文件

java 复制代码
server:
  port: 9527

spring:
  application:
    name: cloud-zuul-gateway

eureka:
  client:
    service-url:
      #defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
      defaultZone: http://localhost:7001/eureka
  instance:
    instance-id: gateway-9527.com
    prefer-ip-address: true

zuul:
  ignored-services: cloud-provider-hystrix-payment # 忽略的服务名
  routes: # 路由映射配置
    myPayment: # 规则名称
      serviceId: cloud-provider-hystrix-payment # 目标服务名称(与注册中心一致)
      path: /testPay/** # 访问路径

(2)测试

  • 禁止访问:http://localhost:9527/cloud-provider-hystrix-payment/payment/circuit/10(报错);
  • 允许访问:http://localhost:9527/testPay/payment/circuit/10(正常响应)。

(3)忽略多个

java 复制代码
zuul:
  # 忽略的服务名,多个用逗号分隔,忽略全部可以用 *
  ignored-services: "*"
  routes: # 路由映射配置
    myPayment: # 规则名称
      serviceId: cloud-provider-hystrix-payment # 目标服务名称(与注册中心一致)
      path: /testPay/** # 访问路径

(4)路由转发和负载均衡

路由转发:当我们设置多个规则名称,zuul会根据访问路径找到对应的规则名,例如当我们路径是/testPay/**的时候会转发到cloud-provider-hystrix-payment服务,当路径是/testOrder/**的时候会转发到cloud-provider-order服务

java 复制代码
zuul:
  ignored-services: cloud-provider-hystrix-payment # 忽略的服务名
  routes: # 路由映射配置
    myPayment: # 规则名称
      serviceId: cloud-provider-hystrix-payment # 目标服务名称(与注册中心一致)
      path: /testPay/** # 访问路径
    myOrder: # 规则名称
      serviceId: cloud-provider-order # 目标服务名称(与注册中心一致)
      path: /testOrder/** # 访问路径  

负载均衡:当cloud-provider-hystrix-payment服务已集群模式启动多个时,访问/testPay/**的时候会以轮询的模式请求cloud-provider-hystrix-payment的各个服务

3、设置统一前缀

(1)修改配置文件

java 复制代码
zuul:
  prefix: /hk         # 配置统一前缀
  ignored-services: cloud-provider-hystrix-payment # 忽略的服务名
  routes: # 路由映射配置
    myPayment: # 规则名称
      serviceId: cloud-provider-hystrix-payment # 目标服务名称(与注册中心一致)
      path: /testPay/** # 访问路径
    myOrder: # 规则名称
      serviceId: cloud-provider-order # 目标服务名称(与注册中心一致)
      path: /testOrder/** # 访问路径

(2)测试

访问localhost:9527/testPay/payment/circuit/10

四、路由信息查询

(1)修改pom

添加Maven坐标

XML 复制代码
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

(2)修改配置文件

XML 复制代码
server:
  port: 9527

spring:
  application:
    name: cloud-zuul-gateway

eureka:
  client:
    service-url:
      #defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
      defaultZone: http://localhost:7001/eureka
  instance:
    instance-id: gateway-9527.com
    prefer-ip-address: true

zuul:
  prefix: /hk         # 配置统一前缀
  ignored-services: cloud-provider-hystrix-payment # 忽略的服务名
  routes: # 路由映射配置
    myPayment: # 规则名称
      serviceId: cloud-provider-hystrix-payment # 目标服务名称(与注册中心一致)
      path: /testPay/** # 访问路径
    myOrder: # 规则名称
      serviceId: cloud-provider-order # 目标服务名称(与注册中心一致)
      path: /testOrder/** # 访问路径

# 开启查看路由的端点
management:
  endpoints:
    web:
      exposure:
        include: 'routes'

五、过滤器

(1)介绍

Zuul 过滤器是 Zuul 网关的核心扩展组件,所有经过 Zuul 的请求 / 响应都会被过滤器链拦截处理,它能帮你实现路由前的鉴权、灰度流量分流、请求限流,路由后的响应加工,以及异常统一处理等核心能力,是 Zuul 实现定制化业务逻辑的关键。

(2)核心分类

核心分为 4 类(按执行先后排序):

过滤器类型(filterType) 执行时机 核心作用 典型应用场景
PRE 请求路由到目标服务之前 预处理请求(鉴权、参数校验、灰度路由、日志记录) 灰度发布流量分流、Token 校验、请求头修改
ROUTING 路由请求到目标服务过程中 实际转发请求到微服务(可自定义路由规则) 替换默认路由逻辑、自定义负载均衡
POST 请求路由到目标服务之后 处理响应(数据加工、统一返回格式、统计耗时) 统一响应体格式、接口耗时监控
ERROR 任意阶段抛出异常时 全局异常处理

(3)案例实现

1)创建一个过滤器类

每个类型的过滤器可通过filterOrder()指定执行顺序(数值越小,执行越早),相同类型、相同顺序的过滤器执行顺序不保证。

java 复制代码
package com.hk.cloudstudy.filters;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

@Component
@Slf4j
public class PreLogFilter extends ZuulFilter {

    @Override
    public String filterType() {
        // 过滤器类型
        return "pre";
    }

    @Override
    public int filterOrder() {
        // 过滤器顺序
        return 1;
    }

    @Override
    public boolean shouldFilter() {
        // 是否启用过滤器
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        // 核心方法
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        String remoteHost = request.getRemoteHost();
        String method = request.getMethod();
        String requestURI = request.getRequestURI();
        log.info("=====> host: {}, uri: {}, method: {}", remoteHost, requestURI, method);
        return null;
    }
}
  • 执行顺序filterOrder()数值越小,执行越早;建议给鉴权、灰度等核心过滤器设置更小的数值,优先执行。
  • 上下文操作RequestContext是 Zuul 的核心上下文,可通过

ctx.set(key, value)修改路由参数(如 serviceId、path),

ctx.setSendZuulResponse(false)终止路由。

  • 性能影响 :过滤器逻辑要极简(避免复杂计算 / 远程调用),否则会增加网关延迟;可通过shouldFilter()动态禁用非必要过滤器。

  • 禁用内置过滤器 :若需禁用 Zuul 内置过滤器(如默认的表单解析过滤器),可在配置中指定:

    复制代码
    zuul:
      filter:
        formbody:
          pre:
            disable: true # 禁用表单体解析的PRE过滤器
  • 异常处理:ERROR 过滤器仅捕获过滤器链中的异常,若路由到微服务的过程中报错,需结合 Hystrix 做降级处理。

2)测试

访问localhost:9527/hk/testPay/payment/circuit/10

3)禁用过滤器

修改配置文件,添加如下配置

java 复制代码
zuul:
  PreLogFilter:
    pre:
      disable: true
4)总结
  • Zuul 过滤器按生命周期分为PRE(路由前)、ROUTING(路由中)、POST(路由后)、ERROR(异常时)四类,是定制网关逻辑的核心;
  • 自定义过滤器需继承ZuulFilter,重写filterType()(类型)、filterOrder()(顺序)、shouldFilter()(是否启用)、run()(核心逻辑)四个方法,并注册为 Spring Bean;
相关推荐
XovH几秒前
Redis 从入门到精通:数据结构Hash 与 List
后端
Cache技术分享1 分钟前
432. Java 日期时间 API - 时间工具 TemporalQuery 详解
前端·后端
XovH3 分钟前
Redis 从入门到精通:初识 Redis
后端
uhakadotcom18 分钟前
在 Python 开发中 transitions 的使用
后端·面试·github
Rust研习社22 分钟前
通过手写一个迷你 grep 来学习 Rust 的所有权与借用
后端
kakawzw22 分钟前
微服务组件源码6——Spring Gateway
spring·gateway
用户5313973181726 分钟前
「踩坑实录」原来的SQL索引自动优化失败了,线上数据库差点被打挂
java·后端
go不是csgo28 分钟前
从0到1理解Go熔断器:sony/gobreaker 源码剖析 + 仿TikTok Feed 项目实战
开发语言·后端·golang
SimonKing30 分钟前
线程池面试被问到怕?看完这篇让他当场沉默
java·后端·程序员
大刚测试开发实战33 分钟前
TestHub重磅更新!AI用例生成增加流式输出、Markdown文档上传、模型配置检测、AI评审开关控制...
vue.js·后端·github