長輪詢適合瀏覽器的Chat聊天、股票行情顯示、股票狀態(tài)更新、體育直播的結(jié)果顯示等。當(dāng)然,不是所有的例子都是對延遲很敏感的,但它們的需求都比較相似。
在標(biāo)準(zhǔn)的HTTP請求響應(yīng)語義中,瀏覽器發(fā)起請求,服務(wù)器發(fā)送一個響應(yīng),這意味著在瀏覽器發(fā)起新請求前,服務(wù)器不能發(fā)送新信息給客戶端瀏覽器。有幾種解決方法,包括:傳統(tǒng)的輪詢、長輪詢、HTTP流、WebSocket協(xié)議等。
瀏覽器保持發(fā)送請求,檢查服務(wù)器是否有新信息返回,服務(wù)器對于每次請求均應(yīng)立即響應(yīng)。這適合的場景下,輪詢可以設(shè)定為合理的時間間隔。例如,郵件客戶端可以每隔10分鐘檢查服務(wù)器是否有新郵件。傳統(tǒng)的輪詢的優(yōu)點(diǎn)是簡單且工作可靠。然而,其缺點(diǎn)是效率不高。如果需要盡快獲得新信息,那么輪詢頻率就必須非常高。
瀏覽器不斷發(fā)送請求,但是服務(wù)器不予以響應(yīng),一直到服務(wù)器有了新信息才響應(yīng)客戶端。從客戶端的角度看它和傳統(tǒng)的輪詢相同。但從服務(wù)器端的角度來看它與傳統(tǒng)的輪詢相比,減少了服務(wù)器端的開銷。
那么響應(yīng)應(yīng)該保持Open多久呢?瀏覽器通常對此時間的設(shè)置是5分鐘,而網(wǎng)絡(luò)中介(比如代理)對此時間設(shè)置的更短。因此,即使服務(wù)器端沒有新消息,客戶端也應(yīng)該定期發(fā)起一個新長輪詢請求。IEFT文件建議這個時間間隔在30秒~120秒之間,而實(shí)際使用取決于你的網(wǎng)絡(luò)情況。
IEFT文件: http://tools.ietf.org/html/rfc6202
長輪詢可以極大地減少需要低延遲的接收信息更新請求的數(shù)量,特別是新信息在無規(guī)律的時間間隔變得可用時。但是,如果信息更新的越頻繁,那么整個方案就越像傳統(tǒng)的輪詢。
瀏覽器向服務(wù)器發(fā)出請求,服務(wù)器要發(fā)送信息時就會響應(yīng)。但是它與長輪詢不同,服務(wù)器需保持響應(yīng)是Open的,有更新時就會響應(yīng)客戶端。該方法去除了輪詢的需要,而且偏離了典型的HTTP請求/響應(yīng)的語義。例如,客戶端和服務(wù)器需要協(xié)商如何解釋響應(yīng)流,這樣客戶端會知道哪一個更新信息結(jié)束了,哪一個更新信息開始了。但是,網(wǎng)絡(luò)中介可以緩存響應(yīng)流,阻撓此方法的意圖。這就是為什么長輪詢更為常用。
瀏覽器發(fā)送一個HTTP請求到服務(wù)器,請求切換到WebSocket協(xié)議,服務(wù)器響應(yīng),確認(rèn)升級協(xié)議到WebSocket。此后,瀏覽器和服務(wù)器可以在TCP套接字上雙向發(fā)送數(shù)據(jù)幀。
WebSocket協(xié)議被設(shè)計用于取代需要輪詢,特別是適用于需要在服務(wù)器和瀏覽器之間頻繁交換數(shù)據(jù)的場景。在HTTP協(xié)議上完成初始握手,以確保WebSocket請求可以穿透防火墻。
WebSockets雙向交換的數(shù)據(jù)有兩種類型,文本信息或二進(jìn)制信息。這使得它與RESTful HTTP方法有顯著不同。事實(shí)上,還有一些其它協(xié)議,比如XMPP,AMQP,STOMP等,目前仍在廣泛使用。
WebSocket協(xié)議已經(jīng)被IETF組織進(jìn)行了標(biāo)準(zhǔn)化,而WebSocket API規(guī)范也由W3C標(biāo)準(zhǔn)完成了制訂。在Java領(lǐng)域也制訂了JSR-356規(guī)范以支持WebSocket協(xié)議。像Jetty、Tomcat這樣的Servlet容器也實(shí)現(xiàn)了對WebSocket協(xié)議的支持。
HTTP Persistent Connection,即HTTP長連接,也叫HTTP Keep-alive或HTTP Connection Reuse。其思想是使用單個的TCP連接來發(fā)送和接收多個HTTP請求/響應(yīng),而不是為每個請求/響應(yīng)都建立一個新連接。新發(fā)布的HTTP /2協(xié)議就使用了這種思想,并進(jìn)一步允許在單個連接上多路復(fù)用多個并發(fā)的請求/響應(yīng)。
而早期的長連接技術(shù)只是要求在客戶端與服務(wù)器之間創(chuàng)建和保持穩(wěn)定可靠的連接。早期由于瀏覽器技術(shù)發(fā)展較緩慢,沒有為這種機(jī)制的實(shí)現(xiàn)提供很好的支持。早期通常的做法是在頁面里嵌入一個隱蔵iframe,將這個隱蔵iframe的src屬性設(shè)為對一個長連接的請求或是采用xhr請求,服務(wù)器端就能源源不斷地往客戶端輸入數(shù)據(jù)。
在這種技術(shù)中,服務(wù)器端利用了HTTP長連接的優(yōu)點(diǎn),使得響應(yīng)總是Open的,即服務(wù)器不會終止響應(yīng),有效地讓瀏覽器可以在初始頁面加載后繼續(xù)加載其它內(nèi)容。隨后服務(wù)器端可以周期性的發(fā)送JavaScript代碼片段來更新頁面的內(nèi)容,從而達(dá)到推動能力。通過使用這種技術(shù),客戶端不需要Java Applet或其它插件才能保持與服務(wù)器的連接Open;客戶端會對服務(wù)器推送的新事件自動通知。其缺點(diǎn)是服務(wù)器端缺少對瀏覽器端的超時控制,如果瀏覽器發(fā)生超時,必須使用頁面刷新。
Pushlets的官方站點(diǎn): http://www.pushlets.com/
Pushlet從2000年發(fā)展到2010年,逐漸淡出市場。
Comet是一個Web應(yīng)用模型,它使用一個HTTP長連接,允許服務(wù)器推送數(shù)據(jù)到瀏覽器,無需瀏覽器顯式的發(fā)起請求。Comet技術(shù)是這種技術(shù)方式的統(tǒng)稱,實(shí)際上有多種具體的實(shí)現(xiàn)技術(shù),下面以具體的時間軸介紹Comet技術(shù)有哪些。
1)早期的java Applet
2)2000年興起的Pushlets框架
3)Hidden iframe
4)XMLHttpRequest
5)XMLHttpRequest的長輪詢
6)腳本標(biāo)簽長輪詢