WebSocket在容器化管理平臺的應用

JSON Docker Go語言 Tmux 好雨科技 2017-04-25

介紹

Websocket是一個持久化協議,相對於HTTP這種非持久協議而言。它實現了瀏覽器與服務器全雙工通信,能更好的節省服務器資源和帶寬並達到實時通訊的目的,與HTTP一樣基於已建立的TCP連接來傳輸數據。但是與HTTP協議不同的地方就是:WebSocket是一種雙向通信協議,在建立連接後,WebSocket服務器端和客戶端都能主動向對方發送或接收數據,就像Socket一樣;WebSocket需要像TCP一樣,先建立連接,連接成功後才能相互通信。

運行機制

傳統的HTTP客戶端與服務器請求響應模式,一個生命週期裡只有一個或多個請求和一個或多個與之對應的響應。

如下所示:

WebSocket在容器化管理平臺的應用

而WebSocket模式下客戶端與服務器響應模式,一旦WebSocket連接建立,在客戶端或者服務端中斷連接前,數據都以幀序列傳輸,不需要重啟客戶端或者服務端重新發起連接請求。

WebSocket在容器化管理平臺的應用

websocket工作流程

  1. 客戶端發起請求

Request Method:GET

Status Code:101 Switching Protocols #101之後的數據傳輸採用Websocket協議

Connection:Upgrade

Sec-WebSocket-Extensions:permessage-deflate;

Sec-WebSocket-Key:dfQAy9mlQ0EjD5MmvvsZaQ== #驗證

Sec-WebSocket-Version:13

Upgrade:websocket #客戶端支持websocket協議,如果服務器也支持就使用WebSocket協議

2. 服務器解析,並返回握手信息,建立連接

Connection:upgrade

sec-websocket-accept:+mKC4huknIfMGJFOzclP9fO058g= #驗證

upgrade:websocket

3. 傳輸數據(雙向)

4. 斷開連接

應用場景

WebSocket屬於Web領域的實時推送技術,目的讓用戶不刷新瀏覽器就可以實時更新。其在容器化管理平臺裡主要有兩個應用場景類型,一個是實時消息類,將實時日誌、業務監控等相關信息推送給客戶端。如:在容器化管理平臺裡部署了一個應用,那麼應用部署的日誌、運行日誌以及監控信息如何及時推送到前端呢,另外一個就是交互消息類,在Web界面操作容器,節省手動登錄服務器進入容器內的時間,提高效率。

實例1:實時消息

就拿雲幫而言,需要實時推送的是每個應用的日誌信息和業務監控數據。那麼我們在處理實時消息時就採用了WebSocket與ZMQ相結合的方式,快速實現將應用日誌信息推送到web端。其簡化模型如下所示:

WebSocket在容器化管理平臺的應用

客戶端與服務器採用WebSocket協議,實時傳輸相關數據。相關數據方面採用的是ZMQ。雲幫主要使用了ZeroMQ消息隊列中的Publisher-Subscriber模型,將所有相關信息彙總到一個節點上在推送到其他節點上。即客戶端(SUB)向服務器(PUB)訂閱消息,然後服務器將消息推送到所有訂閱了消息到客戶端,類似於廣播。之所以採用ZMQ,而不是Socket的原因,前者支持N:M的連接,後者只能1:1的連接。其消息隊列模型示意圖:

WebSocket在容器化管理平臺的應用

具體的應用場景相關設定參數:

#docker-compose.yml

mpush:

container_name: mpush

environment:

- ZMQ_SUB_FROM=tcp://ip:9242

image: hub.goodrain.com/dc-deploy/mpush

log_driver: json-file

log_opt:

max-size: 50m

ports:

- 0.0.0.0:6060:6060

restart: always

#config.py 定義實時消息URL

WEBSOCKET_URL = {

'cloudbang': 'ws://ip:6060/websocket',

}

#dalaran_docker

ZMQ_BIND_SUB=tcp://0.0.0.0:9241

ZMQ_BIND_PUB=tcp://0.0.0.0:9242

ZMQ_BIND_PUB2=tcp://0.0.0.0:9243

#setting

'docker_sub': {

'address': [

'tcp://ip:9242'

],

'storage': '/data/docker_logs'

},

實例2:交互消息

GoTTY是一個用Go語言開發的工具,可以將操作系統的命令字符終端共享成普通的網頁應用展示出來。

在mac安裝根據情況選擇一種

#brew

brew tap yudai/gotty

brew install gotty

#go

go get github.com/yudai/gotty

使用:

gotty -a 0.0.0.0 -p '8080' -w tmux

WebSocket在容器化管理平臺的應用

WebSocket在容器化管理平臺的應用

那麼在雲幫,我們又是如何解決這個問題的?

雲幫web端操作容器就是基於gotty定製開發的WebSocket共享字符終端。

創建一個websocket實例,連接服務器進行前後臺交互及相關事件處理

#前端實現部分代碼

var openWs = function() {

if(is_community == "True"){

host_name = window.location.hostname+":8188";

}

var url = tmp_url.replace("{{DOCKER_WSS_URL}}",host_name)

console.log(url)

var ws = new WebSocket(url);

var term;

var pingTimer;

ws.onopen = function(event) {

ws.send(JSON.stringify({ T_id: t_id, S_id: s_id, C_id: c_id, Md5: md5,}));

pingTimer = setInterval(sendPing, 30 * 1000, ws);

hterm.defaultStorage = new lib.Storage.Local();

hterm.defaultStorage.clear();

term = new hterm.Terminal();

term.getPrefs().set("send-encoding", "raw");

term.onTerminalReady = function() {

var io = term.io.push();

io.onVTKeystroke = function(str) {

ws.send("0" + str);

};

io.sendString = io.onVTKeystroke;

io.onTerminalResize = function(columns, rows) {

ws.send(

"2" + JSON.stringify(

{

columns: columns,

rows: rows,

}

)

)

};

term.installKeyboard();

};

term.decorate(document.getElementById("terminal"));

};

後端程序基於Gotty開發的。

相關推薦

推薦中...