日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

InfoQ: Web請(qǐng)求異步處理降低應(yīng)用依賴風(fēng)險(xiǎn)

 ivy1107 2009-01-11

Web請(qǐng)求異步處理降低應(yīng)用依賴風(fēng)險(xiǎn)

作者 岑文初 發(fā)布于 2009年1月9日 上午8時(shí)16分

問(wèn)題凸現(xiàn)

年關(guān)到了,商家忙著促銷,網(wǎng)站忙著推廣,阿里軟件的服務(wù)集成平臺(tái)也面臨第一次多方大規(guī)模的壓力考驗(yàn)。根據(jù)該平臺(tái)5.3版本的壓力測(cè)試結(jié)果,我們估算了一下現(xiàn)有的推廣會(huì)帶來(lái)的壓力,基本上確定了服務(wù)集成平臺(tái)年底不需要擴(kuò)容。SA(System Administrator,系統(tǒng)管理員)為了保險(xiǎn)起見(jiàn)還是通過(guò)請(qǐng)求方式來(lái)做定時(shí)的心跳檢測(cè),保證服務(wù)集成平臺(tái)的可靠性。結(jié)果阿里旺旺推廣開(kāi)始的第一天,SA的報(bào)警短信就在幾個(gè)忙時(shí)段不停地發(fā)告警,但是查看生產(chǎn)環(huán)境的服務(wù)器狀況以及應(yīng)用狀況后看不出有什么問(wèn)題,于是開(kāi)始懷疑是否告警機(jī)制不是很合理。幾日的訪問(wèn)記錄統(tǒng)計(jì)報(bào)告看過(guò)以后,發(fā)現(xiàn)了幾個(gè)問(wèn)題,首先由于推廣是在IM登錄時(shí)段集中式的推廣,因此高峰期比較集中,壓力也很大,而告警發(fā)生的時(shí)刻也是那些時(shí)候;另外發(fā)現(xiàn)那些推廣使用的API的處理時(shí)間比較長(zhǎng),同時(shí)還有些出現(xiàn)了問(wèn)題,這幾天除了服務(wù)集成平臺(tái)告警以外,那些API服務(wù)器也在告警;因此可以看出問(wèn)題應(yīng)該是由于API提供商響應(yīng)速度慢而拖累了服務(wù)集成平臺(tái)的處理能力,監(jiān)控機(jī)制在高峰情況下沒(méi)有得到及時(shí)的響應(yīng),就認(rèn)為是服務(wù)器已經(jīng)處于無(wú)效狀態(tài)。

其實(shí)這類問(wèn)題在我們現(xiàn)在的應(yīng)用體系架構(gòu)中常常出現(xiàn),原因是現(xiàn)在很少再有純粹“封閉式”應(yīng)用,對(duì)數(shù)據(jù)庫(kù)的依賴,對(duì)存儲(chǔ)的依賴,對(duì)第三方系統(tǒng)的依賴等等。這也讓我回憶到在前一陣子參加的安全會(huì)議中,騰迅的安全技術(shù)團(tuán)隊(duì)的負(fù)責(zé)人說(shuō)安全現(xiàn)在最大的問(wèn)題就在于合作的第三方的安全不受控而引發(fā)的安全潛在影響。Web應(yīng)用未嘗不是,從最基本的事務(wù)處理要小粒度,不要在事務(wù)中包含第三方依賴,到心跳檢測(cè),容錯(cuò)方案的制定等,都已經(jīng)讓我們對(duì)這方面的問(wèn)題有所注意。但是往往這類問(wèn)題不是局部設(shè)計(jì)可以看到的,如果沒(méi)有一個(gè)總體架構(gòu)設(shè)計(jì)者對(duì)于全局的把握、協(xié)調(diào)和防范,那么問(wèn)題出現(xiàn)并且?guī)?lái)的影響將會(huì)很大。

從前對(duì)于服務(wù)集成平臺(tái)的壓力測(cè)試主要是在ISP服務(wù)“基本正常”的情況下做的,但是這次問(wèn)題的暴露就要求我們?cè)诘谌揭蕾嚦霈F(xiàn)邊界問(wèn)題時(shí),及時(shí)做出一些措施或者改進(jìn)設(shè)計(jì)。

