1. 程式人生 > >瀏覽器與伺服器的訊息通訊

瀏覽器與伺服器的訊息通訊

最近工作中遇到一個場景,商家在商家後臺需要實時的獲取到有沒有新訂單,有的話是幾個;這個需求類似與日常中使用QQ或者微信時的新資訊提醒一樣,只要有新資訊就需要提醒;商家基本在PC上使用,各式瀏覽器都有:如 IE系列(7.0,8.0,9.0及以上),chrome核心,firefox等;功能所屬的部署在Tomcat 6.0上,如果技術需要可以部署到 Tomcat 7.0上;

我們先做做技術調研,這種瀏覽器與伺服器實時通訊的方式有哪些方式。

AJAX輪詢

這是我們最自然想到的。 採用常規AJAX輪詢的方式,每10s或者30s輪詢一次,既可以判斷出有有多少個新訂單進入,且這種時間間隔對於訊息提醒也是可以接受的。這種技術方式實現起來非常簡單,目前的機器都是可以機器的,前端瀏覽器也都支援。

但是這種方式會有非常嚴重的問題,就是需要不斷的向伺服器傳送訊息詢問,如果有1w個商家打開了瀏覽器,採用10s輪詢的方式,則伺服器則會承擔1000 的QPS,這1w個商家可能只有10個有訂單通知;這種方式會對伺服器造成極大的效能浪費。

還有一個類似的輪詢是使用JSONP跨域請求的方式輪詢,在實現起來有差別,但基本原理都是相同的,都是客戶端不斷的向伺服器發起請求。

優點
實現簡單。

缺點
這是通過模擬伺服器發起的通訊,不是實時通訊,不顧及應用的狀態改變而盲目檢查更新,導致伺服器資源的浪費,且會加重網路負載,拖累伺服器。

Comet

Comet是一種用於Web的推送技術,能使伺服器實時地將更新的資訊傳送到客戶端,而無須客戶端發出請求,目前有兩種實現方式:

長輪詢(long polling)

長輪詢 (long polling) 是在開啟一條連線以後保持,等待伺服器推送來資料再關閉,可以採用HTTP長輪詢和XHR長輪詢兩種方式。

HTTP 和JSONP方式的長輪詢

把 script 標籤附加到頁面上以讓指令碼執行。伺服器會掛起連線直到有事件發生,接著把指令碼內容傳送回瀏覽器,然後重新開啟另一個 script 標籤來獲取下一個事件,從而實現長輪詢的模型。

XHR長輪詢

這種方式是使用比較多的長輪詢模式。

客戶端開啟一個到伺服器端的 AJAX 請求然後等待響應;伺服器端需要一些特定的功能來允許請求被掛起,只要一有事件發生,伺服器端就會在掛起的請求中送回響應並關閉該請求。客戶端 JavaScript 響應處理函式會在處理完伺服器返回的資訊後,再次發出請求,重新建立連線;如此迴圈。

現在瀏覽器已經支援CROS的跨域方式請求,因此HTTP和JSONP的長輪詢方式是慢慢被淘汰的一種技術,建議採用XHR長輪詢。

長輪詢優缺點

優點
客戶端很容易實現良好的錯誤處理系統和超時管理,實現成本與Ajax輪詢的方式類似。
缺點
需要伺服器端有特殊的功能來臨時掛起連線。當客戶端發起的連線較多時,伺服器端會長期保持多個連線,具有一定的風險。

iframe

iframe 是很早就存在的一種 HTML 標記, 通過在 HTML 頁面裡嵌入一個隱蔵幀,然後將這個隱蔵幀的 SRC 屬性設為對一個長連線的請求,伺服器端就能源源不斷地往客戶端輸入資料。

優點:
這種方式每次資料傳送不會關閉連線,連線只會在通訊出現錯誤時,或是連線重建時關閉(一些防火牆常被設定為丟棄過長的連線, 伺服器端可以設定一個超時時間, 超時後通知客戶端重新建立連線,並關閉原來的連線)。

缺點
IE、Morzilla Firefox 下端的進度欄都會顯示載入沒有完成,而且 IE 上方的圖示會不停的轉動,表示載入正在進行。

Google 的天才們使用一個稱為“htmlfile”的 ActiveX 解決了在 IE 中的載入顯示問題,並將這種方法用到了 gmail+gtalk 產品中。Alex Russell 在 “What else is burried down in the depth’s of Google’s amazing JavaScript?”文章中介紹了這種方法。Zeitoun 網站提供的 comet-iframe.tar.gz,封裝了一個基於 iframe 和 htmlfile 的 JavaScript comet 物件,支援 IE、Mozilla Firefox 瀏覽器,可以作為參考。

