成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

spring-cloud-zuul原理解析(一)

qingshanli1988 / 2625人閱讀

摘要:是開(kāi)源的微服務(wù)網(wǎng)關(guān),它可以和,等組件配合使用,網(wǎng)上也有很多如何使用的文章,我們也在生產(chǎn)環(huán)境使用了,所以讀了下的源碼,下面把它分享出來(lái),與大家探討下核心原理。

Zuul是Netflix開(kāi)源的微服務(wù)網(wǎng)關(guān),它可以和Eureka,consul,Ribbon,Hystrix等組件配合使用,網(wǎng)上也有很多如何使用zuul的文章,我們也在生產(chǎn)環(huán)境使用了,所以讀了下zuul的源碼,下面把它分享出來(lái),與大家探討下zuul核心原理。

一、spring-cloud-zuul是如何映射路由的?

zuul的路由映射是使用springMVC功能,我們知道springMVC有兩大核心組件:

HandlerMapping:映射器

HandlerAdapter:適配器

具體的springMVC原理這里不做講解,我們來(lái)看下zuul是如何自定義HandlerMapping來(lái)注冊(cè)路由映射的?下圖是springMVC的類繼承關(guān)系

很清晰看到Zuul提供的ZuulHandlerMapping是AbstractUrlHandlerMapping的子類,這個(gè)類是根據(jù)url來(lái)查找處理器,核心處理方法在lookupHandler里面:

@Override
protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
    if (this.errorController != null && urlPath.equals(this.errorController.getErrorPath())) {
        return null;
    }
    //過(guò)濾忽略的路由規(guī)則
    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) {//如果沒(méi)有加載過(guò)路由或者路由有刷新,則加載路由
                registerHandlers();
                this.dirty = false;
            }
        }
    }
    //根據(jù)url調(diào)用父類獲取處理器
    return super.lookupHandler(urlPath, request);
}

private void registerHandlers() {
    //使用路由定位器獲取路由規(guī)則
    Collection routes = this.routeLocator.getRoutes();
    if (routes.isEmpty()) {
        this.logger.warn("No routes found from RouteLocator");
    }
    else {
        for (Route route : routes) {
            //調(diào)用父類,注冊(cè)處理器
            registerHandler(route.getFullPath(), this.zuul);
        }
    }
}

梳理一下,以上方法的核心幾步:

判斷urlPath是否被忽略,如果忽略則返回null

判斷路由規(guī)則有沒(méi)有加載過(guò)或者更新過(guò),沒(méi)有加載或者有更新則重新加載

注冊(cè)處理器的時(shí)候,使用的是ZuulController,是Controller的子類,對(duì)應(yīng)的適配器是SimpleControllerHandlerAdapter,也就說(shuō)每一個(gè)路由規(guī)則公共處理器都是ZuulController,這個(gè)處理器最終會(huì)調(diào)用ZuulServlet經(jīng)過(guò)zuul定義的和自定義的攔截器,這個(gè)zuul的核心,后面我們作詳細(xì)講解。

根據(jù)url找到處理器,返回

二、路由定位器

在上面我們注冊(cè)了路由規(guī)則,而路由規(guī)則是由路由定位器獲取,那么zuul給我們提供哪些路由定位器,類圖如下:

SimpleRouteLocator:主要加載配置文件的路由規(guī)則

