(第八篇)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;
相关推荐
long3162 小时前
弗洛伊德·沃肖算法 Floyd Warshall Algorithm
java·后端·算法·spring·springboot·图论
Loo国昌2 小时前
【LangChain1.0】第一篇:基础认知
后端·python·算法·语言模型·prompt
源代码•宸2 小时前
Golang原理剖析(channel面试与分析)
开发语言·经验分享·后端·面试·golang·select·channel
鹿角片ljp2 小时前
Java多线程编程:从基础到实战的完整指南
java·开发语言·后端
rannn_1113 小时前
【Javaweb学习|Day6】日志技术、多表查询、分页查询及优化(动态SQL)
java·后端·javaweb
IT 行者3 小时前
深入理解 OAuth2/OIDC 中的 Issuer:身份认证的基石
spring
qq_12498707533 小时前
基于微信小程序的宠物寄领养系统(源码+论文+部署+安装)
java·spring boot·后端·微信小程序·小程序·宠物·计算机毕业设计
那我掉的头发算什么3 小时前
【SpringBoot】从创建第一个spring项目开始
spring boot·后端·spring
Chan164 小时前
【 Java八股文面试 | RabbitMQ篇 】
java·spring boot·spring·面试·java-ee·rabbitmq·java-rabbitmq