Spring Cloud【Finchley】-18 Zuul过滤器
文章目录
- 概述
- Filter Types
- Zuul 请求生命周期
- 示例
- Step1 新建模块
- Step2 自定义zuul过滤器
- Step3 初始化zuul过滤器
- Step4 测试
- 禁用zuul过滤器
- 代码
- 20190413更新
- Pre和Post过滤器(补充示例)
概述
前面几篇博文,我们梳理了zuul的基本使用、路由及容错.
我们知道,zuul包含了对请求的路由和过滤两个功能,
- 路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础
- 过滤器功能则负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础
每一个进入Zuul的HTTP请求都会经过一系列的过滤器处理链得到请求响应并返回给客户端。
Spring Cloud官网中的介绍比较少 , https://cloud.spring.io/spring-cloud-static/Finchley.SR2/single/spring-cloud.html#_disable_zuul_filters
那我们就去zuul自己的官网上去看看吧 (这里我们看的是zuul1.x)
https://github.com/Netflix/zuul/wiki/How-it-Works
Filter Types
在Spring Cloud Zuul中实现的过滤器必须包含4个基本特征:
- 过滤类型
- 执行顺序
- 执行条件
- 具体操作
我们通过zuul的源码ZuulFilter来看下, ZuulFilter是一个抽象类,并且实现了IZuulFilter接口
IZuulFilter
- filterType:该函数需要返回一个字符串来代表过滤器的类型,而这个类型就是在HTTP请求过程中定义的各个阶段。
在Zuul中默认定义了四种不同生命周期的过滤器类型,具体如下:
- pre:在请求被路由之前调用,可以利用该过滤器进行身份验证、、在集群中选择请求的微服务,记录调试信息等。
- route :在路由请求时候被调用,用于构建发送给微服务的请求,并使用Apache HttpClient或Netflix Ribbon请求微服务。
- post:在routing和error过滤器之后被调用,可用来为响应添加标准的HTTP header、收集统计信息和指标、将响应从微服务发送给客户端等。
- error:处理请求时发生错误时被调用
- filterOrder:通过int值来定义过滤器的执行顺序,数值越小优先级越高。
- shouldFilter:返回一个boolean类型来判断该过滤器是否要执行。我们可以通过此方法来指定过滤器的有效范围。
- run:过滤器的具体逻辑。在该函数中,我们可以实现自定义的过滤逻辑,来确定是否要拦截当前的请求,不对其进行后续的路由,或是在请求路由返回结果之后,对处理结果做一些加工等。
Zuul 请求生命周期
Zuul默认定义了四个不同的过滤器类型,它们覆盖了一个外部HTTP请求到达API网关,直到返回请求结果的全部生命周期.
下图来自Zuul的官方WIKI中关于请求生命周期的图解,它描述了一个HTTP请求到达API网关之后,如何在各个不同类型的过滤器之间流转的详细过程。
当外部HTTP请求到达API网关服务的时候,首先它会进入第一个阶段pre,在这里它会被pre类型的过滤器进行处理,该类型的过滤器主要目的是在进行请求路由之前做一些前置加工,比如请求的校验等
在完成了pre类型的过滤器处理之后,请求进入第二个阶段routing,也就是之前说的路由请求转发阶段,请求将会被routing类型过滤器处理,这里的具体处理内容就是将外部请求转发到具体服务实例上去的过程
当服务实例将请求结果都返回之后,routing阶段完成,请求进入第三个阶段post,此时请求将会被post类型的过滤器进行处理,这些过滤器在处理的时候不仅可以获取到请求信息,还能获取到服务实例的返回信息,所以在post类型的过滤器中,我们可以对处理结果进行一些加工或转换等内容
还有一个特殊的阶段error,该阶段只有在上述三个阶段中发生异常的时候才会触发,但是它的最后流向还是post类型的过滤器,因为它需要通过post过滤器将最终结果返回给请求客户端
示例
Step1 新建模块
为了区分起见,我们在父工程下新建个module microservice-gateway-zuul-filter
pom.xml 及 application.yml 基本与https://github.com/yangshangwei/SpringCloudMaster/tree/master/microservice-gateway-zuul 相同
pom依赖
<!-- eureka client 依赖 . Eureka不是必须的 ,在没有注册中心的情况下,也可以使用zuul --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!-- zuul 依赖 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-zuul</artifactId></dependency>
application.yml配置文件
server:port: 4536spring:application:name: microservice-gateway-zuul-filtereureka:client:service-url:defaultZone: http://artisan:artisan123@localhost:8761/eurekainstance:instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}#actuator 启用所有的监控端点 “*”号代表启用所有的监控端点,可以单独启用,例如,health,info,metrics
# spring boot 升为 2.0 后,为了安全,默认 Actuator 只暴露了2个端点,heath 和 info
management:endpoints:web:exposure:include: "*" endpoint:health:show-details: ALWAYSzuul: routes:microservice-provider-user: /userprovider/**logging:level:com.netflix: DEBUG # 将 com.netflix包的日志级别设置为debug,将打印zuul的转发细节
Step2 自定义zuul过滤器
package com.artisan.microservice.zuulFilter;import javax.servlet.http.HttpServletRequest;import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;public class PreRequestZuulFilter extends ZuulFilter{@Overridepublic boolean shouldFilter() {return true;}@Overridepublic String filterType() {return "pre";}@Overridepublic int filterOrder() {return 0;}@Overridepublic Object run() throws ZuulException {HttpServletRequest request = RequestContext.getCurrentContext().getRequest();System.out.println("pre filter, 请求路径:" +request.getRequestURI());return null;}}
自定义的zuul过滤器,需要继承 ZuulFilter,重写如上方法
- filterType: 过滤器的类型,取值如下 pre route post error . 可以从源码的注释中看到
- filterOrder:过滤器的执行顺序,不同的过滤器可以返回相同的数字
- shouldFilter:表示该过滤器是否要执行,true执行,false不执行
- run:过滤器的具体逻辑
Step3 初始化zuul过滤器
Step4 测试
- 启动microservice-discovery-eureka
- 启动micorservice-provider-user
- 启动microservice-gateway-zuul-filter
- 访问 http://localhost:4536/userprovider/user/2
观察 microservice-gateway-zuul-filter的日志
禁用zuul过滤器
https://cloud.spring.io/spring-cloud-static/Finchley.SR2/single/spring-cloud.html#_disable_zuul_filters
spring cloud 默认为zuul编写并启用了一些过滤器 ,我们用的这个版本在 spring-cloud-netflix-zuul-2.0.0.RELEASE.jar 的org.springframework.cloud.netflix.zuul.filters 目录下
禁用某个或某些过滤器,只需要 设置即可
zuul.<SimpleClassName>.<filterType>.disable=true
举个例子,比如上面自定义的zuul filter, 我们过想禁用的话,两种方式
- 第一种方式:重写shouldFilter逻辑,返回false
- 第二种方式:application.yml中设置disable属性为true ,如下
经测试,生效,日志中没有打印run中的输出。
代码
https://github.com/yangshangwei/SpringCloudMaster/tree/master/microservice-gateway-zuul-filter
20190413更新
Pre和Post过滤器(补充示例)
package com.artisan.apigateway.filter;import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;import javax.servlet.http.HttpServletRequest;import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;@Component
public class TokenFilter extends ZuulFilter {@Overridepublic String filterType() {return PRE_TYPE;}@Overridepublic int filterOrder() {return PRE_DECORATION_FILTER_ORDER - 1;}@Overridepublic boolean shouldFilter() {return true;}@Overridepublic Object run() {RequestContext requestContext = RequestContext.getCurrentContext();HttpServletRequest request = requestContext.getRequest();//这里从url参数里获取, 也可以从cookie, header里获取String token = request.getParameter("token");if (StringUtils.isEmpty(token)) {requestContext.setSendZuulResponse(false);requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());}return null;}
}
返回值推荐使用FilterConstants类提供的常量
package com.artisan.apigateway.filter;import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletResponse;import java.util.UUID;import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.POST_TYPE;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.SEND_RESPONSE_FILTER_ORDER;@Component
public class AddResponseHeaderFilter extends ZuulFilter{@Overridepublic String filterType() {return POST_TYPE;}@Overridepublic int filterOrder() {return SEND_RESPONSE_FILTER_ORDER - 1;}@Overridepublic boolean shouldFilter() {return true;}@Overridepublic Object run() {RequestContext requestContext = RequestContext.getCurrentContext();HttpServletResponse response = requestContext.getResponse();response.setHeader("X-Foo", UUID.randomUUID().toString());return null;}
}
Spring Cloud【Finchley】-18 Zuul过滤器相关推荐
- 积分和人民币比率_通过比率路由到旧版和现代应用程序–通过Spring Cloud的Netflix Zuul...
积分和人民币比率 从应用程序的旧版本迁移到应用程序的现代化版本时,一个非常常见的要求是能够将用户缓慢迁移到新应用程序. 在本文中,我将介绍通过Spring Cloud使用对Netflix Zuul的支 ...
- 基于比率的路由到旧版和现代应用程序–通过Spring Cloud的Netflix Zuul
从应用程序的旧版本迁移到应用程序的现代化版本时,一个非常普遍的要求是能够将用户缓慢迁移到新应用程序. 在本文中,我将介绍通过Spring Cloud使用对Netflix Zuul的支持编写的这种路由层 ...
- spring cloud 学习(6) - zuul 微服务网关
微服务架构体系中,通常一个业务系统会有很多的微服务,比如:OrderService.ProductService.UserService...,为了让调用更简单,一般会在这些服务前端再封装一层,类似下 ...
- java 配置全局过滤器,如何为Spring Cloud Gateway加上全局过滤器
既然是一个网关.那么全局过滤器肯定是少不了的一个存在.像是鉴权.认证啥的不可能每个服务都做一次,一般都是在网关处就搞定了. Zuul他就有很强大的过滤器体系来给人使用. Gateway当然也不会差这么 ...
- Spring Cloud Finchley OpenFeign的重试配置相关的坑
如题,本文基于Spring Cloud Finchley.SR2 OpenFeign的重试 OpenFeign配置重试后,逻辑分析 对比Daltson和Finchley的基本组件,发现Ribbon还有 ...
- Spring Cloud入门教程 - Zuul实现API网关和请求过滤
简介 Zuul是Spring Cloud提供的api网关和过滤组件,它提供如下功能: 认证 过滤 压力测试 Canary测试 动态路由 服务迁移 负载均衡 安全 静态请求处理 动态流量管理 在本教程中 ...
- Spring Cloud 学习 (五) Zuul
Zuul 作为路由网关组件,在微服务架构中有着非常重要的作用,主要体现在以下 6 个方面: Zuul, Ribbon 以及 Eureka 相结合,可以实现智能路由和负载均衡的功能,Zuul 能够将请求 ...
- Spring Cloud 入门 之 Zuul 篇(五)
一.前言 随着业务的扩展,微服务会不对增加,相应的其对外开放的 API 接口也势必增多,这不利于前端的调用以及不同场景下数据的返回,因此,我们通常都需要设计一个 API 网关作为一个统一的 API 入 ...
- 【Spring Cloud】网关 - Zuul(1.x)
1. 背景 通过Spring Cloud 和微服务的学习,我们了解到使用Spring Cloud实现微服务的架构基本成型,大致是这样的: 我们使用Spring Cloud Netflix中的Eurek ...
最新文章
- Android系统--TouchEvent的处理流程
- Java多线程编写简易飞机大战(一)
- OpenStack 认证服务 KeyStone部署 (四)
- NDR(网络威胁检测及响应)与NTA的区别(网络流量检测)
- [导入]《交互设计之路——让高科技产品回归人性》读书笔记(九)
- 访问远程Visdom
- php 获取css值,如何通过JS获取CSS属性值
- c#设计的简单登录界面
- 一种自动(半自动)学习的算法(验证码识别)
- 用 keepalived 搭建高可用集群之 IP Failover
- EtherCAT总线运动控制学习笔记(RXXW_Dor)
- 贝叶斯小数据分析—— 23 条数据决定宇航员生死(使用 PyMC3)
- Ubuntu中禁止与使能鼠标中键的复制功能(vscode出现莫名其妙的多余的代码段)
- xp系统从u盘启动计算机,教你怎么用U盘安装Windows XP系统
- [苹果开发者账号]06 转让开发者账号后,开发者年费自动续费问题
- 工单系统(源代码)PHP语言开发 开发者版
- 快来开建春晚红包信息群吧!
- linux猜数字代码,Shell脚本实现猜数字游戏
- 高德地图POI分类查询
- 骁龙笔记本的目的究竟是什么