摘要:是開源的微服務網關,它可以和,等組件配合使用,網上也有很多如何使用的文章,我們也在生產環境使用了,所以讀了下的源碼,下面把它分享出來,與大家探討下核心原理。
Zuul是Netflix開源的微服務網關,它可以和Eureka,consul,Ribbon,Hystrix等組件配合使用,網上也有很多如何使用zuul的文章,我們也在生產環境使用了,所以讀了下zuul的源碼,下面把它分享出來,與大家探討下zuul核心原理。
一、spring-cloud-zuul是如何映射路由的?
zuul的路由映射是使用springMVC功能,我們知道springMVC有兩大核心組件:
HandlerMapping:映射器
HandlerAdapter:適配器
具體的springMVC原理這里不做講解,我們來看下zuul是如何自定義HandlerMapping來注冊路由映射的?下圖是springMVC的類繼承關系
很清晰看到Zuul提供的ZuulHandlerMapping是AbstractUrlHandlerMapping的子類,這個類是根據url來查找處理器,核心處理方法在lookupHandler里面:
@Override protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception { if (this.errorController != null && urlPath.equals(this.errorController.getErrorPath())) { return null; } //過濾忽略的路由規則 String[] ignored = this.routeLocator.getIgnoredPaths().toArray(new String[0]); if (PatternMatchUtils.simpleMatch(ignored, urlPath)) { return null; } RequestContext ctx = RequestContext.getCurrentContext(); if (ctx.containsKey("forward.to")) { return null; } if (this.dirty) { synchronized (this) { if (this.dirty) {//如果沒有加載過路由或者路由有刷新,則加載路由 registerHandlers(); this.dirty = false; } } } //根據url調用父類獲取處理器 return super.lookupHandler(urlPath, request); } private void registerHandlers() { //使用路由定位器獲取路由規則 Collectionroutes = this.routeLocator.getRoutes(); if (routes.isEmpty()) { this.logger.warn("No routes found from RouteLocator"); } else { for (Route route : routes) { //調用父類,注冊處理器 registerHandler(route.getFullPath(), this.zuul); } } }
梳理一下,以上方法的核心幾步:
判斷urlPath是否被忽略,如果忽略則返回null
判斷路由規則有沒有加載過或者更新過,沒有加載或者有更新則重新加載
注冊處理器的時候,使用的是ZuulController,是Controller的子類,對應的適配器是SimpleControllerHandlerAdapter,也就說每一個路由規則公共處理器都是ZuulController,這個處理器最終會調用ZuulServlet經過zuul定義的和自定義的攔截器,這個zuul的核心,后面我們作詳細講解。
根據url找到處理器,返回
二、路由定位器
在上面我們注冊了路由規則,而路由規則是由路由定位器獲取,那么zuul給我們提供哪些路由定位器,類圖如下:
SimpleRouteLocator:主要加載配置文件的路由規則
DiscoveryClientRouteLocator:服務發現的路由定位器,去注冊中心如Eureka,consul等拿到服務名稱,以這樣的方式/服務名稱/**映射成路由規則
CompositeRouteLocator:復合路由定位器,主要集成所有的路由定位器(如配置文件路由定位器,服務發現定位器,自定義路由定位器等)來路由定位。
RefreshableRouteLocator:路由刷新,只有實現了此接口的路由定位器才能被刷新
擴展:
1、這里我們可以實現自己的路由定位器,擴展自己想要的功能,如從數據庫加載路由規則,可以參考文章
2、利用服務發現的路由定位器去加載理由規則的時候,我們只是簡單的是把serviceId映射成路由規則,有的時間我們還是想在serviceId和路由之間提供約定 ,于是我們可以使用PatternServiceRouteMapper來實現
@Bean public PatternServiceRouteMapper serviceRouteMapper() { return new PatternServiceRouteMapper( "(?^.+)-(? v.+$)", "${version}/${name}"); }
這樣serviceId:myusers-v1將被映射到路由/ v1 / myusers / **,這里任何正則表達式都可以接受,根據自己需要自己設定。
三、過濾器
前面提到,所以路由請求都會被控制器ZuulControoler攔截到,最終交由ZuulServlet來處理,核心處理代碼如下:
@Override public void service(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) throws ServletException, IOException { try { init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse); // Marks this request as having passed through the "Zuul engine", as opposed to servlets // explicitly bound in web.xml, for which requests will not have the same data attached RequestContext context = RequestContext.getCurrentContext(); context.setZuulEngineRan(); try { preRoute(); } catch (ZuulException e) { error(e); postRoute(); return; } try { route(); } catch (ZuulException e) { error(e); postRoute(); return; } try { postRoute(); } catch (ZuulException e) { error(e); return; } } catch (Throwable e) { error(new ZuulException(e, 500, "UNHANDLED_EXCEPTION_" + e.getClass().getName())); } finally { RequestContext.getCurrentContext().unset(); } }
這段代碼體現了zuul過濾器的生命周期,官方提供了一張圖很形象的展示:
zuul把過濾器分為四個階段,分別是
pre:主要是在請求路由之前調用,很多驗證可以在這里做
route:在路由請求時候被調用,主要用來轉發請求
post:主要用來處理響應請求
error:當錯誤發生時,會經由這個類型的過濾器處理
zuul為我們提供了各個階段的過濾器一共10個
這里我們來著重看下路由階段的兩個過濾器
SimpleHostRoutingFilter:主要提供當路由設置url方式時,由這個路由器來轉發請求,使用的是apache的CloseableHttpClient來發送http請求
RibbonRoutingFilter:當路由設置serviceId時,由此過濾器來轉發請求,這里集成了ribbon,Hystrix,實現負載均衡,熔斷的功能;默認情況下也是使用apache的HttpClient來轉發請求
未完待續......
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/76653.html
摘要:不過在出來之后支持異步了,可以把業務操作放到獨立的線程池里面去,這樣可以盡快釋放線程,本身也支持異步了,本篇文章將帶你如何使用的異步特性來改造優化其性能。 ? 我們知道spring-cloud-zuul是依賴springMVC來注冊路由的,而springMVC又是在建立在servlet之上的(這里微服務專家楊波老師寫過一篇文章講述其網絡模型,可以參考看看),在servlet3.0...
摘要:前言在體系中扮演著統一網關的角色,負責與外部交互。與結合使用,可以根據服務名來訪問后端的服務,對于而言,也是一個。這段代碼表示,如果請求中沒有信息,就會報錯。 前言 Zuul在Spring Cloud 體系中扮演著統一網關的角色,負責與外部交互。用戶可以通過不同的URL特征來訪問不同的后端服務,類似于Nginx代理的效果。Zuul與Eureka結合使用,可以根據服務名來訪問后端的服務,...
摘要:事實是只是部分語言的不同表示法。基于這些,解析器會進行立即或者懶解析。然而,解析器做了完全不相關的額外無用功即解析函數。這里不解析函數,該函數聲明了卻沒有指出其用途。所以之前的例子,解析器實際上 原文請查閱這里,本文采用知識共享署名 4.0 國際許可協議共享,BY Troland。 本系列持續更新中,Github 地址請查閱這里。 這是 JavaScript 工作原理的第十四章。 概...
摘要:事實是只是部分語言的不同表示法。基于這些,解析器會進行立即或者懶解析。然而,解析器做了完全不相關的額外無用功即解析函數。這里不解析函數,該函數聲明了卻沒有指出其用途。所以之前的例子,解析器實際上 原文請查閱這里,本文采用知識共享署名 4.0 國際許可協議共享,BY Troland。 本系列持續更新中,Github 地址請查閱這里。 這是 JavaScript 工作原理的第十四章。 概...
閱讀 3759·2021-11-25 09:43
閱讀 2191·2021-11-23 10:13
閱讀 823·2021-11-16 11:44
閱讀 2369·2019-08-29 17:24
閱讀 1384·2019-08-29 17:17
閱讀 3480·2019-08-29 11:30
閱讀 2584·2019-08-26 13:23
閱讀 2345·2019-08-26 12:10