DiscoveryClientRouteLocator:服務(wù)發(fā)現(xiàn)的路由定位器,去注冊(cè)中心如Eureka,consul等拿到服務(wù)名稱,以這樣的方式/服務(wù)名稱/**映射成路由規(guī)則

CompositeRouteLocator:復(fù)合路由定位器,主要集成所有的路由定位器(如配置文件路由定位器,服務(wù)發(fā)現(xiàn)定位器,自定義路由定位器等)來(lái)路由定位。

RefreshableRouteLocator:路由刷新,只有實(shí)現(xiàn)了此接口的路由定位器才能被刷新

擴(kuò)展

1、這里我們可以實(shí)現(xiàn)自己的路由定位器,擴(kuò)展自己想要的功能,如從數(shù)據(jù)庫(kù)加載路由規(guī)則,可以參考文章

2、利用服務(wù)發(fā)現(xiàn)的路由定位器去加載理由規(guī)則的時(shí)候,我們只是簡(jiǎn)單的是把serviceId映射成路由規(guī)則,有的時(shí)間我們還是想在serviceId和路由之間提供約定 ,于是我們可以使用PatternServiceRouteMapper來(lái)實(shí)現(xiàn)

@Bean
public PatternServiceRouteMapper serviceRouteMapper() {
    return new PatternServiceRouteMapper(
        "(?^.+)-(?v.+$)",
        "${version}/${name}");
}

這樣serviceId:myusers-v1將被映射到路由/ v1 / myusers / **,這里任何正則表達(dá)式都可以接受,根據(jù)自己需要自己設(shè)定。

三、過(guò)濾器

前面提到,所以路由請(qǐng)求都會(huì)被控制器ZuulControoler攔截到,最終交由ZuulServlet來(lái)處理,核心處理代碼如下:

@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();
    }
}

這段代碼體現(xiàn)了zuul過(guò)濾器的生命周期,官方提供了一張圖很形象的展示:

zuul把過(guò)濾器分為四個(gè)階段,分別是

pre:主要是在請(qǐng)求路由之前調(diào)用,很多驗(yàn)證可以在這里做

route:在路由請(qǐng)求時(shí)候被調(diào)用,主要用來(lái)轉(zhuǎn)發(fā)請(qǐng)求

post:主要用來(lái)處理響應(yīng)請(qǐng)求

error:當(dāng)錯(cuò)誤發(fā)生時(shí),會(huì)經(jīng)由這個(gè)類型的過(guò)濾器處理

zuul為我們提供了各個(gè)階段的過(guò)濾器一共10個(gè)

這里我們來(lái)著重看下路由階段的兩個(gè)過(guò)濾器

SimpleHostRoutingFilter:主要提供當(dāng)路由設(shè)置url方式時(shí),由這個(gè)路由器來(lái)轉(zhuǎn)發(fā)請(qǐng)求,使用的是apache的CloseableHttpClient來(lái)發(fā)送http請(qǐng)求

RibbonRoutingFilter:當(dāng)路由設(shè)置serviceId時(shí),由此過(guò)濾器來(lái)轉(zhuǎn)發(fā)請(qǐng)求,這里集成了ribbon,Hystrix,實(shí)現(xiàn)負(fù)載均衡,熔斷的功能;默認(rèn)情況下也是使用apache的HttpClient來(lái)轉(zhuǎn)發(fā)請(qǐng)求

未完待續(xù)......

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/76653.html

相關(guān)文章

  • 使用servlet3.0異步特性改造spring-cloud-zuul

    摘要:不過(guò)在出來(lái)之后支持異步了,可以把業(yè)務(wù)操作放到獨(dú)立的線程池里面去,這樣可以盡快釋放線程,本身也支持異步了,本篇文章將帶你如何使用的異步特性來(lái)改造優(yōu)化其性能。 ? 我們知道spring-cloud-zuul是依賴springMVC來(lái)注冊(cè)路由的,而springMVC又是在建立在servlet之上的(這里微服務(wù)專家楊波老師寫(xiě)過(guò)一篇文章講述其網(wǎng)絡(luò)模型,可以參考看看),在servlet3.0...

    HmyBmny 評(píng)論0 收藏0
  • 起學(xué)習(xí)使用Spring Cloud Netflix之Zuul

    摘要:前言在體系中扮演著統(tǒng)一網(wǎng)關(guān)的角色,負(fù)責(zé)與外部交互。與結(jié)合使用,可以根據(jù)服務(wù)名來(lái)訪問(wèn)后端的服務(wù),對(duì)于而言,也是一個(gè)。這段代碼表示,如果請(qǐng)求中沒(méi)有信息,就會(huì)報(bào)錯(cuò)。 前言 Zuul在Spring Cloud 體系中扮演著統(tǒng)一網(wǎng)關(guān)的角色,負(fù)責(zé)與外部交互。用戶可以通過(guò)不同的URL特征來(lái)訪問(wèn)不同的后端服務(wù),類似于Nginx代理的效果。Zuul與Eureka結(jié)合使用,可以根據(jù)服務(wù)名來(lái)訪問(wèn)后端的服務(wù),...

    FullStackDeveloper 評(píng)論0 收藏0
  • JavaScript 工作原理之十四-解析,語(yǔ)法抽象樹(shù)及最小化解析時(shí)間的 5 條小技巧

    摘要:事實(shí)是只是部分語(yǔ)言的不同表示法?;谶@些,解析器會(huì)進(jìn)行立即或者懶解析。然而,解析器做了完全不相關(guān)的額外無(wú)用功即解析函數(shù)。這里不解析函數(shù),該函數(shù)聲明了卻沒(méi)有指出其用途。所以之前的例子,解析器實(shí)際上 原文請(qǐng)查閱這里,本文采用知識(shí)共享署名 4.0 國(guó)際許可協(xié)議共享,BY Troland。 本系列持續(xù)更新中,Github 地址請(qǐng)查閱這里。 這是 JavaScript 工作原理的第十四章。 概...

    ZweiZhao 評(píng)論0 收藏0
  • JavaScript 工作原理之十四-解析,語(yǔ)法抽象樹(shù)及最小化解析時(shí)間的 5 條小技巧

    摘要:事實(shí)是只是部分語(yǔ)言的不同表示法?;谶@些,解析器會(huì)進(jìn)行立即或者懶解析。然而,解析器做了完全不相關(guān)的額外無(wú)用功即解析函數(shù)。這里不解析函數(shù),該函數(shù)聲明了卻沒(méi)有指出其用途。所以之前的例子,解析器實(shí)際上 原文請(qǐng)查閱這里,本文采用知識(shí)共享署名 4.0 國(guó)際許可協(xié)議共享,BY Troland。 本系列持續(xù)更新中,Github 地址請(qǐng)查閱這里。 這是 JavaScript 工作原理的第十四章。 概...

    xuxueli 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<