問(wèn)題分析以及解決方案

問(wèn)題原因:

  1. Http請(qǐng)求處理的阻塞方式。
  2. 后端服務(wù)處理時(shí)間過(guò)長(zhǎng),服務(wù)質(zhì)量不穩(wěn)定。
  3. Web Container接受請(qǐng)求線程資源有限。

解決方案:

  1. 改阻塞方式為非阻塞方式來(lái)處理請(qǐng)求。
  2. 設(shè)置后端超時(shí)時(shí)間,主動(dòng)斷開(kāi)連接,回收資源。
  3. 修改容器配置,增加線程池大小以及等待隊(duì)列長(zhǎng)度。

解決方案一是最難做到的,后面的篇幅將描述對(duì)于這方面技術(shù)的探索。
解決方案二比較容易,允許各個(gè)ISP設(shè)置自己API容許的最大超時(shí)時(shí)間。
解決方案三Tomcat和JBoss在Connector中有兩個(gè)參數(shù)配置(maxThreads和acceptCount)可以做調(diào)整。

第一個(gè)方案其實(shí)和JDK 1.5支持的NIO是一種想法,只是我們?cè)赟ocket中都已經(jīng)采用過(guò)了,而在Http請(qǐng)求處理中因?yàn)橐蕾囉赪eb Container開(kāi)發(fā)商的實(shí)現(xiàn),所以至今還沒(méi)有被廣泛應(yīng)用,不過(guò)在開(kāi)源社區(qū)已經(jīng)有用Mina實(shí)現(xiàn)的Http協(xié)議處理的框架。需要注意的是,現(xiàn)在Web應(yīng)用對(duì)于Web請(qǐng)求高效處理的需求僅僅是很小的一方面,其實(shí)還有很多類似于安全、緩存、監(jiān)控等等附加功能也占據(jù)著很重要的地位。

Servlet 3規(guī)范經(jīng)過(guò)快一年的推廣,已經(jīng)被各大Web Container廠商所接受,Tomcat 6、JBoss 5、Jetty 7都宣稱自己對(duì)Servlet 3作了較好的支持,而在Servlet 3中最廣為關(guān)注的一個(gè)特性就是異步服務(wù)處理Servlet(Async Servlet),這點(diǎn)也是解決我目前面臨問(wèn)題的最好手段。

Servlet 3 與服務(wù)異步處理

Servlet 3主要的新特性分成四部分:內(nèi)嵌式的使用模式、Annotation的支持、Async Servlet的支持和安全提升。內(nèi)嵌式的使用很早就在Jetty中被實(shí)現(xiàn),也成為Jetty的優(yōu)勢(shì)之一,Annotation也只能說(shuō)是錦上添花的部分,而安全暫時(shí)沒(méi)有怎么用到,所以最關(guān)心的還是Async Servlet部分。Async Servlet到底是什么樣的概念,這里就大致描述一下在Servlet 3規(guī)范中對(duì)它的介紹:

  1. 支持 Comet(彗星)。最早期的Http請(qǐng)求就是無(wú)狀態(tài)的請(qǐng)求和響應(yīng),所有的數(shù)據(jù)一次性在請(qǐng)求后返回給客戶端由客戶端渲染。后來(lái)發(fā)展到AJAX,頁(yè)面的請(qǐng)求和渲染由全局變成了局部。而Comet適合事件驅(qū)動(dòng)的Web應(yīng)用和對(duì)交互性和實(shí)時(shí)性要求很強(qiáng)的應(yīng)用,通過(guò)建立客戶端和服務(wù)端的長(zhǎng)連接通道,在一次請(qǐng)求后可以主動(dòng)推送服務(wù)端數(shù)據(jù)的變更情況到客戶端。長(zhǎng)連接建立的策略有兩種:Http Streaming和Http Long Polling。前者客戶端打開(kāi)一個(gè)單一的與服務(wù)器端的 HTTP 持久連接。服務(wù)器通過(guò)此連接把數(shù)據(jù)發(fā)送過(guò)來(lái),客戶端對(duì)它們進(jìn)行增量處理。后者由客戶端向服務(wù)器端發(fā)出請(qǐng)求并打開(kāi)一個(gè)連接。這個(gè)連接只有在收到服務(wù)器端的數(shù)據(jù)之后才會(huì)關(guān)閉。服務(wù)器端發(fā)送完數(shù)據(jù)之后,就立即關(guān)閉連接??蛻舳藙t馬上再打開(kāi)一個(gè)新的連接,等待下一次的數(shù)據(jù)。
  2. 支持Suspending a request。通過(guò)在ServletRequest中增加suspend,resume,complete等,其將Http請(qǐng)求處理的block模式轉(zhuǎn)變成為not block模式,同時(shí)支持對(duì)于狀態(tài)的查詢(suspend,resume,timeout)。
  3. 請(qǐng)求處理過(guò)程中支持事件機(jī)制。響應(yīng)也支持狀態(tài)查詢。

