javascript
Spring Cloud【Finchley】-18 Zuul过滤器
文章目錄
- 概述
- Filter Types
- Zuul 請求生命周期
- 示例
- Step1 新建模塊
- Step2 自定義zuul過濾器
- Step3 初始化zuul過濾器
- Step4 測試
- 禁用zuul過濾器
- 代碼
- 20190413更新
- Pre和Post過濾器(補(bǔ)充示例)
概述
前面幾篇博文,我們梳理了zuul的基本使用、路由及容錯(cuò).
我們知道,zuul包含了對請求的路由和過濾兩個(gè)功能,
- 路由功能負(fù)責(zé)將外部請求轉(zhuǎn)發(fā)到具體的微服務(wù)實(shí)例上,是實(shí)現(xiàn)外部訪問統(tǒng)一入口的基礎(chǔ)
- 過濾器功能則負(fù)責(zé)對請求的處理過程進(jìn)行干預(yù),是實(shí)現(xiàn)請求校驗(yàn)、服務(wù)聚合等功能的基礎(chǔ)
每一個(gè)進(jìn)入Zuul的HTTP請求都會經(jīng)過一系列的過濾器處理鏈得到請求響應(yīng)并返回給客戶端。
Spring Cloud官網(wǎng)中的介紹比較少 , https://cloud.spring.io/spring-cloud-static/Finchley.SR2/single/spring-cloud.html#_disable_zuul_filters
那我們就去zuul自己的官網(wǎng)上去看看吧 (這里我們看的是zuul1.x)
https://github.com/Netflix/zuul/wiki/How-it-Works
Filter Types
在Spring Cloud Zuul中實(shí)現(xiàn)的過濾器必須包含4個(gè)基本特征:
- 過濾類型
- 執(zhí)行順序
- 執(zhí)行條件
- 具體操作
我們通過zuul的源碼ZuulFilter來看下, ZuulFilter是一個(gè)抽象類,并且實(shí)現(xiàn)了IZuulFilter接口
IZuulFilter
- filterType:該函數(shù)需要返回一個(gè)字符串來代表過濾器的類型,而這個(gè)類型就是在HTTP請求過程中定義的各個(gè)階段。
在Zuul中默認(rèn)定義了四種不同生命周期的過濾器類型,具體如下:
- filterOrder:通過int值來定義過濾器的執(zhí)行順序,數(shù)值越小優(yōu)先級越高。
- shouldFilter:返回一個(gè)boolean類型來判斷該過濾器是否要執(zhí)行。我們可以通過此方法來指定過濾器的有效范圍。
- run:過濾器的具體邏輯。在該函數(shù)中,我們可以實(shí)現(xiàn)自定義的過濾邏輯,來確定是否要攔截當(dāng)前的請求,不對其進(jìn)行后續(xù)的路由,或是在請求路由返回結(jié)果之后,對處理結(jié)果做一些加工等。
Zuul 請求生命周期
Zuul默認(rèn)定義了四個(gè)不同的過濾器類型,它們覆蓋了一個(gè)外部HTTP請求到達(dá)API網(wǎng)關(guān),直到返回請求結(jié)果的全部生命周期.
下圖來自Zuul的官方WIKI中關(guān)于請求生命周期的圖解,它描述了一個(gè)HTTP請求到達(dá)API網(wǎng)關(guān)之后,如何在各個(gè)不同類型的過濾器之間流轉(zhuǎn)的詳細(xì)過程。
當(dāng)外部HTTP請求到達(dá)API網(wǎng)關(guān)服務(wù)的時(shí)候,首先它會進(jìn)入第一個(gè)階段pre,在這里它會被pre類型的過濾器進(jìn)行處理,該類型的過濾器主要目的是在進(jìn)行請求路由之前做一些前置加工,比如請求的校驗(yàn)等
在完成了pre類型的過濾器處理之后,請求進(jìn)入第二個(gè)階段routing,也就是之前說的路由請求轉(zhuǎn)發(fā)階段,請求將會被routing類型過濾器處理,這里的具體處理內(nèi)容就是將外部請求轉(zhuǎn)發(fā)到具體服務(wù)實(shí)例上去的過程
當(dāng)服務(wù)實(shí)例將請求結(jié)果都返回之后,routing階段完成,請求進(jìn)入第三個(gè)階段post,此時(shí)請求將會被post類型的過濾器進(jìn)行處理,這些過濾器在處理的時(shí)候不僅可以獲取到請求信息,還能獲取到服務(wù)實(shí)例的返回信息,所以在post類型的過濾器中,我們可以對處理結(jié)果進(jìn)行一些加工或轉(zhuǎn)換等內(nèi)容
還有一個(gè)特殊的階段error,該階段只有在上述三個(gè)階段中發(fā)生異常的時(shí)候才會觸發(fā),但是它的最后流向還是post類型的過濾器,因?yàn)樗枰ㄟ^post過濾器將最終結(jié)果返回給請求客戶端
示例
Step1 新建模塊
為了區(qū)分起見,我們在父工程下新建個(gè)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 啟用所有的監(jiān)控端點(diǎn) “*”號代表啟用所有的監(jiān)控端點(diǎn),可以單獨(dú)啟用,例如,health,info,metrics # spring boot 升為 2.0 后,為了安全,默認(rèn) Actuator 只暴露了2個(gè)端點(diǎn),heath 和 info management:endpoints:web:exposure:include: "*" endpoint:health:show-details: ALWAYSzuul: routes:microservice-provider-user: /userprovider/**logging:level:com.netflix: DEBUG # 將 com.netflix包的日志級別設(shè)置為debug,將打印zuul的轉(zhuǎn)發(fā)細(xì)節(jié)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:過濾器的執(zhí)行順序,不同的過濾器可以返回相同的數(shù)字
- shouldFilter:表示該過濾器是否要執(zhí)行,true執(zhí)行,false不執(zhí)行
- 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 默認(rèn)為zuul編寫并啟用了一些過濾器 ,我們用的這個(gè)版本在 spring-cloud-netflix-zuul-2.0.0.RELEASE.jar 的org.springframework.cloud.netflix.zuul.filters 目錄下
禁用某個(gè)或某些過濾器,只需要 設(shè)置即可
舉個(gè)例子,比如上面自定義的zuul filter, 我們過想禁用的話,兩種方式
經(jīng)測試,生效,日志中沒有打印run中的輸出。
代碼
https://github.com/yangshangwei/SpringCloudMaster/tree/master/microservice-gateway-zuul-filter
20190413更新
Pre和Post過濾器(補(bǔ)充示例)
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參數(shù)里獲取, 也可以從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;} }總結(jié)
以上是生活随笔為你收集整理的Spring Cloud【Finchley】-18 Zuul过滤器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring Cloud【Finchle
- 下一篇: Spring Boot2.x-07Spr