2013-12-09 58 views
0

我正在用Flask框架,WSGIServer和geventwebsockets編寫一個Python web應用程序。服務實時數據python web應用程序

我有一個線程池的工作人員正在進行繁重的處理工作,然後將完成的數據插入MongoDB數據庫。我希望能夠在現場顯示來自MongoDB的實時新數據流。

我目前做的是開放與客戶端連接和查詢的MongoDB爲每3秒新數據的套接字如下所示:

from flask import Flask 
from flask_sockets import Sockets 
import datetime 

app = Flask(__name__) 
sockets = Sockets(app) 

@sockets.route('/echo') 
def echo_socket(ws): 
    last_tweet_printed = datetime.datetime.utcnow() - datetime.timedelta(seconds=55) #start printing tweets from 1 minute ago until catch up. 
    while True: 
     from database_functions import DatabaseFunctions 
     import time 
     databaseFunctions = DatabaseFunctions() 
     tweets = databaseFunctions.loadTweets() # pulls latest tweets from database (all tweets from last 1 minute) 

     limit = 5 # max to print out at once to browser 
     index = 0 

     for tweet in tweets: 
      if(limit != index): 

       if(last_tweet_printed < tweet[u'created_at']): #if the last tweet is older than the one we just pulled... 
        last_tweet_printed = tweet[u'created_at'] #update the latest tweet from db... 
        tweet_text = tweet[u'text'] 

        ws.send("<font color=\"blue\">"+tweet_text + "</font><br> <font color=\"red\">" + str(last_tweet_printed) + "</font><br>") 

       else: 
        print('no new tweets in database, wait till next poll.\n') 

       index+=1 
      else: 
       break 

     print('sleeping...\n') 
     time.sleep(3) #sleep for 3 seconds before polling mongoDB again. 



@app.route('/') 
def hello(): 
    return \ 
''' 
<html> 
    <head> 
     <title>Test Real-Time</title> 
     <script type="text/javascript"> 
      var ws = new WebSocket("ws://" + location.host + "/echo"); 
      ws.onmessage = function(evt){ 
        var received_msg = evt.data; 
        document.getElementById('mark_test').innerHTML += "Tweet: "+received_msg+"<br>"; 

        //alert(received_msg); 
      }; 

      ws.onopen = function(){ 
       ws.send("hello Mark!"); 
      }; 
     </script> 

    </head> 

    <body> 
     <h1>Real Time Stream:</h1> 
     <div id="mark_test"> 

     </div> 
    </body> 

</html> 
''' 


if __name__ == '__main__': 
    from gevent import pywsgi 
    from geventwebsocket.handler import WebSocketHandler 
    server = pywsgi.WSGIServer(('', 5000), app, handler_class=WebSocketHandler) 
    server.serve_forever() 

與這一直途中有任何限制書面?是否有更有效/最佳實踐的替代方案可以爲用戶帶來更加無縫的流?我希望應用程序能夠處理更多的數據庫請求。

回答

2

您的方法有兩個問題。一個,連接到這個Flask服務器的每個客戶端分別輪詢數據庫,所以如果你有100個客戶端連接,你每3秒做100個查詢。最好有一個後臺線程每3秒輪詢一次數據庫,並更新其他線程。 echo_socket可能會在每次更新後由後臺線程通知的全局Condition變量上等待。

您的代碼的另一個問題是,當您可以長時間輪詢時,您正在輪詢MongoDB。長輪詢可以讓您在到達數據庫的消息和將消息廣播給用戶之間獲得更低的延遲,它將減少服務器上的負載,。考慮Rick Copeland's blog post on MongoDB pub/sub的靈感。

相關問題