看過Servlet 3.0的規(guī)范和API后,可以看出來,所謂異步的HTTP,其實(shí)異步的不是HTTP,而是服務(wù)器端異步地處理HTTP請(qǐng)求,而HTTP客戶端,仍舊是同步的等待服務(wù)端的處理結(jié)果。一般servlet容器會(huì)分配一個(gè)線程用來處理一個(gè)來自客戶端的HTTP請(qǐng)求,在這個(gè)線程發(fā)送回HTTP響應(yīng)之前,這個(gè)線程只屬于這個(gè)HTTP請(qǐng)求不能離開處理其它請(qǐng)求。采用Servlet3.0之后,當(dāng)前的線程可以開啟異步處理,開啟異步處理的時(shí)候會(huì)得到一個(gè)異步處理上下文對(duì)象,之后當(dāng)前的線程就可以不生成HTTP響應(yīng)而直接退出去處理其它的HTTP請(qǐng)求,其它線程可以在之后通過異步處理上下文來生成和發(fā)送那個(gè)HTTP響應(yīng)??梢娝^的異步HTTP其實(shí)只是一種可以讓當(dāng)前的處理線程在不生成響應(yīng)前就離開,而在之后再處理這個(gè)HTTP請(qǐng)求的機(jī)制。
從客戶端看來,不論是哪種方式,瀏覽器都在發(fā)送完HTTP請(qǐng)求之后,都必須同步的等待服務(wù)器端的響應(yīng)。假如瀏覽器發(fā)送完HTTP請(qǐng)求之后,可以在得到服務(wù)器處理結(jié)果之前轉(zhuǎn)而處理其它事情,而在未來的某個(gè)時(shí)刻,當(dāng)服務(wù)器處理完請(qǐng)求后,不需要客戶端再發(fā)送請(qǐng)求,就可以發(fā)響應(yīng)發(fā)回給瀏覽器,也許那才是真的異步HTTP了。但是這是違反HTTP的有請(qǐng)求才響應(yīng),無請(qǐng)求不響應(yīng)的基本原則的。 HTTP長(zhǎng)連接可以讓客戶端和服務(wù)器在同一個(gè)TCP連接中做多次請(qǐng)求響應(yīng),但是并不能改變客戶端和服務(wù)器之間的同步請(qǐng)求響應(yīng)模式。
盡管Servlet3.0的異步功能不能改變HTTP的協(xié)議,在本質(zhì)上讓瀏覽器和服務(wù)器之間異步的交互,但是這一功能還是有非常大的意義的。假設(shè)接受請(qǐng)求和發(fā)送響應(yīng)的時(shí)間分別為Req和Resp,每個(gè)請(qǐng)求都要執(zhí)行一個(gè)耗時(shí)P的操作O,并且O操作會(huì)讓調(diào)用者阻塞,當(dāng)在P時(shí)間內(nèi)有n個(gè)請(qǐng)求發(fā)送過來時(shí),用傳統(tǒng)的處理方式,由于P時(shí)間內(nèi)每個(gè)線程都不能處理完,servlet容器要分配F(n) = n個(gè)線程處理請(qǐng)求,如下圖所示:
而用Servlet3.0的異步處理時(shí),處理線程可以開啟單一線程去做那個(gè)耗時(shí)P的操作,而把當(dāng)前請(qǐng)求的異步處理上下文放入一個(gè)等待隊(duì)列中,自己則接著處理其它的請(qǐng)求,假設(shè)這個(gè)開啟異步,加入異步處理上下文的操作需要時(shí)間A,那么需要開啟F(n) = n*(A+Req+Resp)/(P + Req + Resp) + 1個(gè)線程就可以在P時(shí)間內(nèi)處理完所有請(qǐng)求。如下圖所示:
假如執(zhí)行操作O可以不阻塞,耗時(shí)C就返回, 那么n客戶端每獲得一次資源,需要發(fā)送f(n) = n*P / (Req + C + Resp) 次請(qǐng)求,而用異步處理的時(shí)候,只需要n次請(qǐng)求??梢姰?dāng)A足夠小于P時(shí),O阻塞訪問時(shí),異步可以用更少的線程處理更多的請(qǐng)求;O非阻塞訪問時(shí),異步可以減少請(qǐng)求次數(shù)。
以web QQ為例來看看。用戶發(fā)送消息時(shí),假設(shè)服務(wù)器分發(fā)消息耗時(shí)P遠(yuǎn)遠(yuǎn)大于開啟異步和把消息放到待分發(fā)隊(duì)列的耗時(shí)A,那么采用異步處理發(fā)送消息,可以用更少的線程處理更多的發(fā)送消息請(qǐng)求。用戶接受消息,假設(shè)平均P時(shí)間內(nèi)用戶才有新消息到達(dá),而檢查一次新消息的耗時(shí)遠(yuǎn)小于P,那么采用異步則可以減少很多客戶端請(qǐng)求。
沒有相關(guān)文章








