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
複製代碼
相關文章
相關標籤/搜索