使用場景
在web開發(fā)中有時候需要實時獲取數(shù)據(jù),可以采用的方法也很多,比如ajax輪詢,長連接等。之前項目中有一個需求是實時的日志展示,實時性要求高
還有根據(jù)歷史監(jiān)控數(shù)據(jù)進行趨勢圖的繪制,數(shù)據(jù)量巨大,等待時間長。那么如果使用http請求來處理則面臨著超時的問題,如果用ajax頻繁的輪詢將對服務器造成很大的壓力。websocket提供了客戶端和服務器進行雙向?qū)崟r的全雙工通信的方法。并且絕大多數(shù)現(xiàn)代瀏覽器都支持websocket,因此需要使用nginx對websocket服務進行反代和負載均衡,nginx從1.3版本后開始支持websocket。項目用到的tornado框架也原生支持websocket,看來可以嘗試用websocket來嘗試解決問題。
Tornado的支持
tornado對websocket支持的很好,通過繼承tornado.websocket.WebSocketHandler類就可以實現(xiàn)對websocket連接的處理。websocket是在標準
http上實現(xiàn)的,websocket中的握手和http中的握手兼容,它使用http中的Upgrade協(xié)議頭將連接從http升級到WebSocket,從源碼上可以看出
WebSocketHandler繼承了tornado.web.RequestHandler,因此websocket也可以通過get_argument方法獲取ws://URL?**=傳來的參數(shù)。
WebSocketHandler提供了一系列方法用以處理連接和消息收發(fā),源碼中的docstring描述得很清楚,源碼是最好的文檔沒有之一。
class WebSocketHandler(tornado.web.RequestHandler):
"""Subclass this class to create a basic WebSocket handler.
Override `on_message` to handle incoming messages, and use
`write_message` to send messages to the client. You can also
override `open` and `on_close` to handle opened and closed
connections.
See http://dev.w3.org/html5/websockets/ for details on the
JavaScript interface. The protocol is specified at
http://tools.ietf.org/html/rfc6455.
Here is an example WebSocket handler that echos back all received messages
back to the client:
.. testcode::
class EchoWebSocket(tornado.websocket.WebSocketHandler):
def open(self):
print("WebSocket opened")
def on_message(self, message):
self.write_message(u"You said: " + message)
def on_close(self):
print("WebSocket closed")
.. testoutput::
:hide:
...
Nginx配置反向代理和負載均衡
upstream tornadoes {
server 127.0.0.1:7000;
server 127.0.0.1:7001;
}
server {
listen 8000;
server_name ***.com;
location / {
proxy_pass http://tornadoes;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}
nginx默認采用循環(huán)的方式分配請求,循環(huán)的將請求分配到upstream中定義的服務地址。location中的定義對支持websocket必不可少。