python tornado websocket 即時日誌展示,tornadowebsocket
一、主題:即時展示伺服器端動態產生的記錄檔
二、流程:
1. 用戶端瀏覽器與伺服器建立websocket 連結,伺服器掛起儲存連結執行個體,等待新內容觸發返回動作
2. Log Service器指令碼迴圈去發現新內容,發現新行向 tornado等待API POST 發送新內容
3. tornado 處理器接收到新內容, 通過 websocket 向儲存的用戶端連結返回新行
4. 用戶端瀏覽器接收到新內容,修飾,展示
三、代碼:
1. tornado伺服器url路由、基本頁面handler 及 html:
#模組路徑根據自身項目而定 (r'/logs/index/', 'apps.logs.handler.IndexHandler'), (r'/logs/newlinesforcallbacker/', 'apps.logs.handler.WriteNewLinesHandler'), (r'/logs/newlinesforserver/', 'apps.logs.handler.ReceiveNewLinesHandler'),
class IndexHandler(BaseHandler): ''' 首頁 ''' def get(self, *args, **kwargs): self.render('logs/index.html')
<div align="center"> <h2>this logs monitor</h2> <div style="width: 70%" id="main"> <!-- 行展示 --> </div></div>
2. 伺服器端websocket handler (WriteNewLinesHandler) 、 儲存刪除連結處理類 及用戶端websocket請求 js
class ProStatus(object): ''' 處理類 ''' w_register = [] def register(self, callbacker): ''' 記錄用戶端串連執行個體 ''' self.w_register.append(callbacker) def unregister(self, callbacker): ''' 刪除用戶端串連執行個體 ''' self.w_register.remove(callbacker) def makelines(self, lines): ''' 處理接受的行內容 ''' pass def trigger(self, line): ''' 向所有被記錄用戶端發送最新內容 ''' passclass WriteNewLinesHandler(tornado.websocket.WebSocketHandler): ''' 接受websocket連結,儲存連結執行個體 ''' def check_origin(self, origin): #針對websocket處理類重寫同源檢查的方法 return True def open(self): ''' 處理新的串連 ''' ProStatus().register(self) def on_close(self): ProStatus().unregister(self) #刪除用戶端串連 def on_message(self, message): pass
$(function(){ function requestText(){ host = "ws://" + location.hostname + ":" + location.port + "/logs/newlinesforcallbacker/" websocket = new WebSocket(host) websocket.onopen = function(evt){} // 建立串連 websocket.onmessage = function(evt){ // 擷取伺服器返回的資訊 data = $.parseJSON(evt.data) $("#main").append(data+"</br>") //寫入頁面 } websocket.onerror = function(evt){} } requestText()})
3. tornado 等待指令碼提交新內容處理handler(ReceiveNewLinesHandler)、 向掛起用戶端發送新內容函數 及 遍曆日誌提交新內容指令碼
class ProStatus(object): ''' 處理類 ''' w_register = [] def register(self, callbacker): ''' 記錄用戶端串連執行個體 ''' pass def unregister(self, callbacker): ''' 刪除用戶端串連執行個體 ''' pass def makelines(self, lines): ''' 處理接受的行內容 ''' for line in lines: self.trigger(line) def trigger(self, line): ''' 向所有被記錄用戶端發送最新內容 ''' for callabler in self.w_register: callabler.write_message(json.dumps(line))class ReceiveNewLinesHandler(BaseHandler): ''' 接受伺服器端指令碼提交的最新行內容 ''' def post(self, *args, **kwargs): linesdata = self.get_argument('lines', '') #print type(json.loads(linesdata)) ProStatus().makelines(json.loads(linesdata))
#-*-coding:utf-8-*-__author__ = 'zhouwang'import timeimport urllibimport urllib2import jsonp = 0while True: f = open('logs.txt', 'r+') f.seek(p, 0) #位移到上次結束位置 lines = f.readlines() if lines: #對行內容操作, 向伺服器發送最新行內容 data = urllib.urlencode({'lines':json.dumps(lines)}) url = 'http://localhost:8800/logs/newlinesforserver/' req = urllib2.Request(url, data) res_data = urllib2.urlopen(req) #print res_data.read() #擷取當前位置,作為位移值 p = f.tell() f.close() time.sleep(1)
ps: 遍曆大記錄檔,及過濾行內容請參考:http://www.cnblogs.com/wowoo1121/p/5381971.html