我們常用的網頁版的gtalk就是這種實現方式,Google的開發人員使使用一個稱為“htmlfile”的 ActiveX 解決了在 IE 中的載入顯示問題。

Comet實現框架

CometD

CometD 框架是基於 HTTP 的事件驅動通訊解決方案,使用了Bayeux通訊協議,提供了一個 Java 伺服器部件和一個 Java 客戶端部件,還有一個基於 jQuery 和 Dojo 的 JavaScript 客戶端庫。

Bayeux 通訊協議主要是基於 HTTP,提供了客戶端與伺服器之間的響應性雙向非同步通訊。Bayeux 協議基於通道進行通訊,通過該通道從客戶端到伺服器、從伺服器到客戶端或從客戶端到客戶端(但是是通過伺服器)路由和傳送訊息。Bayeux 是一種 “釋出- 訂閱” 協議。

CometD 與三個傳輸協議繫結在一起:JSON、JSONP 和 WebSocket。他們都依賴於 Jetty Continuations 和 Jetty WebSocket API。在預設情況下,可以在 Jetty 6、Jetty 7、和 Jetty 8 中以及其他所有支援 Servlet 3.0 Specification 的服務中使用 CometD。

Atmosphere提供了一個通用 API,以便使用許多 Web 伺服器(包括 Tomcat、Jetty、GlassFish、Weblogic、Grizzly、JBossWeb、JBoss 和 Resin)的 Comet 和 WebSocket 特性。它支援任何支援 Servlet 3.0 Specification 的 Web 伺服器。

Atmosphere 提供了一個 jQuery 客戶端庫,該庫可以使連線設定變得更容易,它能夠自動檢測可以使用的最佳傳輸協議(WebSockets 或 CometD)。Atmosphere 的 jQuery 外掛的用法與 HTML5 WebSockets API 相似。

Pushlet 使用了觀察者模型:客戶端傳送請求,訂閱感興趣的事件;伺服器端為每個客戶端分配一個會話 ID 作為標記,事件源會把新產生的事件以多播的方式傳送到訂閱者的事件佇列裡。

Pushlet 最後更新於2010年2月5號,之後至今沒有再更新。