“每個(gè)請(qǐng)求都要執(zhí)行一個(gè)耗時(shí)P的操作O,并且O操作會(huì)讓調(diào)用者阻塞,” 很抱歉我對(duì)這句話沒有完全理解,什么是P?什么是O?
“Servlet3.0的異步處理時(shí),處理線程可以開啟單一線程去做那個(gè)耗時(shí)P的操作” 對(duì)這個(gè)句話也不理解? 處理什么線程?哪來的線程需要被處理? 我的理解能力不夠好,請(qǐng)多多見諒,呵呵。
說真的,我又看了2遍,作為一個(gè)初學(xué)者的角度 還真的不能完全聽明白您的上述道白,sorry…..
PS:
1.如果說理論、底層的東西就盡量去白話,多打比方,少點(diǎn)數(shù)學(xué)公式。
2.太多字,不如一張圖,一圖抵千字。
這兩天比較忙,匆忙寫的,有些地方是不太好說清楚。確實(shí)是上圖方便,改天加上。
類似完成端口?
不太明白你所謂的端口是指什么
O是指一個(gè)耗時(shí)比較長(zhǎng)的操作,比如訪問數(shù)據(jù)庫(kù)等。P是指完成O這個(gè)操作需要使用的時(shí)間。
處理線程指的是當(dāng)前的處理http請(qǐng)求的線程,這是個(gè)定語(yǔ)。
圖不太好畫,不過我還是畫了個(gè)圖上去了。數(shù)學(xué)公式也不是精確地表達(dá),但是從一定程度上可以看出什么各種量之間的關(guān)系,我覺得更易于理解。如果只說使用了異步,可以處理更多并發(fā)的客戶端請(qǐng)求,很多人可能不清楚為什么,以及在多大程度上處理更多的請(qǐng)求,有了公式就容易理解一點(diǎn)。
大部分贊同,雖然我沒有看過servlet3.0規(guī)范。但我想圖上那個(gè)異步執(zhí)行只有一個(gè)線程的方式應(yīng)該是你的例子,而不是servlete容器真正的模型。否則所有的業(yè)務(wù)都交由一個(gè)線程處理,無法利用多CPU或者多核的能力。應(yīng)該是交由一個(gè)線程池來處理才對(duì)。
這種模型的一個(gè)優(yōu)點(diǎn)是可以提高接受請(qǐng)求的數(shù)量。因?yàn)橛幸恍┚€程專門負(fù)責(zé)接受請(qǐng)求,只負(fù)責(zé)接受請(qǐng)求。
謝謝你的回復(fù)。你說的是很有道理的,如果要處理的操作,可以并發(fā),瓶頸在CPU的話,是可以像你說的那樣的。如果要處理的操作不可以并發(fā),或者瓶頸并不在CPU上,用多個(gè)線程來處理的意義也不大,因?yàn)檫@多個(gè)線程還是會(huì)阻塞住。