zuul 源碼解析
1. RefreshableRouteLocatorRouteLocator
路由定位器,在 Spring Cloud Zuul 中,RouteLocator 的主要作用是加載 zuul 路由配置信息(如yml配置文件或數(shù)據(jù)庫)到zuul中,再由過濾器將這些信息一步步去匹配,主要的 RouteLocator 有如下幾種
SimpleRouteLocator
主要加載配置文件的路由規(guī)則
DiscoveryClientRouteLocator
服務(wù)發(fā)現(xiàn)的路由定位器,去注冊中心如Eureka,consul等拿到服務(wù)名稱,以這樣的方式/服務(wù)名稱/**映射成路由規(guī)則
CompositeRouteLocator
復(fù)合路由定位器,主要集成所有的路由定位器(如配置文件路由定位器,服務(wù)發(fā)現(xiàn)定位器,自定義路由定位器等)來路由定位。
RefreshableRouteLocator
路由刷新,只有實現(xiàn)了此接口的路由定位器才能被刷新
2. 核心過濾器
在Spring Cloud Zuul中,為了讓API網(wǎng)關(guān)組件可以更方便的上手使用,它在HTTP請求生命周期的各個階段默認(rèn)地實現(xiàn)了一批核心過濾器,它們會在API網(wǎng)關(guān)服務(wù)啟動的時候被自動地加載和啟用。我們可以在源碼中查看和了解它們,它們定義于spring-cloud-netflix-core模塊的org.springframework.cloud.netflix.zuul.filters包下。
pre過濾器
- ServletDetectionFilter:它的執(zhí)行順序為-3,是最先被執(zhí)行的過濾器。該過濾器總是會被執(zhí)行,主要用來檢測當(dāng)前請求是通過Spring的DispatcherServlet處理運行,還是通過ZuulServlet來處理運行的。它的檢測結(jié)果會以布爾類型保存在當(dāng)前請求上下文的isDispatcherServletRequest參數(shù)中,這樣在后續(xù)的過濾器中,我們就可以通過RequestUtils.isDispatcherServletRequest()和RequestUtils.isZuulServletRequest()方法判斷它以實現(xiàn)做不同的處理。一般情況下,發(fā)送到API網(wǎng)關(guān)的外部請求都會被Spring的DispatcherServlet處理,除了通過/zuul/路徑訪問的請求會繞過DispatcherServlet,被ZuulServlet處理,主要用來應(yīng)對處理大文件上傳的情況。另外,對于ZuulServlet的訪問路徑/zuul/ ,我們可以通過zuul.servletPath參數(shù)來進行修改。
- Servlet30WrapperFilter:它的執(zhí)行順序為-2,是第二個執(zhí)行的過濾器。目前的實現(xiàn)會對所有請求生效,主要為了將原始的HttpServletRequest包裝成Servlet30RequestWrapper對象。
- FormBodyWrapperFilter:它的執(zhí)行順序為-1,是第三個執(zhí)行的過濾器。該過濾器僅對兩種類請求生效,第一類是Content-Type為application/x-www-form-urlencoded的請求,第二類是Content-Type為multipart/form-data并且是由Spring的DispatcherServlet處理的請求(用到了ServletDetectionFilter的處理結(jié)果)。而該過濾器的主要目的是將符合要求的請求體包裝成FormBodyRequestWrapper對象。
- DebugFilter:它的執(zhí)行順序為1,是第四個執(zhí)行的過濾器。該過濾器會根據(jù)配置參數(shù)zuul.debug.request和請求中的debug參數(shù)來決定是否執(zhí)行過濾器中的操作。而它的具體操作內(nèi)容則是將當(dāng)前的請求上下文中的debugRouting和debugRequest參數(shù)設(shè)置為true。由于在同一個請求的不同生命周期中,都可以訪問到這兩個值,所以我們在后續(xù)的各個過濾器中可以利用這兩值來定義一些debug信息,這樣當(dāng)線上環(huán)境出現(xiàn)問題的時候,可以通過請求參數(shù)的方式來激活這些debug信息以幫助分析問題。另外,對于請求參數(shù)中的debug參數(shù),我們也可以通過zuul.debug.parameter來進行自定義。
- PreDecorationFilter:它的執(zhí)行順序為5,是pre階段最后被執(zhí)行的過濾器。該過濾器會判斷當(dāng)前請求上下文中是否存在forward.to和serviceId參數(shù),如果都不存在,那么它就會執(zhí)行具體過濾器的操作(如果有一個存在的話,說明當(dāng)前請求已經(jīng)被處理過了,因為這兩個信息就是根據(jù)當(dāng)前請求的路由信息加載進來的)。而它的具體操作內(nèi)容就是為當(dāng)前請求做一些預(yù)處理,比如:進行路由規(guī)則的匹配(設(shè)置 routeHost 至 request 域中)、在請求上下文中設(shè)置該請求的基本信息以及將路由匹配結(jié)果等一些設(shè)置信息等,這些信息將是后續(xù)過濾器進行處理的重要依據(jù),我們可以通過RequestContext.getCurrentContext()來訪問這些信息。另外,我們還可以在該實現(xiàn)中找到一些對HTTP頭請求進行處理的邏輯,其中包含了一些耳熟能詳?shù)念^域,比如:X-Forwarded-Host、X-Forwarded-Port。另外,對于這些頭域的記錄是通過zuul.addProxyHeaders參數(shù)進行控制的,而這個參數(shù)默認(rèn)值為true,所以Zuul在請求跳轉(zhuǎn)時默認(rèn)地會為請求增加X-Forwarded-*頭域,包括:X-Forwarded-Host、X-Forwarded-Port、X-Forwarded-For、X-Forwarded-Prefix、X-Forwarded-Proto。我們也可以通過設(shè)置zuul.addProxyHeaders=false關(guān)閉對這些頭域的添加動作。
route過濾器
- RibbonRoutingFilter:它的執(zhí)行順序為10,是route階段第一個執(zhí)行的過濾器。該過濾器只對請求上下文中存在serviceId參數(shù)的請求進行處理,即只對通過serviceId配置路由規(guī)則的請求生效。而該過濾器的執(zhí)行邏輯就是面向服務(wù)路由的核心,它通過使用Ribbon和Hystrix來向服務(wù)實例發(fā)起請求,并將服務(wù)實例的請求結(jié)果返回。
- SimpleHostRoutingFilter:它的執(zhí)行順序為100,是route階段第二個執(zhí)行的過濾器。該過濾器只對請求上下文中存在routeHost參數(shù)的請求進行處理,即只對通過url配置路由規(guī)則的請求生效。而該過濾器的執(zhí)行邏輯就是直接向routeHost參數(shù)的物理地址發(fā)起請求,從源碼中我們可以知道該請求是直接通過httpclient包實現(xiàn)的,而沒有使用Hystrix命令進行包裝,所以這類請求并沒有線程隔離和斷路器的保護。
- SendForwardFilter:它的執(zhí)行順序為500,是route階段第三個執(zhí)行的過濾器。該過濾器只對請求上下文中存在forward.to參數(shù)的請求進行處理,即用來處理路由規(guī)則中的forward本地跳轉(zhuǎn)配置。
post過濾器
- SendErrorFilter:它的執(zhí)行順序為0,是post階段第一個執(zhí)行的過濾器。該過濾器僅在請求上下文中包含error.status_code參數(shù)(由之前執(zhí)行的過濾器設(shè)置的錯誤編碼)并且還沒有被該過濾器處理過的時候執(zhí)行。而該過濾器的具體邏輯就是利用請求上下文中的錯誤信息來組織成一個forward到API網(wǎng)關(guān)/error錯誤端點的請求來產(chǎn)生錯誤響應(yīng)。
- SendResponseFilter:它的執(zhí)行順序為1000,是post階段最后執(zhí)行的過濾器。該過濾器會檢查請求上下文中是否包含請求響應(yīng)相關(guān)的頭信息、響應(yīng)數(shù)據(jù)流或是響應(yīng)體,只有在包含它們其中一個的時候就會執(zhí)行處理邏輯。而該過濾器的處理邏輯就是利用請求上下文的響應(yīng)信息來組織需要發(fā)送回客戶端的響應(yīng)內(nèi)容。


浙公網(wǎng)安備 33010602011771號