web 實時重新整理 websocket 大資料
最近在做的一個專案,是一個大資料分析平臺,有如下需求:有如果個實驗裝置執行並且將執行資料通過socket傳送到分析平臺,分析平臺通過執行socket作業來完成對socket資料的接收,同時還需要對接收到的socket資料進行解析並且可以通過一個數據看板對資料實時監控。如下圖所示:
選擇websocket的原因,就是看板頁面不必每次都去定時的請求資料,而是一旦websocket伺服器發現有新資料則直接推送給客戶端進行渲染,減少了佔用的寬頻和伺服器資源。由於socket資料量多且快,所以如果將資料直接存入到傳統的關係型資料庫則會遇到效率瓶頸,這時候就必須要有一個快取,redis基於記憶體且最大的特點就是快,用作快取再合適不過,待作業結束後再將資料儲存進hbase中即可。看板用到了baidu的echarts3折線圖。
接收到的socket資料來源源不斷的被寫入到redis中,接收到的資料格式類似於:資料量1|資料量2|資料量3|日期1|日期2...websocket的任務就是將這些資料交給看板進行渲染,那麼怎麼去拿到資料呢?就是websocket服務端定時的去redis拿,一旦有新資料則推送給看板。
首先開發websocket服務端,ServerSocket採用單例模式,因為是整合服務,所以如果需要關閉服務的話可以直接將ServerSocket關閉即可,伺服器端程式碼如下:
1. PrintWriter pw = getWriter(socket);
2. byte[] buf = new
3. int len = in.read(buf, 0, 1024);
4. byte[] res = newbyte[len];
5. System.arraycopy(buf, 0, res, 0, len);
6. String key = new String(res);
7. if (!hasHandshake && key.indexOf("Key") > 0) {
8. key = key.substring(
9. key = key.substring(key.indexOf("Key") + 4, key.length())
10. .trim();
11. key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
12. MessageDigest md = MessageDigest.getInstance("SHA-1");
13. md.update(key.getBytes("utf-8"), 0, key.length());
14. byte[] sha1Hash = md.digest();
15. sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
16. key = encoder.encode(sha1Hash);
17. pw.println("HTTP/1.1 101 Switching Protocols");
18. pw.println("Upgrade: websocket");
19. pw.println("Connection: Upgrade");
20. pw.println("Sec-WebSocket-Accept: " + key);
21. pw.println();
22. pw.flush();
23. hasHandshake = true;
24. }
上面這段程式碼是websocket握手的程式碼,握手之後獲取看板傳來的id,然後再去redis請求資料,發現新資料則推送給看板,推送的程式碼:
1. /**
2. * 推送資料到客戶端
3. *
4. * @param byteBuf
5. * @param finalFragment
6. * @throws IOException
7. */
8. privatevoid responseClient(ByteBuffer byteBuf, boolean finalFragment)
9. throws IOException {
10. OutputStream out = socket.getOutputStream();
11. int first = 0x00;
12. // 是否是輸出最後的WebSocket響應片段
13. if (finalFragment) {
14. first = first + 0x80;
15. first = first + 0x1;
16. }
17. out.write(first);
18.
19. if (byteBuf.limit() < 126) {
20. out.write(byteBuf.limit());
21. } elseif (byteBuf.limit() < 65536) {
22. out.write(126);
23. out.write(byteBuf.limit() >>> 8);
24. out.write(byteBuf.limit() & 0xFF);
25. } else {
26. out.write(127);
27. out.write(0);
28. out.write(0);
29. out.write(0);
30. out.write(0);
31. out.write(byteBuf.limit() >>> 24);
32. out.write(byteBuf.limit() >>> 16);
33. out.write(byteBuf.limit() >>> 8);
34. out.write(byteBuf.limit() & 0xFF);
35.
36. }
37.
38. // Write the content
39. out.write(byteBuf.array(), 0, byteBuf.limit());
40. out.flush();
41. }
伺服器端程式碼的核心基本上是這些,那麼現在是前段的程式碼了,因為是使用了echarts的折線圖,所以至於echarts的使用這裡不贅述,在頁面載入完畢後連線websocket服務端並且傳送id以及其他的一些引數,連線的程式碼如下所示:
[javascript]view plaincopy
1. function connect(form_data) {
2. try {
3. var host = "ws://localhost:8000";
4. websocket = new WebSocket(host);
5.
6. websocket.onopen = function() {
7. if (form_data != null)
8. sendToServer(form_data);// 與伺服器端連線成功後需要將作業例項ID傳送給伺服器端
9. };
10. websocket.onmessage = function(event) {// 伺服器端推送過來的資料格式必須是:資料量|日期
11. // ,其中日期格式為:yyyy-MM-dd HH:mm:ss:SS
12. processMultiData(event.data);// 處理多行資料
13. if (option2.series.length == 0)
14. genLegend();
15. genSeries();
16. myChart.setOption(option2);
17. };
18. websocket.onclose = function() {
19. // alert('連線關閉');
20. };
21. } catch (exception) {
22. alert("error");
23. }
24. }
傳送資料給伺服器端的程式碼:
[javascript]view plaincopy
1. function sendToServer(option_data) {// 傳送例項ID往ws伺服器端
2. try {
3. websocket.send(option_data);
4. } catch (exception) {
5. alert("傳送例項ID出錯!" + exception);
6. }
7. }
websocket的幾個方法分別是onopen:連線上後執行;onmessage:接收到資料後執行的邏輯,還有onclose以及onerror都很好理解啦。
==
用 SqlDependency
自動通知,
只有資料表有變化,就自動反映出來了,
專案是一個實時監控系統,有一個告警資料需要4秒內響應,可是告警資料的入庫不是在web平臺進行無法跟蹤,是其他系統入庫。領導希望web告警的資訊展示能馬上響應,原先做法是頁面每30重新整理一次,如果要在4秒內做響應就要改成4秒重新整理這樣對資料訪問太過頻繁,小弟不知如何解決希望各位幫助一下
實時的開啟 和 關閉。暫停播放。
有三種方式:
1,ajax短連線:客戶端每隔一秒鐘發一次請求,伺服器收到請求後會立刻返回結果,不管有沒有新資料。
2,ajax長連線:客戶端傳送一次請求,伺服器端收到請求後查詢有沒有新資料,如果沒有新資料就阻塞這個請求,直到有新資料或者超時為止。客戶端每次收到請求返回結果後立刻再發一次請求。comet貌似就是這個原理。
3,WebSocket:這就不是一個HTTP協議了,而是一個tcp協議,而且Socket這個玩意顧名思義就是一個流了,可以雙向操作。缺點是有些瀏覽器不支援。
對比延遲:
假設網路延遲是m毫秒,那麼ajax短連線的延遲在m到1000毫秒之間,另外兩種基本只有m毫秒的延遲。
對比資源佔用:
應該是1>2>3。但是1和2的比較要看情況,如果兩次請求間隔時間很長的話應該是2>1>3。
實時通訊技術在股票價格、新聞報道、餘票查詢、交通情況等領域中有著廣泛的應用,
但是目前的實時Web應用的實現方式,都是基於HTTP協議,圍繞著輪詢和其他伺服器推送技術展開的,所以不可避免的產生大量的額外的報頭資料,造成傳輸時延。HTML5中的WebSocket協議是基於瀏覽器與伺服器全雙工通訊的新理論。客戶端通過WebSocket與伺服器進行通訊時,只有第一次握手互動資訊比較複雜,在握手成功後便進入全雙工的資料傳輸階段,降低了資料流量與傳輸時延。
setInterval用這個方法,頁面自動重新整理,N秒鐘執行一次。
股市看盤,2秒獲取一次http。
Web頁面實時刷新技術探討
一、總述
隨著網路技術的飛速發展,使用B/S結構來實現專案應用已經越來越多,而實時監控一直都是多數行業軟體所必備的功能,由此使用Web頁面來實現實時監控成了一種必然的需求。
二、實時刷新技術
1、傳統的頁面重新整理方式
傳統的頁面重新整理方式很多,常見的有頁面間隔一定的時間自動重新整理、ActiveX控制元件、Applet等。
採用頁面間隔一定的時間自動重新整理的方式,是在網頁的頭部加入一下程式碼:
<metahttp-equiv="refresh" content="20;url=newPage">
這裡是經過20秒跳轉到一個新頁面,可以將“newPage”設定為本頁面即為重新整理本頁面,重新整理間隔時間可以修改“20”為任意時間。通過這種方式如果併發和訪問量較大,伺服器就有可能承受不了這種壓力,從而造成伺服器宕機。
使用ActiveX控制元件的方式需要每個客戶端下載安裝ActiveX控制元件,並且客戶端瀏覽器只能使用Windows的IE瀏覽器。
同樣使用Applet需要客戶端安裝Java執行時。
這些傳統的頁面重新整理方式都或多或少的存在著一些確定,在Web專案應用中的使用也越來越少。
2、Ajax輪詢
Ajax輪詢方式是使用客戶端指令碼,通過XMLHttpRequest來定時傳送請求,從而查詢頁面資料的更新情況。通過這種方式,程式實現方便簡捷,但客戶端頻繁的傳送請求會給伺服器帶來很大的壓力和客戶端處理器負載,如果伺服器端沒有更新時,這種輪詢訪問伺服器便是無意義的,並且耗費了網路資源與CPU處理資源。
3、DWR伺服器Push
DWR的反轉AJAX功能允許我們從伺服器端來控制客服端,而不需要客戶端的請求,伺服器可以自動把訊息發給指定的客戶端。DWR的Push技術是讓伺服器每次傳送廣播時,把這個廣播推送給客戶端,而不用客戶端去重新整理,DWR的推送是基於長連線的,效能優越。
4、與服務端建立長連線
與伺服器建立長連線,也就是在顯示資料頁面中嵌入一個隱藏頁面,該隱藏頁面主要完成取伺服器端所要顯示的資料,並且將該頁面顯示資料的方法寫成一個死迴圈,以此來保持與伺服器端的長連線。
同樣以伺服器端通過手動控制按鈕產生一張圖片,客戶端顯示最新圖片及圖片的資訊內容作為例項加以說明。
5、RTMP協議傳輸
隨著網路技術的迅猛發展,視訊、音訊等多媒體通訊需求越來越多,Adobe公司開放了RTMP(theReal-time Messaging Protocol)協議規範,RTMP協議作為客戶端和伺服器端的傳輸協議,這是一個專門為高效傳輸視訊、音訊和資料而設計的 TCP/IP 協議。其優秀產品Flex是用於構建和維護在所有主要瀏覽器、桌面和作業系統一致地部署的極具表現力的 Web 應用程式的高效率的開放原始碼框架。
從目前的應用來說,RTMP主要用於音、視訊的傳輸,流視訊伺服器就是FMS(Flash Media Server),其原稱為FCS(Flash Communication Server),技術範疇能應用到諸如Flash聊天室、視訊會議等領域。
以一個實現聊天功能的Flex程式為例,
從目前實際應用來說,以上四種實現Web頁面實時重新整理都是可行方案,各有優缺點與適用的具體環境。
Ajax輪詢方式比較適用於需要傳輸的資料量較小的情況,可通過客戶端首先輪詢伺服器端的更新標識,若有更新再下載更新資料,這樣能減小一部分伺服器的壓力。
DWR反轉AJAX功能,真正實現了從伺服器端將更新“推”到客戶端。
與伺服器端建立長連線的方式,也是通過客戶端的請求獲取更新資料的。
通過RTMP協議傳輸,主要適用於音、視訊的資料傳輸,比較適用於視訊聊天室,目前視訊伺服器FMS的費用較高(4500元100個客戶端),與伺服器的連線數受到限制。
總體來看,要實現Web頁面的實時重新整理,肯定是會給伺服器帶來一定的壓力的,對於具體專案的不同需求,可選擇合適的方式來實現Web頁面的實時重新整理。