<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    上善若水
    In general the OO style is to use a lot of little objects with a lot of little methods that give us a lot of plug points for overriding and variation. To do is to be -Nietzsche, To bei is to do -Kant, Do be do be do -Sinatra
    posts - 146,comments - 147,trackbacks - 0

    概述

    當Jetty中的Connector收到一個客戶端的連接時(ServerSocket或ServerSocketChannel的accept()方法返回),Connector會首先創(chuàng)建一個ConnectedEndPoint用于和連接的底層(Socket、Channel)打交道(讀寫數(shù)據(jù)),在創(chuàng)建的ConnectedEndPoint時會同時使用該EndPoint創(chuàng)建相應類型的Connection,然后會創(chuàng)建一個Task仍給線程池,最終線程池會啟動一個線程啟動這個Task,而在這個Task中調(diào)用Connection中的handle()方法,以處理當前的連接請求,在這個Task中,它會持續(xù)的調(diào)用Connection中的handle()方法直到連接關(guān)閉或Connector停止。在ConnectorEndPoint中,它自己就實現(xiàn)了Runnable接口,因而可以將它自己丟給線程池,而在SelectChannelEndPoint中則交給SelectorManager來管理客戶端連接過來的Channel,并調(diào)用Connection的handle方法。

    Connection接口定義

    Connection的定義如下:
    public interface Connection {
        // Connection中的核心邏輯,在HttpConnection中,它使用HttpParser解析請求數(shù)據(jù),HttpParser采用事件相應機制,可以通過注冊HttpParser.EventHandler(RequestHandler)填充HttpConnection中的需要從請求消息中獲取的信息,最后在messageComplete()事件相應方法中調(diào)用handleRequest()方法將解析后的Request請求交由Server實例的handle()方法處理。在Jetty中,Server是HandlerWrapper子類,它存儲了所有注冊的Handler,從而將最終的處理流程傳導給所有注冊的Handler。在所有注冊的Handler處理完成后,Connection中的handle()方法會繼續(xù)執(zhí)行,使用HttpGenerator、NestedGenerator將緩存的數(shù)據(jù)刷新到EndPoint中。如果當前請求的相應狀態(tài)是101(Switching Protocols),則handle方法返回的Connection實例是從注冊的以"org.eclipse.jetty.io.Connection"為key的實例,也正是因為這個相應狀態(tài)碼的存在,這個handle方法的返回值是一個Connection。
        Connection handle() throws IOException;

        // 除了handle方法,Connection中還有一些提供了一些包含Connection狀態(tài)的方法:

        
    // 返回Connection創(chuàng)建的時間戳。
        long getTimeStamp();
        // 當前Connection是否處于Idle狀態(tài),如HttpParser、HttpGenerator都處于Idle狀態(tài)。
        boolean isIdle();
        // 當前Connection是否處于Suspended狀態(tài),用于Continuation機制。
        boolean isSuspended();
        // 當Connection關(guān)閉時會調(diào)用這個方法。
        void closed();
        // 當連接的Idle時間超時后調(diào)用該方法,在HttpConnection中,該方法會關(guān)閉EndPoiont。
        void idleExpired();
    }

    Connection類圖



    HttpConnection實現(xiàn)

    HttpConnection是Jetty中對Connection的主要實現(xiàn),它表示Http客戶端和服務器的一次連接,用于將Request、Response、EndPoint聯(lián)系在一起。同時HttpConnection也是在避免使用pooling的方式下重用Request、Response、HttpParser、HttpGenerator、HttpFields(requestFields、responseFields)、Buffer、HttpURI等(因為Jetty保證了每一次連接只創(chuàng)建一個HttpConnection實例,這是一個可以學習的點,不用pooling方式的重用,以進一步提升性能)。另外,HttpConnection還有對Connector和Server實例的引用,并且用request字段記錄了該Connection總共處理的請求數(shù)(在headerComplete回調(diào)函數(shù)中自增)。

    如果請求包含Expect頭,并且其值是100-continue,表示客戶端希望在請求被正真處理前發(fā)送一個響應以表示是否能處理該請求,因而在第一次調(diào)用getInputStream時表示服務器已經(jīng)準備好開始處理請求消息體了,此時在返回ServletInputStream之前,服務器要發(fā)送100 Continue響應消息給客戶端(通過調(diào)用HttpGenerator中的send1xx()方法)。在Jetty中,HttpInput類繼承自ServletInputStream,它從HttpParser中讀取請求消息體數(shù)據(jù)。
    如果請求頭包含Expect頭,并且它的值是102-processing,此時服務器可能會發(fā)送102狀態(tài)碼的響應,表示請求正在被處理,之后會發(fā)送最終的響應。在Jetty中,可以通過Response中的sendError()方法,傳入102的狀態(tài)碼以發(fā)送102狀態(tài)碼的響應(使用HttpGenerator中的send1xx()方法)。

    handle()方法是HttpConnection中的核心方法,在每一個連接到來時,Connector會創(chuàng)建一個Runnable實例,將該Runnable實例扔到線程池中,在該Runnable的run()方法實現(xiàn)中不斷的調(diào)用Connection的handle()方法直到當前連接或Connector關(guān)閉。在該方法的實現(xiàn)中:
    1. 它首先設置_handling字段,表示當前正在處理,并且將當前HttpConnection實例設置到__currentConnection的ThreadLocal變量中。
    2. 循環(huán)處理請求消息直到EndPoint關(guān)閉或者在more_in_buffer為true(初始值為true)。
    3. 如果當前Request處于Async狀態(tài),并且還Async狀態(tài)還沒有結(jié)束,直接調(diào)用handleRequest()方法,如果Async狀態(tài)結(jié)束了,但是HttpParser還沒有結(jié)束,則繼續(xù)使用HttpParser解析,在解析過程中,可能會在headerComplete()、content()、messageComplete()回調(diào)函數(shù)中調(diào)用handleRequest()方法(具體參見HttpParser的實現(xiàn));而后在HttpGenerator已經(jīng)Commit(所有的響應頭已經(jīng)準備好,并已經(jīng)寫入到EndPoint中),但是還沒有完成的情況下,將HttpGenerator中的數(shù)據(jù)Flush到EndPoint中;此時如果EndPoint還存在輸出緩存,則將其Flush到底層鏈路中。
    4. 如果當前Request沒有處于Async狀態(tài),如果HttpPaser還沒有結(jié)束,使用HttpParser解析,在解析過程中,可能會在headerComplete()、content()、messageComplete()回調(diào)函數(shù)中調(diào)用handleRequest()方法(具體參見HttpParser的實現(xiàn));而后在HttpGenerator已經(jīng)Commit(所有的響應頭已經(jīng)準備好,并已經(jīng)寫入到EndPoint中),但是還沒有完成的情況下,持續(xù)的將HttpGenerator中的數(shù)據(jù)Flush到EndPoint中,如果EndPoint還存在輸出緩存,則將其Flush到底層鏈路中;如果HttpGenerator已經(jīng)處于完成狀態(tài),但是EndPoint中還有輸出緩存數(shù)據(jù),此時將這些數(shù)據(jù)Flush到底層鏈路,如果寫完緩存中的數(shù)據(jù),將progress設置為true,表示handle方法需要繼續(xù)處理。
    5. 在這些過成中如果出現(xiàn)任何HttpException,則使用HttpGenerator發(fā)送錯誤響應碼給客戶端(使用sendError()方法,并關(guān)閉EndPoint)。
    6. 如果HttpParser中還有數(shù)據(jù)未處理或者EndPoint中還有輸入數(shù)據(jù)未處理,則循環(huán)繼續(xù)。
    7. 如果此時HttpParser已經(jīng)處理完成,HttpGenerator已經(jīng)處理完成,并且EndPoint中的輸出緩存中已經(jīng)沒有任何數(shù)據(jù):1. 如果響應狀態(tài)碼時101 Switching Protocols,且在Request存在org.eclipse.jetty.io.Connection的Connection實例,則新的Connection從Request的該Attribute中獲取,并重置HttpParser和HttpGenerator;2. 如果Request不存在該Attribute的Connection,HttpGenerator非persisent狀態(tài)或EndPoint的InputStream已經(jīng)關(guān)閉,則重置HttpParser,關(guān)閉EndPoint,設置more_in_buffer為false,重置當前HttpConnection。
    8. 如果HttpParser處于idle狀態(tài),并且EndPoint的InputStream已經(jīng)關(guān)閉,則關(guān)閉當前EndPoint,并設置more_in_buffer為false。
    9. 如果Request的Async處于啟動狀態(tài),則設置more_in_buffer為false。
    10. 如果EndPoint是AsyncEndPoint,Generator已經(jīng)Commit,但是還未Complete,則該EndPoint schedule一個write操作。
    11. 最后,清理_handle字段和__currentConnection的ThreadLocal字段。

    handleRequest()是HttpConnection在對請求消息頭解析完成后執(zhí)行的真正處理邏輯方法:
    1. 對任何Request還沒有處理完成,并且Server不為null且處于Running狀態(tài),循環(huán)處理。
    2. 設置Request的handled為false,以及PathInfo字段(如果pathInfo為null,又不是Connect請求,則為400 Error)。
    3. 如果_out字段不為null,reopen it。
    4. 如果Request處于initial狀態(tài),設置Request的DispatcherType為REQUEST,使用當前的EndPoint和Request實例配置Connector,并調(diào)用使用當前HttpConnection作為參數(shù)調(diào)用Server的handle()方法;否則,設置Request的DispatcherType為ASYNC,調(diào)用Server的handleAsync()方法(傳入當前HttpConnection做為參數(shù))。
    5. 對任何非ContinuationThrowable異常,設置Request的handled為true,error為true,對HttpException使用Response發(fā)送響應狀態(tài)碼給客戶端,而對Throwable,使用HttpGenerator發(fā)送400或500狀態(tài)碼給客戶端。
    6. 如果此時Request處于為完成狀態(tài),調(diào)用AsyncContinuation.doComplete()方法;如果100 Continue響應沒有發(fā)送給客戶端,則清除該狀態(tài),但是如果此時Response還沒有Commit,則設置HttpGenerator的persistent為false,表示客戶端并沒有發(fā)送數(shù)據(jù)過來,我們可以關(guān)閉該連接了;如果EndPoint關(guān)閉了,則調(diào)用Response的complete方法;如果EndPoint沒有關(guān)閉并且有error,直接關(guān)閉EndPoint;如果EndPoint沒有關(guān)閉,也沒有error,但是HttpGenerator沒有Commit,Request也沒有被handle,則使用resonse發(fā)送404 Resource Not Found響應消息,之后調(diào)用Response的complete方法;最后設置Request的handled為true。

    commitResponse()方法,用于控制HttpGenerator的執(zhí)行流程:
    1. 在HttpGenerator還沒有Commit之前(即響應狀態(tài)行和響應消息頭還沒寫入到EndPoint中)時,先調(diào)用HttpGenerator的setResponse()方法設置狀態(tài)行。
    2. 然后調(diào)用HttpGenerator的completeHeader()方法將響應消息頭寫入到EndPoint中。
    3. 最后調(diào)用HttpGenerator的complete方法,不斷的將HttpGenerator中的緩存寫入到EndPoint中。

    flushResponse()方法只是調(diào)用了commitResponse方法。

    HttpOutput時Jetty中繼承自ServletOutputStream的類,它使用AbstractorGenerator向底層EndPoint中寫入數(shù)據(jù)。

    Output時HttpConnection中的內(nèi)部類,它繼承自HttpOutput,它在調(diào)用close/flush時會先調(diào)用commitResponse/flushReponse方法,保證響應消息先寫狀態(tài)行,然后是響應消息頭,最后才是響應消息體。該類還實現(xiàn)了sendContent方法,其參數(shù)可以是HttpContent類型或Resource類型,該方法是一個Util方法,它會自動設置Content-Type、Content-Length、Last-Modified等頭,并將HttpContent或Resource對應的數(shù)據(jù)寫入到EndPoint中。
    posted on 2014-03-29 14:42 DLevin 閱讀(3024) 評論(5)  編輯  收藏 所屬分類: Jetty

    FeedBack:
    # 戀字坊
    2014-03-30 23:08 | 戀字坊
    學習了,先收藏一下,具體用的時候再看看  回復  更多評論
      
    # re: 深入Jetty源碼之Connection
    2014-03-31 09:00 | 萬利鎖業(yè)
    支持博主更新 啊  回復  更多評論
      
    # re: 深入Jetty源碼之Connection
    2014-04-08 16:52 | 真相帝
    雖然看不懂,但是感覺很厲害的樣子!!  回復  更多評論
      
    # re: 深入Jetty源碼之Connection
    2014-04-11 10:34 | 無添加護膚品
    // 返回Connection創(chuàng)建的時間戳。
    long getTimeStamp();  回復  更多評論
      
    # re: 深入Jetty源碼之Connection
    2014-05-06 10:43 | 同款網(wǎng)
    我也先收藏一下,寫得非常好,將來可以運用的同款網(wǎng)上使用,先收獲了很多  回復  更多評論
      
    主站蜘蛛池模板: 亚洲一区二区视频在线观看| 三根一起会坏掉的好痛免费三级全黄的视频在线观看 | 亚洲黄页网在线观看| 亚洲视频精品在线观看| 亚洲精彩视频在线观看| 亚洲色图视频在线观看| 日韩成人精品日本亚洲| 久久综合给合久久国产免费| 免费乱码中文字幕网站| 亚洲日韩涩涩成人午夜私人影院| 亚洲视频精品在线观看| 一级**爱片免费视频| 一二三四免费观看在线视频中文版| 91在线视频免费91| 亚洲最大激情中文字幕| 亚洲一区二区观看播放| 日本视频免费高清一本18| 免费观看四虎精品国产永久| 亚洲中文字幕无码一区二区三区| 亚洲国产精品日韩在线| 国产自国产自愉自愉免费24区| 毛片无码免费无码播放| 亚洲精品在线视频| 精品亚洲456在线播放| 久久免费视频精品| 亚洲美日韩Av中文字幕无码久久久妻妇| 亚洲人成影院午夜网站| 女bbbbxxxx另类亚洲| 日本免费xxxx| 国产亚洲精品一品区99热| 污网站免费在线观看| 黄色成人网站免费无码av| 亚洲欧洲日产国产综合网| 色吊丝性永久免费看码 | AV片在线观看免费| 亚洲综合成人网在线观看| xxxxx做受大片在线观看免费| 日韩毛片免费在线观看| 综合久久久久久中文字幕亚洲国产国产综合一区首 | 亚洲AV永久无码精品| 一级毛片大全免费播放下载|