Cometd 和Atmosphere框架參見示例程式碼 (https://github.com/brucefengnju/cometdatoms)。

Comet實現要點

不要在同一客戶端同時使用超過兩個的 HTTP 長連線
HTTP 1.1 規範中規定,客戶端不應該與伺服器端建立超過兩個的 HTTP 連線, 新的連線會被阻塞,在IE瀏覽器中嚴格遵守了這種規定。

伺服器端的效能和可擴充套件性
一般 Web 伺服器會為每個連線建立一個執行緒,如果在大型的商業應用中使用 Comet,伺服器端需要維護大量併發的長連線。在這種應用背景下,伺服器端需要考慮負載均衡和叢集技術;或是在伺服器端為長連線作一些改進。

在客戶和伺服器之間保持“心跳”資訊
在瀏覽器與伺服器之間維持一個長連線會為通訊帶來一些不確定性:因為資料傳輸是隨機的,客戶端不知道何時伺服器才有資料傳送。伺服器端需要確保當客戶端不再工作時,釋放為這個客戶端分配的資源,防止記憶體洩漏。因此需要一種機制使雙方知道雙方都在正常執行。
伺服器端在阻塞讀時會設定一個時限,超時後阻塞讀呼叫會返回,同時發給客戶端沒有新資料到達的心跳資訊。此時如果客戶端已經關閉,伺服器往通道寫資料會出現異常,伺服器端就會及時釋放為這個客戶端分配的資源。

如果客戶端使用的是基於 AJAX 的長輪詢方式;伺服器端返回資料、關閉連線後,經過某個時限沒有收到客戶端的再次請求,會認為客戶端不能正常工作,會釋放為這個客戶端分配、維護的資源。

當伺服器處理資訊出現異常情況,需要傳送錯誤資訊通知客戶端,同時釋放資源、關閉連線。

WebSocket是HTML5開始提供的一種在單個 TCP 連線上進行全雙工通訊的協議。WebSocket通訊協議於2011年被IETF定為標準RFC 6455,WebSocketAPI被W3C定為標準。在WebSocket API中,瀏覽器和伺服器只需要做一個握手的動作,然後,瀏覽器和伺服器之間就形成了一條快速通道。兩者之間就直接可以資料互相傳送。

瀏覽器支援

瀏覽器 版本支援
Chrome 4+
Firefox 4+
IE 10+
Opera 10+
Safari 5+

實現

WebSocket的實現已經有很多種版本,詳細可以檢視DEMO

總結

總結下來長輪詢不是一個很好的方案,而且對於伺服器而言是有風險的;另外支援WebSocket協議的瀏覽器都比較新,特比是IE需要10以上的版本;而我們的業務是面向於商家端,商家的瀏覽器版本相對較低,很多對WebSocket都不支援;相對而言Comet的方式比較適合,也有相應的實現框架,實現成本最低;因此最後我們還是決定使用Comet的方式來實現,後面上線執行一段時間之後再來給大家介紹。

References

打賞支援我寫出更多好文章,謝謝!

打賞作者

打賞支援我寫出更多好文章,謝謝!

任選一種支付方式

相關推薦

瀏覽器伺服器訊息通訊

最近工作中遇到一個場景,商家在商家後臺需要實時的獲取到有沒有新訂單,有的話是幾個;這個需求類似與日常中使用QQ或者微信時的新資訊提醒一樣,只要有新資訊就需要提醒;商家基本在PC上使用,各式瀏覽器都有:如 IE系列(7.0,8.0,9.0及以上),chrome核心,f

瀏覽器伺服器通訊的過程

首先需要知道: 使用者在瀏覽器中輸入網址時候,瀏覽器會通過訪問的域名來定位得到IP(DNS) 會依此從瀏覽器快取、系統快取、路由器快取、ISP DNS快取中查詢 HTTP協議:超文字傳輸協議,目的是為了提供一種釋出和接受HTML頁面的方法,瀏覽器和伺服器都遵循的一種

WebSocket瀏覽器伺服器之間的對話(用於訊息推送)

 1.如果加入資料庫後,A發訊息時客戶B未上線,服務端將會把訊息存在資料庫中,等客戶B上線後,在將訊息取出傳送給客戶B 2.服務端也可傳送訊息到任意客戶端上。 程式的執行效果截圖如下(在chrome,搜狗,firefox下測試通過):程式碼將在最後給出 首先我們開啟一個

瀏覽器伺服器通訊技術——跨域資源共享

由於同源策略限制,預設情況下,使用XHR物件只能訪問與包含它的頁面位於同一個域(相同的協議、域名和埠)中的資源。要實現合理的跨域資源請求,有兩種策略:1.跨域資源共享 ,2.利用DOM中能夠執行跨域請求的功能。本文詳述了第一種策略的實現方法。 跨域資源共享(CORS)背後的基本思想,就是使用自定義的HTTP

java socket:客戶端伺服器通訊

Socket:網路上兩個程式通過一個雙向的通訊連線實現資料交換,連線的一段為一個socket,要實現兩個程式的資料交換一般要一對socket。 這個定義參考自百度百科,我覺得說的還不錯,另外,socket的英文有‘插口’的意思,其實也可以理解為程式的插口等等。

JavaWeb學習總結(二)——瀏覽器伺服器的互動

疑問:學習web開發,為什麼必須要先裝一個WEB伺服器? 1、不管什麼web資源,想被遠端計算機訪問,都必須有一個與之對應的網路通訊程式,當用戶來訪問時,這個網路通訊程式讀取web資源資料,並把資料傳送給來訪者。2、WEB伺服器就是這樣一個程式,它用於完成底層網路通迅。使用

Chrome外掛:本地程式實現驗證碼破解(瀏覽器本地程序通訊

利用chrome呼叫本地程式破解圖片驗證碼background.js  var port = null, tabId, fname = "vcode.chrome.v1.item.01"; //對應登錄檔HKEY_CURRENT_USER\Software\Google\Chrome\Nat

Ajax伺服器非同步通訊通訊程式碼的實現

Ajax實現了無需重新整理介面就能從伺服器拿到資料作為一種非常流行的技術,現已廣泛應用於前端開發 Ajax的核心是XMLHttpRequest這個物件。 看看具體的程式 1. XMLHttpRequest的方法與屬性介紹,通過程式我們查詢

瀏覽器伺服器資料互動亂碼問題小總結一下

request亂碼指的是:瀏覽器向伺服器傳送的請求引數中包含中文字元,伺服器獲取到的請求引數的值是亂碼; response亂碼指的是:伺服器向瀏覽器傳送的資料包含中文字元,瀏覽器中顯示的是亂碼; 亂碼產生的原因:不管是request亂碼還是response亂碼,其實都是由於客戶端(瀏覽器)跟伺服器端採用

瀏覽器伺服器互動資訊(序列化發序列化) ViewState

本篇來解釋上篇博文中使用者輸入資料沒有消失的問題。(由於http協議的無狀態性使得每次頁面請求都會重新建立所有控制元件。即所有的資料都將不復存在) 先來看一下asp.net頁面的生命週期 ASP.NET頁面的生命週期:(詳見ASP.Net4.0權威指南第1章第3節) 1.瀏

使用WebSocket伺服器進行通訊

WebSocket介面 按照傳統的HTTP協議,如果瀏覽器不向Web伺服器發起請求,那麼Web伺服器就不能把資料“推送”給瀏覽器。在這樣的技術背景下,如果需要構建實時性要求比較高的應用,比如線上遊戲,線上證券,裝置監控,新聞線上播報等,當客戶端瀏覽器呈現這些資訊的時候,伺服

Android伺服器通訊方式(一)之HTTP、TCP、Socket

      Android作為客戶端,與伺服器的通訊方式主要有兩種:一種是HTTP通訊,一種是Socket通訊。 一、HTTP、Socket簡介       HTTP通訊:即使用HTTP協議進行通訊,工作原理是客戶端向伺服器端傳送一條HTTP請求,伺服器收到之後先解析客戶

Android客戶端伺服器進行通訊

在Android開發中,經常使用到與後臺進行互動,後臺人員給你一個URL,Android使用HttpURLConnection得到後臺返回的資料。這些任務是開發中經常遇到的。這裡,我們自己搭建一個簡易的後臺,來實現Android客戶端與後臺的互動。 首先,後臺

linux下socket實現多個客戶端伺服器通訊

學習完《UNIX環境高階程式設計》套接字一章的內容之後,自己實現了單個客戶端與伺服器的通訊程式,後面想想要是多個客戶端如何與伺服器通訊呢?這就有了這篇文章。 伺服器端程式: #include<stdio.h> #include <stdlib.h&g

Android客戶端伺服器連線通訊

遇到一個小問題: 第一個Activity與伺服器連線時能夠成功連線 但是利用跳轉之後的Activity與伺服器連線一直不成功 解決: 在登陸時呼叫connect方法與伺服器連線,Activity跳轉之後就會斷開連線,因為連線函式是直

Java NIO學習筆記(四) 使用JDK 1.7 NIO2.0 實現客戶端伺服器通訊

JDK1.7 提供了全新的非同步NIO模式。稱為:NIO2.0或AIO。該模式引入了新的非同步通道的概念,並提供了非同步檔案通道和非同步套接字通道的實現。非同步通道提供兩種方式獲取獲取操作結果。分別是: 通過java.util.concurrent

Android開發伺服器端,android伺服器如何通訊

最近在做一個對PC端資料庫操作的事,知道伺服器是用websrvers,但是不知道websrvers是怎麼知道你使用者需要什麼,伺服器怎麼得知你要執行的操作是什麼。他們是用什麼方法交流的。求大神給講解下,在下小白。

【玩轉cocos2d-x之三十一】弱聯網伺服器通訊

這裡採用Apache+php搭建了一個簡易伺服器,服務端用php語言,客戶端採用cocos2d-x的CCHttpClient類通過http方式訪問服務端資源。模擬了cocos2d-x提交賬戶和密

Http協議下的瀏覽器伺服器的互動

http是超文字傳輸協議的縮寫,顧名思義,它是瀏覽器有伺服器傳輸超文字時所要遵守的一套協議。通俗的講,http協議是基於應用層的通訊規範。所以,瞭解http協議對於web開發是尤為重要的。 一. 關於http的幾個概念: 1. 連線: 瀏覽器與伺服器之間傳

Linux C UDP Socket實現客戶伺服器簡單通訊

在linux平臺下用c語言udp協議實現客戶與伺服器的簡單通訊與封裝的實現 一、伺服器端 1、新建CreateServer.c和CreateServer.h檔案,伺服器的建立程式碼在此實現,程式中封裝了建立TcpSocket和UdpSocket伺服器的方法,