1. 程式人生 > >DJANGO 實時系統的另類實現

DJANGO 實時系統的另類實現

http://scriptogr.am/pison/post/django-

概述

基於Tornado, Redis, Django, SSE協議 實現Django的實時通訊系統

緣起

業務上要求能夠實現一旦伺服器收到警報,立刻將資訊反饋到頁面——簡單地說,就是彈框加BIBI聲。

角色

由於Django不支援非同步,所以本質上是無法滿足實時的要求——他一個請求進來是block住的,直到任務完成才返回。 即使是用uwsgi技術,也只能將可處理的執行緒支撐到兩位數以下。

Tornado天生支援非同步,當然也可以用Flask。

聽Alex Maccaw說SSE( Server-Sent Events)比Websocket更好。舉個簡單的例子,SSE不需要特殊的協議支援,因為它是基於傳統的HTTP,而Websocket則是需要full-duplex connections。其次Websocket缺少一些工程設計,而SSE能夠設定自動重新連線, 事件ID, 和傳送結構化資料。 更多的資訊,可以參考

Stream Updates with Server-Sent Events Killing a library(用ruby實現了SSE,略簡單)

迫於工程專案的緊急性,只能找現成的輪子——今天的主角Tornado-sse

需要的安裝Django-sse(Django內傳送資訊到redis), sse(將資訊處理成符合sse標準的包), redis(Django和Tornado通訊)。

步驟

在Django的setting檔案中新增

### SSE ###
INSTALLED_APPS += (
'redis',
'django_sse',
'tornado_sse',
)

REDIS_SSEQUEUE_CONNECTION_SETTINGS = {
'location': 'localhost:6379',
'db': 0,
}
### SSE ###

在tasks.py檔案(就是你用來執行任務的檔案)

from django_sse.redisqueue import send_event
def notify(message):

    info = json.dumps({
    'type': 'foo',
    'html': message,
    })

    send_event('message', info, 'sse') # 預設頻道
    return True
當然我建議將這個函式設定為signal觸發

在base.html中加入

    <head>
    <script type="text/javascript" src="{{ STATIC_URL }}tornado_sse/jquery.eventsource.js"></script>
    <script type="text/javascript" src="{{ STATIC_URL }}tornado_sse/sse.js"></script>
    </head>

<body sse-data="/sse/">
</body>
如果是本地的話,需要修改為127.0.0.1:8888/

伺服器環境如果是Apache

    <Location /sse>
    ProxyPass http://localhost:8888
    </Location>

如果是nginx:

    location /sse/ {
    rewrite                 ^(.*)$ / break; # to root of our tornado
    proxy_buffering         off; # to push immediately
    proxy_pass              http://127.0.0.1:8888;
}

最後啟動:

  1. redis: nohup redis-server &
  2. django:python manage.py runserver
  3. python server.py (服務端可以用supervisord控制tornado服務)

補充

因為專案原先採用RabbitMQ來做資訊分發、Celery任務執行,不過因為時間不夠,只能臨時先用redis頂著。 如果是RabbitMQ,就需要用Pika來實現具體參考

以上也只利用SSE獲取通知,並有深入的處理資訊和按頻道分發——後面會增加按團隊來分發通知的功能。Tornado-sse的原始碼很短,各位可以細細讀讀,機制和Websocket的實現是類似的,基於事件嘛。