1. 程式人生 > >微服務閘道器Zuul過濾器Filter

微服務閘道器Zuul過濾器Filter

## Zuul本質 Zuul是一個閘道器,關於閘道器的介紹參考:[億級流量架構之閘道器設計思路、常見閘道器對比](https://www.cnblogs.com/Courage129/p/14446586.html), 可知Zuul是一個業務閘道器, 而深入瞭解Zuul, 基本就是一系列過濾器的集合: ![img](https://img2020.cnblogs.com/blog/2002319/202102/2002319-20210225135718363-448942492.png) ## Zuul的過濾器 下面開始詳細瞭解Zuul的過濾器, 主要有pre、rout、post、error四種過濾器型別,將這個整明白了, zuul的使用就過大半了。 四種類型過濾器呼叫順序: ![](https://img2020.cnblogs.com/blog/2002319/202103/2002319-20210311131450308-1195871209.png) 過濾器型別定義在filterType方法中, 返回一個字串代表過濾器的型別,在zuul中定義的四種不同生命週期的過濾器型別,主要功能如下: - `pre`:在請求被路由之前呼叫, 利用這種路由器進行鑑權等服務, 記錄日誌、 限流 - `route`:在路由請求時候被呼叫,作用是將請求路由到指定服務中去, 用於構建傳送給微服務的請求, 並且用Http Client(或者Ribbon)請求微服務 - `post`:在route和error過濾器之後被呼叫,可以用來新增Header , 記錄日誌, 將響應返回給客戶端。 - `error`:處理請求時發生錯誤時呼叫 >從pre和route階段丟擲的異常將會進入error階段,再進入到post階段進行返回。由於SendErrorFilter需要判斷請求上下文中是否包含`error.status_code`屬性:有的話就用SendErrorFilter處理錯誤結果;沒有的話就用SendResponseFilter返回正常結果,但是`error.status_code`屬性預設是在各個階段過濾器中自己put進去的,這就導致,各個階段過濾器丟擲異常之後,是沒有辦法返回錯誤結果的。因此,我們擴充套件了一個ErrorFilter來捕獲異常,然後手工的設定`error.status_code`屬性,讓SendErrorFilter能正常運作。 每一種處理器具體細分多種, 參考圖(利用谷歌檢索難以搜到圖的來源, 這兒給出我參考部落格的[地址](https://blog.csdn.net/zero__007/article/details/84037246?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-4&spm=1001.2101.3001.4242)): ![](https://img2020.cnblogs.com/blog/2002319/202103/2002319-20210311131503102-1576787223.png) 需要記住幾個常見的, Route中有三種過濾器, 分別是: RibbonXXXFilter : 路由到服務 SimpleHostRoutingFilter : 路由到URL地址 SendForwardFilter : 轉向Filter自己 ## Filter流程以及引數解釋 建立過濾器, 一般是先繼承ZuulFilter然後重寫裡面的方法,分別是: **filterType** : 指定過濾器的型別, 分別是上文提到的四種,pre route post error **filterOrder **: 指定過濾器執行順序, 數字越小越先執行 **shouldFilter** : 是否執行這個過濾器, 也就是上來就看這兒是true還是false, false的話就不執行這個過濾器的邏輯。 **run **: 過濾器執行的邏輯, 這一般是過濾器的重點內容。 下面示例一個限流過濾器: ```java @Component // 交給Spring管理 public class LimitFilter extends ZuulFilter { @Override //指定型別為pre public String filterType() { return FilterConstants.PRE_TYPE; } @Override // 執行執行等級 public int filterOrder() { return -10; } @Override // 是否執行 public boolean shouldFilter() { return true; } //建立令牌 private static final RateLimiter RATE_LIMITER = RateLimiter.create(5); @Override public Object run() throws ZuulException { //拿到請求上下文 RequestContext currentContext = RequestContext.getCurrentContext(); if (RATE_LIMITER.tryAcquire()){ System.out.println("通過"); return null; }else { System.out.println("被限流了"); currentContext.setSendZuulResponse(false); currentContext.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value()); } return null; } } ``` 需要注意的是, 之前說過pre執行順序比post高, 也就意味著即使post執行等級比pre的小的話, pre過濾器還是會優先執行, `filterOrder`只在同一級別的過濾器中才會被