圖 異步服務(wù)請(qǐng)求基本流程

現(xiàn)實(shí)中的異步服務(wù)處理

Tomcat 的異步服務(wù)處理

這里使用的是Tomcat 6.0.14版本。在Tomcat中對(duì)于異步處理描述在Advanced IO中作了說(shuō)明,主要分成兩部分:Comet的支持和異步輸出。

Comet的支持作用分成兩部分:請(qǐng)求讀數(shù)據(jù)的非阻塞,響應(yīng)處理的異步執(zhí)行。前者可以防止在大流量數(shù)據(jù)上傳過(guò)程中,信道空閑等待的資源浪費(fèi),后者用于在處理請(qǐng)求時(shí),依賴于第三方或者本身處理比較耗時(shí)的情況下,懸掛起請(qǐng)求處理線程,提高請(qǐng)求處理能力,完成處理后異步輸出結(jié)果。

Servlet不再是原來(lái)對(duì)于幾個(gè)標(biāo)準(zhǔn)的Http請(qǐng)求類型的方法實(shí)現(xiàn),而是對(duì)于事件響應(yīng)的處理。Comet定義了4個(gè)基礎(chǔ)的事件:

  1. EventType.BEGIN:客戶端建立起連接時(shí)激發(fā)的事件,可以用于資源初始化。
  2. EventType.READ:有數(shù)據(jù)可以被讀入的事件。(熟悉NIO的事件模式應(yīng)該可以了解)
  3. EventType.END:請(qǐng)求處理結(jié)束時(shí)激發(fā)的事件,可以用于資源清理。
  4. EventType.ERROR:當(dāng)請(qǐng)求處理出現(xiàn)問(wèn)題時(shí)激發(fā)的事件。(IO異常,超時(shí)等)

還有一些子事件類型,例如超時(shí)就屬于ERROR的子事件類型,可以在事件處理中更加精確地定位事件類型。

必需的配置:在server.xml中配置如下(紅色部分):

<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" 
connectionTimeout="20000"
redirectPort="8443" />

實(shí)際代碼范例如下:

//CometProcessor接口必需被實(shí)現(xiàn),一旦實(shí)現(xiàn)以后,則該Servlet在配置好以后不會(huì)再調(diào)用service,get,post等方法的實(shí)現(xiàn)。
public class SIPCometTomcatServlet extends HttpServlet implements CometProcessor
{
    @Override
    //事件處理響應(yīng)方法實(shí)現(xiàn)
    public void event(CometEvent event) throws IOException, ServletException
    {
        if (event.getEventType() == CometEvent.EventType.BEGIN)
        {
            //設(shè)置事件超時(shí)時(shí)間
            event.setTimeout(10 * 1000);
            //另起線程處理后臺(tái)工作,異步返回結(jié)果,事件響應(yīng)將不等待后臺(tái)處理直接返回
            new Handler(event.getHttpServletRequest(),event.getHttpServletResponse()).start();
        }
        else if (event.getEventType() == CometEvent.EventType.ERROR)
        {
            //結(jié)束事件,回收request,response資源
            event.close();
        }
        else if (event.getEventType() == CometEvent.EventType.END)
        {
            event.close();
        }
       
    }
   
//另起一個(gè)線程異步處理請(qǐng)求。   
class Handler extends java.lang.Thread
    {
        private HttpServletResponse response;
        private HttpServletRequest request;
       
