轉(zhuǎn)自:http://blog.csdn.net/shine0181/article/details/7799754/
HTTP實現(xiàn)長連接
HTTP是無狀態(tài)的也就是說,瀏覽器和服務器每進行一次HTTP操作,就建立一次連接,但任務結(jié)束就中斷連接泼掠。如果客戶端瀏覽器訪問的某個HTML或其他類型的Web頁中包含有其他的Web資源髓堪,如JavaScript文件、圖像文件熙尉、CSS文件等药有;當瀏覽器每遇到這樣一個Web資源毅戈,就會建立一個HTTP會話
HTTP1.1和HTTP1.0相比較而言,最大的區(qū)別就是增加了持久連接支持(貌似最新的 http1.0 可以顯示的指定 keep-alive),但還是無狀態(tài)的愤惰,或者說是不可以信任的苇经。
如果瀏覽器或者服務器在其頭信息加入了這行代碼
Connection:keep-alive
TCP連接在發(fā)送后將仍然保持打開狀態(tài),于是宦言,瀏覽器可以繼續(xù)通過相同的連接發(fā)送請求扇单。保持連接節(jié)省了為每個請求建立新連接所需的時間,還節(jié)約了帶寬奠旺。
實現(xiàn)長連接要客戶端和服務端都支持長連接蜘澜。
如果web服務器端看到這里的值為“Keep-Alive”施流,或者看到請求使用的是HTTP 1.1(HTTP 1.1****默認進行持久連接),它就可以利用持久連接的優(yōu)點鄙信,當頁面包含多個元素時(例如Applet瞪醋,圖片),顯著地減少下載所需要的時間装诡。要實現(xiàn)這一點银受,web服務器需要在返回給客戶端HTTP頭信息中發(fā)送一個Content-Length(返回信息正文的長度)頭,最簡單的實現(xiàn)方法是:先把內(nèi)容寫入ByteArrayOutputStream鸦采,然后在正式寫出內(nèi)容之前計算它的大小
無論客戶端瀏覽器 (Internet Explorer) 還是 Web 服務器具有較低的 KeepAlive 值蚓土,它都將是限制因素。例如赖淤,如果客戶端的超時值是兩分鐘,而 Web 服務器的超時值是一分鐘谅河,則最大超時值是一分鐘咱旱。客戶端或服務器都可以是限制因素
在header中加入 --Connection:keep-alive在HTTp協(xié)議請求和響應中加入這條就能維持長連接绷耍。再封裝HTTP消息數(shù)據(jù)體的消息應用就顯的非常簡單易用
Http Keep-Alive seems to be massively misunderstood. Here's a short description of how it works, under both1.0 and 1.1
HTTP/1.0
Under HTTP 1.0, there is no official specification for how keepalive operates. It was, in essence, tacked on to an existing protocol. If the browser supportskeep-alive, it adds an additional header to the request:
Connection:Keep-Alive
Then, when the server receives this request and generates a response, it also adds a header to the response:
Connection:Keep-Alive
Following this, the connection is NOT dropped, but is instead kept open. When the client sends another request, it uses the sameconnection. This will continue until either the client or the server decides that the conversation is over, and one of them drops theconnection.
HTTP/1.1
Under HTTP 1.1, the official keepalive method is different.All connections are kept alive, unless stated otherwise with the following header:
Connection: close
The Connection:Keep-Alive header no longer has any meaning because of this.
Additionally, an optional Keep-Alive: header is described, but is so underspecified as to be meaningless. Avoid it.
Not reliable
HTTP is a stateless protocol - this means that every request is independent of every other.Keep alive doesn’t change that. Additionally, there is no guarantee that the client or the server will keep theconnection open. Even in 1.1, all that is promised is that you will probably get a notice that theconnection is being closed. So keepalive is something you should not write your application to rely upon.
KeepAlive and POST
The HTTP 1.1 spec states that following the body of a POST, there are to be no additional characters. It also states that "certain" browsers may not follow this spec, putting a CRLF after the body of the POST. Mmm-hmm. As near as I can tell, most browsers follow a POSTed body with a CRLF. There are two ways of dealing with this: Disallow keepalive in the context of a POST request, or ignore CRLF on a line by itself. Most servers deal with this in the latter way, but there's no way to know how a server will handle it without testing.
Java應用
client用apache的commons-httpclient來執(zhí)行method 吐限。用 method.setRequestHeader("Connection" , "Keep-Alive" or "close") 來控制是否保持連接。
常用的apache褂始、resin诸典、tomcat等都有相關(guān)的配置是否支持keep-alive。
tomcat中可以設置:maxKeepAliveRequests
The maximum number of HTTP requests which can be pipelined until the connection is closed by the server. Setting this attribute to 1 will disableHTTP/1.0 keep-alive, as well as HTTP/1.1 keep-alive and pipelining. Setting this to -1 will allow an unlimited amount of pipelined or keep-aliveHTTP requests. If not specified, this attribute is set to 100.
解釋1
所謂長連接指建立SOCKET連接后不管是否使用都保持連接崎苗,但安全性較差狐粱, 所謂短連接指建立SOCKET連接后發(fā)送后接收完數(shù)據(jù)后馬上斷開連接,一般銀行都使用短連接解釋2
長連接就是指在基于tcp的通訊中胆数,一直保持連接肌蜻,不管當前是否發(fā)送或者接收數(shù)據(jù)。 而短連接就是只有在有數(shù)據(jù)傳輸?shù)臅r候才進行連接必尼,客戶-服務器通信/傳輸數(shù)據(jù)完畢就關(guān)閉連接蒋搜。解釋3
長連接和短連接這個概念好像只有移動的CMPP協(xié)議中提到了,其他的地方?jīng)]有看到過判莉。 通信方式 各網(wǎng)元之間共有兩種連接方式:長連接和短連接豆挽。所謂長連接,指在一個TCP連接上可以連續(xù)發(fā)送多個數(shù)據(jù)包券盅,在TCP連接保持期間帮哈,如果沒有數(shù)據(jù)包發(fā)送,需要雙方發(fā)檢測包以維持此連接渗饮。短連接是指通信雙方有數(shù)據(jù)交互時但汞,就建立一個TCP連接宿刮,數(shù)據(jù)發(fā)送完成后,則斷開此TCP連接私蕾,即每次TCP連接只完成一對 CMPP消息的發(fā)送僵缺。 現(xiàn)階段,要求ISMG之間必須采用長連接的通信方式踩叭,建議SP與ISMG之間采用長連接的通信方式磕潮。解釋4
短連接:比如http的,只是連接容贝、請求自脯、關(guān)閉,過程時間較短,服務器若是一段時間內(nèi)沒有收到請求即可關(guān)閉連接斤富。 長連接:有些服務需要長時間連接到服務器膏潮,比如CMPP,一般需要自己做在線維持满力。
最近在看“服務器推送技術(shù)”焕参,在B/S結(jié)構(gòu)中,通過某種magic使得客戶端不需要通過輪詢即可以得到服務端的最新信息(比如股票價格)油额,這樣可以節(jié)省大量的帶寬叠纷。
傳統(tǒng)的輪詢技術(shù)對服務器的壓力很大,并且造成帶寬的極大浪費潦嘶。如果改用ajax輪詢涩嚣,可以降低帶寬的負荷(因為服務器返回的不是完整頁面),但是對服務器的壓力并不會有明顯的減少掂僵。
而推技術(shù)(push)可以改善這種情況航厚。但因為HTTP連接的特性(短暫,必須由客戶端發(fā)起)看峻,使得推技術(shù)的實現(xiàn)比較困難阶淘,常見的做法是通過延長http連接的壽命,來實現(xiàn)push互妓。
接下來自然該討論如何延長http連接的壽命溪窒,最簡單的自然是死循環(huán)法:
public void doGet(Request req, Response res) {
PrintWriter out = res.getWriter();
……
正常輸出頁面
……
out.flush();
while (true) {
out.print("輸出更新的內(nèi)容");
out.flush();
Thread.sleep(3000);
}
}
如果使用觀察者模式則可以進一步提高性能。
但是這種做法的缺點在于客戶端請求了這個servlet后冯勉,web服務器會開啟一個線程執(zhí)行servlet的代碼澈蚌,而servlet由遲遲不肯結(jié)束,造成該線程也無法被釋放灼狰。于是乎宛瞄,一個客戶端一個線程,當客戶端數(shù)量增加時交胚,服務器依然會承受很大的負擔份汗。
要從根本上改變這個現(xiàn)象比較復雜盈电,目前的趨勢是從web服務器內(nèi)部入手,用nio(JDK 1.4提出的java.nio包)改寫request/response的實現(xiàn)杯活,再利用線程池增強服務器的資源利用率匆帚,從而解決這個問題,目前支持這一非J2EE官方技術(shù)的服務器有Glassfish和Jetty(后者只是聽說旁钧,沒有用過)吸重。
目前也有一些框架/工具可以幫助你實現(xiàn)推功能,比如pushlets歪今。不過沒有深入研究嚎幸。