最近工作中遇到了一個(gè)場(chǎng)景,商家需要在商家后面實(shí)時(shí)了解是否有新訂單,在某些情況下有幾種。(威廉莎士比亞,溫斯頓,工作)這個(gè)要求類似于日常生活中使用QQ或微信時(shí)的新信息通知,只要有新信息,就需要通知。商家基本在PC上使用,各種瀏覽器都有:如IE系列(7.0、8.0、9.0或更高版本)、CHOLE內(nèi)核、Firefox等。功能所屬的部署位于Tomcat 6.0中。如果有技術(shù)要求,可以部署到Tomcat 7.0中。
我們先做技術(shù)調(diào)查,這種瀏覽器與服務(wù)器實(shí)時(shí)通信的方式有哪些。
AJAX輪詢這是我們最自然想到的。 采用常規(guī)AJAX輪詢的方式,每10s或者30s輪詢一次,既可以判斷出有有多少個(gè)新訂單進(jìn)入,且這種時(shí)間間隔對(duì)于消息提醒也是可以接受的。這種技術(shù)方式實(shí)現(xiàn)起來(lái)非常簡(jiǎn)單,目前的機(jī)器都是可以機(jī)器的,前端瀏覽器也都支持。
但是這種方式會(huì)有非常嚴(yán)重的問(wèn)題,就是需要不斷的向服務(wù)器發(fā)送消息詢問(wèn),如果有1w個(gè)商家打開(kāi)了瀏覽器,采用10s輪詢的方式,則服務(wù)器則會(huì)承擔(dān)1000 的QPS,這1w個(gè)商家可能只有10個(gè)有訂單通知;這種方式會(huì)對(duì)服務(wù)器造成極大的性能浪費(fèi)。
還有一個(gè)類似的輪詢是使用JSONP跨域請(qǐng)求的方式輪詢,在實(shí)現(xiàn)起來(lái)有差別,但基本原理都是相同的,都是客戶端不斷的向服務(wù)器發(fā)起請(qǐng)求。
優(yōu)點(diǎn)
實(shí)現(xiàn)簡(jiǎn)單。
缺點(diǎn)
這是通過(guò)模擬服務(wù)器發(fā)起的通信,不是實(shí)時(shí)通信,不顧及應(yīng)用的狀態(tài)改變而盲目檢查更新,導(dǎo)致服務(wù)器資源的浪費(fèi),且會(huì)加重網(wǎng)絡(luò)負(fù)載,拖累服務(wù)器。 comet
Comet是一種用于Web的推送技術(shù),能使服務(wù)器實(shí)時(shí)地將更新的信息傳送到客戶端,而無(wú)須客戶端發(fā)出請(qǐng)求,目前有兩種實(shí)現(xiàn)方式: 長(zhǎng)輪詢(long polling)
長(zhǎng)輪詢 (long polling) 是在打開(kāi)一條連接以后保持,等待服務(wù)器推送來(lái)數(shù)據(jù)再關(guān)閉,可以采用HTTP長(zhǎng)輪詢和XHR長(zhǎng)輪詢兩種方式。
HTTP 和JSONP方式的長(zhǎng)輪詢
把 script 標(biāo)簽附加到頁(yè)面上以讓腳本執(zhí)行。服務(wù)器會(huì)掛起連接直到有事件發(fā)生,接著把腳本內(nèi)容發(fā)送回瀏覽器,然后重新打開(kāi)另一個(gè) script 標(biāo)簽來(lái)獲取下一個(gè)事件,從而實(shí)現(xiàn)長(zhǎng)輪詢的模型。 XHR長(zhǎng)輪詢
這種方式是使用比較多的長(zhǎng)輪詢模式。
客戶端打開(kāi)一個(gè)到服務(wù)器端的 AJAX 請(qǐng)求然后等待響應(yīng);服務(wù)器端需要一些特定的功能來(lái)允許請(qǐng)求被掛起,只要一有事件發(fā)生,服務(wù)器端就會(huì)在掛起的請(qǐng)求中送回響應(yīng)并關(guān)閉該請(qǐng)求??蛻舳?JavaScript 響應(yīng)處理函數(shù)會(huì)在處理完服務(wù)器返回的信息后,再次發(fā)出請(qǐng)求,重新建立連接;如此循環(huán)。
現(xiàn)在瀏覽器已經(jīng)支持CROS的跨域方式請(qǐng)求,因此HTTP和JSONP的長(zhǎng)輪詢方式是慢慢被淘汰的一種技術(shù),建議采用XHR長(zhǎng)輪詢。 長(zhǎng)輪詢優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
客戶端很容易實(shí)現(xiàn)良好的錯(cuò)誤處理系統(tǒng)和超時(shí)管理,實(shí)現(xiàn)成本與Ajax輪詢的方式類似。
缺點(diǎn)
需要服務(wù)器端有特殊的功能來(lái)臨時(shí)掛起連接。當(dāng)客戶端發(fā)起的連接較多時(shí),服務(wù)器端會(huì)長(zhǎng)期保持多個(gè)連接,具有一定的風(fēng)險(xiǎn)。 iframe
iframe 是很早就存在的一種 HTML 標(biāo)記, 通過(guò)在 HTML 頁(yè)面里嵌入一個(gè)隱蔵幀,然后將這個(gè)隱蔵幀的 SRC 屬性設(shè)為對(duì)一個(gè)長(zhǎng)連接的請(qǐng)求,服務(wù)器端就能源源不斷地往客戶端輸入數(shù)據(jù)。
優(yōu)點(diǎn):
這種方式每次數(shù)據(jù)傳送不會(huì)關(guān)閉連接,連接只會(huì)在通信出現(xiàn)錯(cuò)誤時(shí),或是連接重建時(shí)關(guān)閉(一些防火墻常被設(shè)置為丟棄過(guò)長(zhǎng)的連接, 服務(wù)器端可以設(shè)置一個(gè)超時(shí)時(shí)間, 超時(shí)后通知客戶端重新建立連接,并關(guān)閉原來(lái)的連接)。
缺點(diǎn)
IE、Morzilla Firefox 下端的進(jìn)度欄都會(huì)顯示加載沒(méi)有完成,而且 IE 上方的圖標(biāo)會(huì)不停的轉(zhuǎn)動(dòng),表示加載正在進(jìn)行。
Google 的天才們使用一個(gè)稱為“htmlfile”的 ActiveX 解決了在 IE 中的加載顯示問(wèn)題,并將這種方法用到了 gmail+gtalk 產(chǎn)品中。Alex Russell 在 “What else is burried down in the depth’s of Google’s amazing JavaScript?”文章中介紹了這種方法。Zeitoun 網(wǎng)站提供的 comet-ifram
e.,封裝了一個(gè)基于 iframe 和 htmlfile 的 JavaScript comet 對(duì)象,支持 IE、Mozilla Firefox 瀏覽器,可以作為參考。
我們常用的網(wǎng)頁(yè)版的gtalk就是這種實(shí)現(xiàn)方式,Google的開(kāi)發(fā)人員使使用一個(gè)稱為“htmlfile”的 ActiveX 解決了在 IE 中的加載顯示問(wèn)題。 Comet實(shí)現(xiàn)框架 CometD
CometD 框架是基于 HTTP 的事件驅(qū)動(dòng)通信解決方案,使用了Bayeux通信協(xié)議,提供了一個(gè) Java 服務(wù)器部件和一個(gè) Java 客戶端部件,還有一個(gè)基于 jQuery 和 Dojo 的 JavaScript 客戶端庫(kù)。
Bayeux 通信協(xié)議主要是基于 HTTP,提供了客戶端與服務(wù)器之間的響應(yīng)性雙向異步通信。Bayeux 協(xié)議基于通道進(jìn)行通信,通過(guò)該通道從客戶端到服務(wù)器、從服務(wù)器到客戶端或從客戶端到客戶端(但是是通過(guò)服務(wù)器)路由和發(fā)送消息。Bayeux 是一種 “發(fā)布- 訂閱” 協(xié)議。
CometD 與三個(gè)傳輸協(xié)議綁定在一起:JSON、JSONP 和 WebSocket。他們都依賴于 Jetty Continuations 和 Jetty WebSocket API。在默認(rèn)情況下,可以在 Jetty 6、Jetty 7、和 Jetty 8 中以及其他所有支持 Servlet 3.0 Specification 的服務(wù)中使用 CometD。
服務(wù)器和內(nèi)部構(gòu)件 Atmosphere框架
Atmosphere提供了一個(gè)通用 API,以便使用許多 Web 服務(wù)器(包括 Tomcat、Jetty、GlassFish、Weblogic、Grizzly、JBossWeb、JBoss 和 Resin)的 Comet 和 WebSocket 特性。它支持任何支持 Servlet 3.0 Specification 的 Web 服務(wù)器。
Atmosphere 提供了一個(gè) jQuery 客戶端庫(kù),該庫(kù)可以使連接設(shè)置變得更容易,它能夠自動(dòng)檢測(cè)可以使用的最佳傳輸協(xié)議(WebSockets 或 CometD)。Atmosphere 的 jQuery 插件的用法與 HTML5 WebSockets API 相似。 Pushlet
Pushlet 使用了觀察者模型:客戶端發(fā)送請(qǐng)求,訂閱感興趣的事件;服務(wù)器端為每個(gè)客戶端分配一個(gè)會(huì)話 ID 作為標(biāo)記,事件源會(huì)把新產(chǎn)生的事件以多播的方式發(fā)送到訂閱者的事件隊(duì)列里。
Pushlet 最后更新于2010年2月5號(hào),之后至今沒(méi)有再更新。
Cometd 和Atmosphere框架參見(jiàn)示例代碼 (https://github.com/brucefengnju/cometdatoms)。 Comet實(shí)現(xiàn)要點(diǎn)
不要在同一客戶端同時(shí)使用超過(guò)兩個(gè)的 HTTP 長(zhǎng)連接
HTTP 1.1 規(guī)范中規(guī)定,客戶端不應(yīng)該與服務(wù)器端建立超過(guò)兩個(gè)的 HTTP 連接, 新的連接會(huì)被阻塞,在IE瀏覽器中嚴(yán)格遵守了這種規(guī)定。
服務(wù)器端的性能和可擴(kuò)展性
一般 Web 服務(wù)器會(huì)為每個(gè)連接創(chuàng)建一個(gè)線程,如果在大型的商業(yè)應(yīng)用中使用 Comet,服務(wù)器端需要維護(hù)大量并發(fā)的長(zhǎng)連接。在這種應(yīng)用背景下,服務(wù)器端需要考慮負(fù)載均衡和集群技術(shù);或是在服務(wù)器端為長(zhǎng)連接作一些改進(jìn)。
在客戶和服務(wù)器之間保持“心跳”信息
在瀏覽器與服務(wù)器之間維持一個(gè)長(zhǎng)連接會(huì)為通信帶來(lái)一些不確定性:因?yàn)閿?shù)據(jù)傳輸是隨機(jī)的,客戶端不知道何時(shí)服務(wù)器才有數(shù)據(jù)傳送。服務(wù)器端需要確保當(dāng)客戶端不再工作時(shí),釋放為這個(gè)客戶端分配的資源,防止內(nèi)存泄漏。因此需要一種機(jī)制使雙方知道雙方都在正常運(yùn)行。
服務(wù)器端在阻塞讀時(shí)會(huì)設(shè)置一個(gè)時(shí)限,超時(shí)后阻塞讀調(diào)用會(huì)返回,同時(shí)發(fā)給客戶端沒(méi)有新數(shù)據(jù)到達(dá)的心跳信息。此時(shí)如果客戶端已經(jīng)關(guān)閉,服務(wù)器往通道寫數(shù)據(jù)會(huì)出現(xiàn)異常,服務(wù)器端就會(huì)及時(shí)釋放為這個(gè)客戶端分配的資源。
如果客戶端使用的是基于 AJAX 的長(zhǎng)輪詢方式;服務(wù)器端返回?cái)?shù)據(jù)、關(guān)閉連接后,經(jīng)過(guò)某個(gè)時(shí)限沒(méi)有收到客戶端的再次請(qǐng)求,會(huì)認(rèn)為客戶端不能正常工作,會(huì)釋放為這個(gè)客戶端分配、維護(hù)的資源。
當(dāng)服務(wù)器處理信息出現(xiàn)異常情況,需要發(fā)送錯(cuò)誤信息通知客戶端,同時(shí)釋放資源、關(guān)閉連接。 websocket
WebSocket是HTML5開(kāi)始提供的一種在單個(gè) TCP 連接上進(jìn)行全雙工通訊的協(xié)議。WebSocket通訊協(xié)議于2011年被IETF定為標(biāo)準(zhǔn)RFC 6455,WebSocketAPI被W3C定為
標(biāo)準(zhǔn)。在WebSocket API中,瀏覽器和服務(wù)器只需要做一個(gè)握手的動(dòng)作,然后,瀏覽器和服務(wù)器之間就形成了一條快速通道。兩者之間就直接可以數(shù)據(jù)互相傳送。
瀏覽器支持 瀏覽器版本支持 Chrome 4+ Firefox 4+ IE 10+ Opera 10+ Safari 5+
詳情查看 Browser compatibility 實(shí)現(xiàn)
WebSocket的實(shí)現(xiàn)已經(jīng)有很多種版本,詳細(xì)可以查看DEMO。 總結(jié)
總結(jié)下來(lái)長(zhǎng)輪詢不是一個(gè)很好的方案,而且對(duì)于服務(wù)器而言是有風(fēng)險(xiǎn)的;另外支持WebSocket協(xié)議的瀏覽器都比較新,特比是IE需要10以上的版本;而我們的業(yè)務(wù)是面向于商家端,商家的瀏覽器版本相對(duì)較低,很多對(duì)WebSocket都不支持;相對(duì)而言Comet的方式比較適合,也有相應(yīng)的實(shí)現(xiàn)框架,實(shí)現(xiàn)成本最低;因此最后我們還是決定使用Comet的方式來(lái)實(shí)現(xiàn),后面上線運(yùn)行一段時(shí)間之后再來(lái)給大家介紹。
1.《瀏覽器怎么實(shí)現(xiàn)心跳?總結(jié)很全面速看!瀏覽器與服務(wù)器的消息通信》援引自互聯(lián)網(wǎng),旨在傳遞更多網(wǎng)絡(luò)信息知識(shí),僅代表作者本人觀點(diǎn),與本網(wǎng)站無(wú)關(guān),侵刪請(qǐng)聯(lián)系頁(yè)腳下方聯(lián)系方式。
2.《瀏覽器怎么實(shí)現(xiàn)心跳?總結(jié)很全面速看!瀏覽器與服務(wù)器的消息通信》僅供讀者參考,本網(wǎng)站未對(duì)該內(nèi)容進(jìn)行證實(shí),對(duì)其原創(chuàng)性、真實(shí)性、完整性、及時(shí)性不作任何保證。
3.文章轉(zhuǎn)載時(shí)請(qǐng)保留本站內(nèi)容來(lái)源地址,http://f99ss.com/gl/3005717.html