        public Handler(HttpServletRequest request,HttpServletResponse response)
        {
            this.response = response;
            this.request = request;
        }
       
        @Override
        public void run()
        {
            try
            {
                String id;
                id = request.getParameter("id");
                if (id == null)
                    id = "no id";
               
                Thread.sleep(5000);
                       
                PrintWriter pw = response.getWriter();   
                pw.write(id);
                pw.flush();
               
            } catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
}

使用過(guò)程中的一些總結(jié):

  1. 事件響應(yīng)框架將服務(wù)的請(qǐng)求由完整的一次服務(wù)處理切割成為細(xì)粒度的多事件處理,為請(qǐng)求多階段并行處理提供了框架基礎(chǔ)。
  2. Event對(duì)象在事件處理方法結(jié)束后就被回收了,但是request和response在事件處理完以后還可以繼續(xù)使用,因此可以看出原來(lái)的阻塞式的方式已經(jīng)可以通過(guò)事件的切分成為非阻塞的方式。
  3. 沒(méi)有提供Servlet 3中描述的suspend,resume,complete方法,無(wú)法主動(dòng)控制request的異步處理。上面的代碼可以看出我只使用了Begin方法啟動(dòng)了一個(gè)線程,但是由于無(wú)法主動(dòng)地結(jié)束請(qǐng)求,因此在向客戶端返回?cái)?shù)據(jù)以后還要等到超時(shí)才會(huì)結(jié)束這次會(huì)話。(看了Tomcat的代碼,也想模仿close的動(dòng)作但是由于它使用了protected無(wú)法獲取封裝的request對(duì)象,因此無(wú)法釋放資源)。當(dāng)然也可以通過(guò)客戶端配合,由客戶端主動(dòng)發(fā)起再次的數(shù)據(jù)傳輸激發(fā)READ事件來(lái)結(jié)束會(huì)話。這么做對(duì)客戶端的依賴比較強(qiáng),同時(shí)也增加了客戶端的處理復(fù)雜度。
  4. Tomcat支持異步輸出:在APR或者NIO的模式下,Tomcat支持在系統(tǒng)壓力增大的時(shí)候,支持異步回寫大文件數(shù)據(jù)。

總體上來(lái)說(shuō)實(shí)現(xiàn)了部分對(duì)于Comet的支持,但是沒(méi)有對(duì)異步服務(wù)流程作很好的支持,無(wú)法在開(kāi)發(fā)中使用(簡(jiǎn)單順暢的使用)。

JBoss的異步服務(wù)處理

JBoss 4.2.3版本配置和使用與Tomcat 6類似,沒(méi)有什么差異。

JBoss 5剛剛發(fā)布了RC版本,對(duì)于異步服務(wù)處理作了很大的改動(dòng),與Tomcat配置很不同,這里具體的說(shuō)一下JBoss5中的異步服務(wù)使用。

JBoss 5已經(jīng)將Tomcat中的Http11NioProtocol給刪除了,取而代之的是JBoss自己servlet包內(nèi)增加的一個(gè)HttpEventServlet接口,這個(gè)接口和Tomcat的CometProcessor類似。

首先,必須配置JBoss內(nèi)置的Web容器為APR模式,也就是配置jbossweb.sar下面的server.xml中Connector 如下:

<Connector protocol="org.apache.coyote.http11.Http11AprProtocol" port="8080" address="${jboss.bind.address}"
               connectionTimeout="2000" redirectPort="8443" />

