Zuul的工做原理以及相关参数配置

Zuul的工做原理

Zuul的核心时一系列的过滤器Filter来实现的,zuul的全部功能都是基于过滤器去实现的。web

Zuul Filter 的主要特色

  • Filter的类型:Filter的类型决定了此Filter在Filter链中的执行顺序。多是路由发生前,可能路由动做发生时,可能时路由动做发生后,也多是在路由过程发生在异常时。
  • Filter的执行顺序:统一类型的Filter能够经过filterOrder()方法来设定字定义的Filter的执行顺序。
  • Filter的执行条件:Filter运行所须要的标准或条件
  • Filter的执行效果:符合某个Filter的中条件,尝试的执行效果。

Zuul生命周期

Zuul一共有四种不一样的生命周期的Filter,分别是:算法

  1. pre:在Zuul按照规则路由到下级服务以前执行。若是须要对请求进行预处理,好比鉴权,限流等,都应该考虑在此类Filter实现。spring

  2. route:这个类Filter是Zuul路由动做的执行者,是Apache HttpClient或Netflix Ribbon构建和发送原始HTTP请求的地方法,目前支持OkHttp。数据库

  3. post:这类Filter是在源服务返回结果或者异常信息发生后执行,若是须要对返回信息作一些处理,则在此类Filter进行处理。api

  4. error:在整个生命周期内若是发生异常,则会进入error Filter,可作全局异常处理。网络

在实际项目中,每每须要自实现以上类型的Filter来对请求链路进行处理,根据业务的需求,选取相应的生命周期的Filter来达成目的。在Filter之间,经过RequestContext类老进行通讯,内部采用ThreadLocal保存你没给请求的一些信息,包括请求路由,错误信息,HttpServletRequest,HttpServletResponse,这使得一些操做时十分可靠的,它还扩张了ConcurrentHashMap,目的时为了在处理工程中保存各类形式的信息。app

Zuul原生Filter

若是使用@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.

实现自定义的Filter

在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();
    }
}
复制代码

后台打印的日志以下:

Zuul限流

限流的算法主要有两种算法,分别以下:

  1. 漏桶算法:

    漏桶算法(Leaky Bucket)是网络世界中流量整形(Traffic Shaping)或速率限制(Rate Limiting)时常用的一种算法,它的主要目的是控制数据注入到网络的速率,平滑网络上的突发流量。漏桶算法提供了一种机制,经过它,突发流量能够被整形以便为网络提供一个稳定的流量。

  2. 令牌算法:

令牌桶算法是网络流量整形(Traffic Shaping)和速率限制(Rate Limiting)中最常使用的一种算法。典型状况下,令牌桶算法用来控制发送到网络上的数据的数目,并容许突发数据的发送。

显示限流中咱们最经常使用的方式是定义Filter,而后加上上面的主要限流算法便可。在实际开发中咱们可使用别人现成的工具。spring-cloud-zuul-ratelimit,该框架主要用于提供Zuul的限流,该框架提供了不少细粒度的策略:

  • user:认证用户名或者匿名,针对某个用户粒度进行限流
  • origin:客户机ip,针对请求客户机ip粒度进行限流
  • url:特定的url,针对某个请求url粒度进行限流
  • serviceId:特定服务,针对某个服务id粒度进行限流

多种粒度临时变量存储方式

  • IN_MEMEORY:基于本地内存,底层是ConcurrentHashMap
  • REDIS:Redis的K/V存储
  • CONSUL:Consul的K/V存储
  • JPA:Spring Data JPA,基于数据库的存储
  • BUKE4J:一个使用JAVA编写的基于令牌算法的限流库,主要有四种模式:JCache,Hazelcast,Apache Ignite,Inifinispan。

上面主要是一些关于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的文件上传

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的饥饿加载

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
复制代码
相关文章
相关标签/搜索