微服务网关:Zuul
前言#
网关是一个系统的入口。请求首先通过网关,进行路径的路由,定位到具体的服务节点上
Zuul是一个微服务网关,首先是一个微服务。也是会在注册中心中进行服务的注册和发现。也是一个网关,请求应该通过Zuul来进行路由
Zuul的核心是一系列过滤器
Zuul的作用#
- 统一入口:未全部为服务提供一个唯一的入口,网关起到外部和内部隔离的作用,保障了后台服务的安全性
- 鉴权校验:识别每个请求的权限,拒绝不符合要求的请求
- 动态路由:动态的将请求路由到不同的后端集群中
- 减少客户端与服务端的耦合:服务可以独立发展,通过网关层来做映射
快速实现#
环境准备#
eureka-server01:注册中心
eureka-server02:注册中心
product-service:商品微服务,提供查询接口http://localhost:7070/product/{id}
order-service:订单微服务,提供查询接口http://localhost:9090/order/{id}
eureka-server01配置文件
spring:
application:
name: eureka-server01
server:
port: 8761
eureka:
instance:
hostname: eureka01
prefer-ip-address: true
instace-id: ${spring.cloud.client.ip-address}:${server.port}
client:
service-url:
default-zone: http://localhost:8762/eureka/
eureka-server01启动类
@SpringBootApplication
@EnableEurekaServer
public class EurekaServer01 {
public static void main(String[] args) {
SpringApplication.run(EurekaServer01.class, args);
}
}
eureka-server02配置与01基本相同,端口改成8672,其他不再赘述
product-service配置文件
spring:
application:
name: product-service
server:
port: 7070
...
client:
service-url:
default-zone: http://localhost:8761/eureka/,default-zone: http://localhost:8762/eureka/
...
order-service配置与product-service基本一致,将端口改为9090,其他不再赘述
Zuul网关搭建#
pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
启动类
@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
url地址路由#
配置文件
server:
port: 9000
spring:
application:
name: zuul-server
zuul:
routes:
# 路由id,这个地方可以任意取名,不一定和目标微服务名相同,但约定大于配置(挖坑)
product-service:
# 通配符
# ? 匹配单个字符
# * 匹配任意数量字符但不包括子路径
# ** 匹配任意数量字符包括所有下级路径
path: /product-service/**
url: http://localhost:7070/
通过这个配置文件,当请求url为http://localhost:9000/product-service/product/1
就会路由到http://localhost:7070/product/1
,即将**内容拼接到配置文件中url后面
服务名称路由#
Zuul支持和Eureka进行整合,根据serviceid自动从注册中心获取服务地址进行请求转发,这样的好处在于添加或者删除修改服务实例时,不需要再去修改配置文件
pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
配置文件
server:
port: 9000
spring:
application:
name: zuul-server
zuul:
routes:
product-service:
path: /product-service/**
# 根据serviceId自动从注册中心获取服务地址进行路由转发
serviceId: product-service
eureka:
instance:
hostname: eureka01
prefer-ip-address: true
instace-id: ${spring.cloud.client.ip-address}:${server.port}
client:
service-url:
default-zone: http://localhost:8761/eureka/,http://localhost:8762/eureka/
简化路由规则(填坑)#
默认路由配置:路由id和微服务名称一致,path默认对应微服务名称/**
所以当Zuul只起路由转发的作用时,配置文件可以写成
server:
port: 9000
spring:
application:
name: zuul-server
eureka:
instance:
hostname: eureka01
prefer-ip-address: true
instace-id: ${spring.cloud.client.ip-address}:${server.port}
client:
service-url:
default-zone: http://localhost:8761/eureka/,http://localhost:8762/eureka/
这样默认会有两条路由规则
product-service对应/product-service/**
order-service对应/order-service/**
路由排除#
通过路由排除,可以设置不允许访问的资源
url排除
zuul:
ignored-patterns: /**/order/**
服务名称排除
zuul:
ignored-services: order-service
路由前缀#
zuul:
prefix: /api
网关过滤器#
- 前置过滤 请求进入Zuul后,立即执行的过滤逻辑
- 路由后过滤 路由执行后,服务调用前执行的过滤逻辑
- 后置过滤 服务调用结束后执行的过滤逻辑
- 异常过滤 任意一个过滤器发生异常或远程服务调用无结果反馈的时候执行的过滤逻辑
实现方式#
继承ZuulFilter类,重写其中filterType,filterOrder,shouldFilter,run四个方法
快速入门
@Component
public class CustomFilter extends ZuulFilter{
/***
* TODO
* @description: 过滤器类型
* @return:
* pre-路由前
* routing-路由后,调用前
* post-在route或error执行后
* error-任意一个filter发生异常的时候执行或远程服务调用没有反馈时
*/
@Override
public String filterType() {
return "pre";
}
/***
* TODO
* @description: 定义执行顺序,数值越小优先级越高
* @return: 优先级
*/
@Override
public int filterOrder() {
return 0;
}
/***
* TODO
* @description: 过滤器是否生效
*/
@Override
public boolean shouldFilter() {
return false;
}
/***
* TODO
* @description: 执行逻辑
*/
@Override
public Object run() throws ZuulException {
return null;
}
}
统一鉴权案例#
// 这段代码的业务逻辑仅作演示使用,重要的是了解需要重写的方法的含义 >_< ~
@Component
public class AccessFilter 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 rc = RequestContext.getCurrentContext();
HttpServletRequest request = rc.getRequest();
String token = request.getParameter("token");
if(token == null){
rc.setSendZuulResponse(false);
rc.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
rc.getResponse().setContentType("application/json; charset=utf-8");
PrintWriter writer = null;
try {
writer = rc.getResponse().getWriter();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(writer != null){
writer.close();
}
}
}
return null;
}
}
rc.setSendZuulResponse(false);
这个语句的含义是:这个请求最终不会被zuul转发到后端服务器,但是如果当前Filter后面还存在其他Filter,那么其他Filter依旧会被调用
Zuul请求生命周期#
看一下就好
网关容错(挖坑)#
本文内容参考
《SpringCloud之Zuul网关原理及其配置》
《2021最新版-SpringCloud-微服务-Zuul服务网关框架搭建-通俗易懂附配套资料》
作者:colee51666
出处:https://www.cnblogs.com/colee51666/p/16440920.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
尊重每一个原创,从你我开始!
转载请注明原文链接,如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“👍”哦,博主在此感谢你的支持!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南