其次異步服務(wù)處理的Servlet必須實(shí)現(xiàn)HttpEventServlet接口,接口只有一個(gè)方法,就是事件處理方法:public void event(HttpEvent event)。事件定義與Tomcat稍有不同,在BEGIN,ERROR,READ,END基礎(chǔ)上增加了TIMEOUT,EOF,EVENT,WRITE四個(gè)事件,同時(shí)去掉了SubType。

  1. TIMEOUT其實(shí)是從原來(lái)的Error的SubType分離出來(lái)的,這個(gè)方法是在最后一次處理事件到當(dāng)前時(shí)間超過(guò)設(shè)定的超時(shí)時(shí)間而被激發(fā)的,同時(shí)TIMEOUT被激發(fā)并不會(huì)關(guān)閉請(qǐng)求處理流程,必須顯示調(diào)用事件的close方法才會(huì)結(jié)束會(huì)話。
  2. EOF事件將會(huì)在客戶端主動(dòng)斷連的情況下被觸發(fā),就好比IE窗口在請(qǐng)求過(guò)程中被關(guān)閉就會(huì)被觸發(fā)。
  3. EVENT事件在事件對(duì)象被調(diào)用resume的時(shí)候被激發(fā),按照原意應(yīng)該最好可以附帶上一些自定義信息來(lái)做一些工作,但是我自己使用過(guò)程中還沒(méi)有發(fā)現(xiàn)有什么好的辦法可以在事件中附帶信息到事件處理中。
  4. WRITE方法在調(diào)用isWriteReady方法時(shí)被激發(fā),可以在網(wǎng)絡(luò)出現(xiàn)問(wèn)題或者繁忙的時(shí)候異步等待輸出。

再則,JBoss的事件對(duì)象還支持幾個(gè)方法來(lái)實(shí)現(xiàn)異步處理以及Comet機(jī)制,方法如下:

  1. close方法:表示一次請(qǐng)求處理的結(jié)束,會(huì)告知客戶端沒(méi)有數(shù)據(jù)返回了,同時(shí)也會(huì)激發(fā)END事件。
  2. setTimeout方法:設(shè)置連接超時(shí)時(shí)間(單位毫秒),計(jì)算超時(shí)是從最近的事件處理時(shí)間開(kāi)始記錄的,如果發(fā)生超時(shí),則會(huì)激發(fā)TIMEOUT事件。
  3. isReadReady方法:如果連接有數(shù)據(jù)可以讀取則返回true,如果這個(gè)方法返回false,servlet還試圖去讀去數(shù)據(jù),則會(huì)阻塞。
  4. isWriteReady方法:如果返回true,則連接可以無(wú)阻塞的寫出數(shù)據(jù),如果返回false,servlet必須停止寫數(shù)據(jù),如果強(qiáng)制寫出,則可能會(huì)發(fā)生IO錯(cuò)誤或者會(huì)采用異步輸出。當(dāng)客戶端的輸出通道可用以后,則會(huì)激發(fā)write事件。
  5. suspend方法:suspend連接處理線程直到timeout發(fā)生或者resume被調(diào)用,實(shí)際上意味著servlet在suspend以后不再收到READ事件,READ事件將會(huì)在后臺(tái)被不斷的激發(fā),除非被suspend.
  6. resume方法:會(huì)激發(fā)event事件,可以利用這個(gè)方法來(lái)結(jié)束異步處理。同時(shí)也可以激活因?yàn)閟uspend停止的read事件,同時(shí)也可以在resume以后再調(diào)用suspend方法。注意,這里未必是要求必須先suspend以后再resume。
  7. event,request,response在事件響應(yīng)過(guò)程中都可以被使用,但是線程不安全,同時(shí)在調(diào)用了close以后,request,response資源會(huì)被釋放,可以通過(guò)對(duì)event對(duì)象做同步來(lái)保證線程安全的問(wèn)題。當(dāng)READ事件和END事件都發(fā)生的時(shí)候,首先會(huì)完成READ事件,然后再去完成END。

具體的實(shí)現(xiàn)代碼如下:

