目录
一、概述
Zuul是一种提供动态路由、监视、弹性、安全性等功能的边缘服务。它是Netflix出品的一个基于JVM路由和服务端的负载均衡器。
API网关为微服务架构中的服务提供了统一的访问入口,客户端通过API网关访问相关服务。API网关的定义类似于设计模式中的门面模式,它相当于整个微服务架构中的门面,所有客户端的访问都通过它来进行路由及过滤。它实现了请求路由、负载均衡、校验过滤、服务容错、服务聚合等功能。

它可以做:路由、过滤、负载均衡、灰度发布
灰度发布(又称金丝雀发布)是一种渐进式软件发布策略,核心是先将新版本推给小部分用户,验证稳定与反馈后逐步扩大范围,最终全量上线,以此降低发布风险、平滑过渡。
它的核心能力包括:
- 动态路由:将请求转发到指定微服务;
- 请求过滤:路由前后的请求 / 响应处理(如鉴权、日志、参数校验);
- 负载均衡:结合 Eureka 实现服务集群的轮询访问;
- 灰度发布:渐进式发布新版本,降低上线风险。
适用场景:适用于 Spring Cloud Netflix 体系的微服务架构,若为 Spring Cloud Alibaba 体系,可优先选择 Gateway(Zuul 2.x 虽支持异步,但生态不如 Gateway 完善)。
二、路由的基本配置
操作前提:
- 已搭建 Eureka 注册中心(端口 7001);
- 已开发并注册支付服务(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;