Zuul的核心时一系列的过滤器Filter来实现的,zuul的全部功能都是基于过滤器去实现的。web
Zuul一共有四种不一样的生命周期的Filter,分别是:算法
pre:在Zuul按照规则路由到下级服务以前执行。若是须要对请求进行预处理,好比鉴权,限流等,都应该考虑在此类Filter实现。spring
route:这个类Filter是Zuul路由动做的执行者,是Apache HttpClient或Netflix Ribbon构建和发送原始HTTP请求的地方法,目前支持OkHttp。数据库
post:这类Filter是在源服务返回结果或者异常信息发生后执行,若是须要对返回信息作一些处理,则在此类Filter进行处理。api
error:在整个生命周期内若是发生异常,则会进入error Filter,可作全局异常处理。网络
在实际项目中,每每须要自实现以上类型的Filter来对请求链路进行处理,根据业务的需求,选取相应的生命周期的Filter来达成目的。在Filter之间,经过RequestContext类老进行通讯,内部采用ThreadLocal保存你没给请求的一些信息,包括请求路由,错误信息,HttpServletRequest,HttpServletResponse,这使得一些操做时十分可靠的,它还扩张了ConcurrentHashMap,目的时为了在处理工程中保存各类形式的信息。app
若是使用@EnableZuulProxy注解搭配Spring Boot Actuator,会看到管控的端点的信息,具体的配置以下:框架
添加依赖pom.xml:spring-boot
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
复制代码
添加配置:工具
management:
endpoints:
web:
exposure:
include: "*" # * 在yaml 文件属于关键字
复制代码
访问以下的地址能够看到:
名称 | 类型 | 次序 | 描述 |
---|---|---|---|
ServletDetectionFilter | pre | -3 | 经过Spring Dispatcher检查请求是否经过 |
Servlet30WrapperFilter | pre | -2 | 适配HttpServletRequest为Servlet30Wrapper对象 |
FormBodyWrapperFilter | pre | -1 | 解析表单数据为下游请求从新编译 |
DebugFilter | pre | 1 | Debug路由标识 |
PreDecorationFilter | pre | 5 | 处理请求上下文供后续使用,设置下游相关头信息 |
RibbonRoutingFilter | route | 10 | 使用Ribbon,Hystrix或者嵌入式HTTP客户端发送请求 |
SimpleHostRoutingFilter | route | 100 | 使用Apache的HttpClient发送请求 |
SendForwardFilter | route | 500 | 使用Servlet发送请求 |
SendResponseFilter | post | 1000 | 将代理请求的响应写入当前响应 |
SendErrorFilter | error | 0 | 若是RquestContext.getThrowable()不为空,则转发到error,path配置的路径 |
因为以前的例子的启动类使用了@EnbaleZuulProxy注解后安装的Filter,若是使用了@EnaleZuulServer将缺乏PreDecorationFilter,RibbonRoutingFilter,SimpleHostRoutingFilter等过滤器
以上的过滤器类有可能并不必定可以知足咱们的须要,因此咱们能够采起替代的方式,将其源码覆盖,也能够采起禁用策略: zuul...disable=true,好比要禁用DebugFilter,只须要在配置文件添加以下的配置: zuul.DebugFilter.pre.disable=true.
在Zuul中实现自定义的Filter,咱们只须要集成ZuulFilter类便可,ZuulFilter是一个抽象类,咱们须要实现如下的几个方法:
filterOrder():使用返回值设定Filter执行次序。
filterType():使用返回值摄动Filter类型,能够是pre,route,post,error类型。
shouldFilter():使用返回值设定该Filter是否执行,能够做为开关使用。
run():Filter里面的核心执行逻辑,业务处理在此编写。
除了是上面的方法须要重写以外,还须要把建立好的过滤器加入配置中,咱们能够像下面把配置的加入内存中
@Configuration
public class ZuulFilterConfiguration {
@Bean
public FirstPreFilter firstPreFilter() {
return new FirstPreFilter();
}
@Bean
public SencodPreFilter sencodPreFilter() {
return new SencodPreFilter();
}
@Bean
public ThirdPreFilter thirdPreFilter(){
return new ThirdPreFilter();
}
@Bean
public PostFilter postFilter(){
return new PostFilter();
}
@Bean
public ErrorFilter errorFilter(){
return new ErrorFilter();
}
}
复制代码
后台打印的日志以下:
限流的算法主要有两种算法,分别以下:
漏桶算法:
漏桶算法(Leaky Bucket)是网络世界中流量整形(Traffic Shaping)或速率限制(Rate Limiting)时常用的一种算法,它的主要目的是控制数据注入到网络的速率,平滑网络上的突发流量。漏桶算法提供了一种机制,经过它,突发流量能够被整形以便为网络提供一个稳定的流量。
令牌算法:
令牌桶算法是网络流量整形(Traffic Shaping)和速率限制(Rate Limiting)中最常使用的一种算法。典型状况下,令牌桶算法用来控制发送到网络上的数据的数目,并容许突发数据的发送。
显示限流中咱们最经常使用的方式是定义Filter,而后加上上面的主要限流算法便可。在实际开发中咱们可使用别人现成的工具。spring-cloud-zuul-ratelimit,该框架主要用于提供Zuul的限流,该框架提供了不少细粒度的策略:
多种粒度临时变量存储方式
上面主要是一些关于spring-cloud-zuul-ratelimit的一些基本的只是,现实中须要怎么使用?
pom的依赖
<dependency>
<groupId>com.marcosbarbero.cloud</groupId>
<artifactId>spring-cloud-zuul-ratelimit</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
复制代码
application.yml配置文件的配置
zuul:
ratelimit:
#按力度拆分的临时变量key的前缀
key-prefix: springcloud-book
#启动限流开关
enabled: true
#key的存储类型默认是IN_MEMORY本地存储,此外还有多种形式
repository: in_memory
#标识代理以后,能够单独细化到服务粒度
behind-proxy: true
#犬奴限流策略,可单独细化到服务粒度
default-policy:
#在一个单位时间窗口内的请求数量
limit: 2
#在一个单位时间窗口内的请求时间限制
quota: 1
#单位时间窗口
refresh-interval: 3
type:
- user
- origin
- url
复制代码
连续屡次请求能够看到以下的结果:
Zuul的文件上传直接沿用了Springboot的那一套,因此配置的时候也能够想配置SpringBoot文件上传那样。
spring:
application:
name: zuul-server
servlet: #spring boot2.0以前是http
multipart:
enabled: true # 使用http multipart上传处理
max-file-size: 100MB # 设置单个文件的最大长度,默认1M,如不限制配置为-1
max-request-size: 100MB # 设置最大的请求文件的大小,默认10M,如不限制配置为-1
file-size-threshold: 1MB # 当上传文件达到1MB的时候进行磁盘写入
location: / # 上传的临时目录
##### Hystrix默认超时时间为1秒,若是要上传大文件,为避免超时,稍微设大一点
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 30000
ribbon:
ConnectTimeout: 3000
ReadTimeout: 30000
复制代码
Zuul内部默认使用了Ribbon来调用远程服务,因此因为Ribbon的缘由,在咱们部署好全部的组华南以后,第一次经历zuul的调用每每会注册中心读取服务注册表,初始化Ribbon负载信息,这是一种懒加载的策略,可是这个过程是很耗时的,尤为是服务过多的时候,为了不这个问题,咱们能够在启动的Zuul的时候就姐加载应用程序上下文信息,开启饥饿加载咱们只须要配置配置文件。
zuul:
ribbon:
eager-load:
enabled: true #开启饥饿加载
复制代码
在Spring Cloud中有多种和发送Http请求的返回格式能够与Zuul结合,Ribbon,Feign或者RestTemplate,可是不管选择那种,均可以出现请求失败的状况,在复杂的网络中是无可避免的。Zuul做为uige网关中间件,在出现偶然请求失败的时候进行适当的调整是颇有必要的,重试是能够有效避免一些特殊状况的引发的请求丢失的。
pom依赖:
<!-- https://mvnrepository.com/artifact/org.springframework.retry/spring-retry -->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.2.4.RELEASE</version>
</dependency>
复制代码
配置以下:
ribbon:
#重试机制配置
ConnectTimeout: 3000
ReadTimeout: 60000
MaxAutoRetries: 1 #对第一次请求的服务的重试次数
MaxAutoRetriesNextServer: 1 #要重试的下一个服务的最大数量(不包括第一个服务)
OkToRetryOnAllOperations: true
复制代码