public class SIPCometJBossServlet extends HttpServlet implements HttpEventServlet
{
    @Override
    public void event(HttpEvent event) throws IOException, ServletException
    {
        switch (event.getType())
        {
            //will be called at the beginning of the processing of the connection
            case BEGIN:
            {
                event.setTimeout(100 * 1000);//設(shè)置超時(shí)時(shí)間
                //event.suspend();//resume之前不必要一定使用suspend
                new Handler(event).start();
                break;
            }
           
            //Error will be called by the container in the case
            //where an IO exception or a similar unrecoverable error occurs
            case ERROR:
            {
                event.close();
                break;
            }
           
            //End may be called to end the processing of the request
            case END:
            {
                //event.close();//可以寫也可以不寫,因?yàn)檫M(jìn)入這個(gè)方法也就是調(diào)用了close方法,起碼暫時(shí)還不知道有其他什么入口
                break;
            }
           
            //This indicates that input data is available,
            //and that at least one read call can be made without blocking
            case READ:
            {
                break;
            }
           
            //The connection timed out according to the timeout value which has been set
            //,but the connection will not be closed unless the servlet uses the close method of the event
            case TIMEOUT:
            {
                event.close();//如果不主動(dòng)關(guān)閉,Timeout方法會(huì)被循環(huán)調(diào)用,會(huì)話不會(huì)結(jié)束
                break;
            }
           
            //The end of file of the input has been reached, and no further data is available
            case EOF:
            {
                event.close();
                break;
            }
           
            //Event will be called by the container after the resume() method is called,
            //during which any operation can be performed, including closing the connection using the close() method.
            case EVENT:
            {
                event.close();//作為resume方法調(diào)用后主動(dòng)釋放連接資源的一種手段
                break;
            }
           
            //Write is sent if the servlet is using the isWriteReady method
            case WRITE:
            {
                break;
            }
           
        }
    }
    class Handler extends java.lang.Thread
    {
        private HttpEvent event;//event的生命周期已經(jīng)不限制于事件處理方法,因此隨時(shí)可以關(guān)閉請(qǐng)求處理
        private HttpServletResponse response;
        private HttpServletRequest request;
       
        public Handler(HttpEvent event)
        {
            this.event = event;
            this.response = event.getHttpServletResponse();
            this.request = event.getHttpServletRequest();
        }
       
        @Override
        public void run()
        {
            try
            {
                String id;
                id = request.getParameter("id");
               
                if (id == null)
                    id = "no id";
               
                Thread.sleep(5000);
//危險(xiǎn)?。?!其實(shí)event,response,request都是線程不安全的,因此此時(shí)可能response已經(jīng)被釋放,需要同步住event的對(duì)象來(lái)操作,效率可能會(huì)降低
                PrintWriter pw = response.getWriter();
                pw.write(id);
                pw.flush();
                event.resume();//發(fā)送結(jié)束調(diào)用resume方法,進(jìn)入event方法,結(jié)束請(qǐng)求處理
               
            } catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
}

使用總結(jié):

  1. 對(duì)于Servlet描述的異步服務(wù)處理有了較好的支持。
  2. 事件方法比較豐富,但是對(duì)于可定義事件支持不夠完善。
  3. 對(duì)象并發(fā)控制需要開(kāi)發(fā)者自己設(shè)計(jì),權(quán)衡多線程處理的高效以及資源爭(zhēng)奪的消耗。

下面對(duì)異步服務(wù)處理Servlet和普通Servlet做了一下簡(jiǎn)單的性能測(cè)試。

首先我原本想用ab來(lái)做一下簡(jiǎn)單的壓力測(cè)試即可,但是ab好像對(duì)于apr模式下的測(cè)試支持的不好,一壓就報(bào)錯(cuò)(apr_poll: The timeout specified has expired (70007)),也可能是自己不會(huì)用吧,因此就自己寫了一段測(cè)試代碼來(lái)做測(cè)試。

測(cè)試場(chǎng)景如下:

兩類Servlet都可以設(shè)置處理時(shí)Hold的時(shí)間,來(lái)達(dá)到消耗連接數(shù)的目的。測(cè)試客戶端可以設(shè)置并發(fā)多少用戶,每個(gè)用戶發(fā)起多少次請(qǐng)求。下表就是測(cè)試的結(jié)果:

這里設(shè)置的是Servlet都hold1秒鐘,APR啟動(dòng)時(shí)配置的最大連接數(shù)為默認(rèn)的200個(gè)。

客戶端設(shè)置 普通Servlet總耗時(shí)(ms) 異步Servlet總耗時(shí)(ms) 普通Servlet單個(gè)線程耗時(shí)(ms) 異步Servlet單個(gè)線程耗時(shí)(ms)
100并發(fā)線程,每個(gè)線程執(zhí)行1次請(qǐng)求 263866 274430 2638 2744
300并發(fā)線程,每個(gè)線程執(zhí)行1次請(qǐng)求 550718 617082 1835 2056
100并發(fā)線程,每個(gè)線程執(zhí)行10次請(qǐng)求 1087747 1207920 10877 12079
300并發(fā)線程,每個(gè)線程執(zhí)行10次請(qǐng)求 retrying request,connect reject 5193644 retrying request,connect reject 17312

從上表可以看出,就純粹從處理效率來(lái)說(shuō),采用事件處理方式在線程切換過(guò)程中存在著一定的損失,但是就我們使用異步請(qǐng)求處理的本意來(lái)看,對(duì)于在高并發(fā)下對(duì)后端依賴無(wú)法避免的性能損耗情況下,異步請(qǐng)求解決了連接耗盡的問(wèn)題。

最后再來(lái)看我在測(cè)試過(guò)程中用JProfiler來(lái)截取的一些線程創(chuàng)建和使用狀況:

上圖是最初的線程創(chuàng)建情況,還沒(méi)有任何請(qǐng)求被發(fā)送到服務(wù)端,因此線程池也沒(méi)有開(kāi)任何一個(gè)連接。

這是普通的Servlet在壓力測(cè)試下的線程狀況,線程就開(kāi)到了200最大值,圖中由于程序來(lái)Hold請(qǐng)求處理線程出現(xiàn)了紅色阻塞和黃色等待,同時(shí)客戶端已經(jīng)開(kāi)始出現(xiàn)拒絕連接的錯(cuò)誤。下圖就是錯(cuò)誤的截圖:

上圖是異步服務(wù)處理Servlet在壓力測(cè)試開(kāi)始的情況,可以發(fā)現(xiàn)它的http線程還是200,但是其他事件處理線程在不斷增長(zhǎng)。下圖已經(jīng)增長(zhǎng)到了3000多個(gè)線程。(這里需要注意的就是這種異步處理資源申請(qǐng)沒(méi)有設(shè)置上限,因此對(duì)于資源消耗來(lái)說(shuō)也是比較大的,同時(shí)要防范攻擊性請(qǐng)求造成服務(wù)端垮掉)。

結(jié)語(yǔ)

多線程、分布式計(jì)算、Erlang等這些編程方式、框架設(shè)計(jì)、語(yǔ)言其實(shí)都在實(shí)現(xiàn)這一個(gè)理論,那就是分而治之,多線程是站在單應(yīng)用的角度去考慮解決方案,分布式計(jì)算是在多機(jī)協(xié)作考慮解決方案,Erlang在單機(jī)多處理器的角度去考慮解決方案。但彼此的理念都是一樣,將能夠分割的不相關(guān)聯(lián)的獨(dú)立任務(wù)并行處理,最終實(shí)現(xiàn)最優(yōu)化的處理效果。

對(duì)于服務(wù)集成平臺(tái)是否采用這種技術(shù),我自己還沒(méi)有最終的決定,首先就如上面的測(cè)試結(jié)果來(lái)看,有得還是有失的,其次這種并發(fā)異步處理帶來(lái)的多線程維護(hù)控制復(fù)雜度,也需要考慮到成本中。Jetty的開(kāi)發(fā)者對(duì)于是否將異步服務(wù)處理Servlet來(lái)交由開(kāi)發(fā)者控制而不是容器本身來(lái)控制表示出了反對(duì)意見(jiàn),的確,這樣復(fù)雜的控制交給開(kāi)發(fā)者來(lái)處理會(huì)增加開(kāi)發(fā)者的學(xué)習(xí)成本以及維護(hù)成本。


作者介紹:岑文初,就職于阿里軟件公司研發(fā)中心平臺(tái)一部,任架構(gòu)師。當(dāng)前主要工作涉及阿里軟件開(kāi)發(fā)平臺(tái)服務(wù)框架(ASF)設(shè)計(jì)與實(shí)現(xiàn),服務(wù)集成平臺(tái)(SIP)設(shè)計(jì)與實(shí)現(xiàn)。沒(méi)有什么擅長(zhǎng)或者精通,工作到現(xiàn)在唯一提升的就是學(xué)習(xí)能力和速度。個(gè)人Blog為:http://blog.csdn.net/cenwenchu79。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多