为python web应用程序提供实时数据服务

为python web应用程序提供实时数据服务,python,mongodb,sockets,flask,gevent,Python,Mongodb,Sockets,Flask,Gevent,我正在用Flask框架、WSGIServer和geventwebsockets编写一个pythonweb应用程序 我有一个线程池,工作人员在做繁重的处理工作,然后将完成的数据插入MongoDB数据库。我希望能够向站点上的用户显示来自MongoDB的实时新数据流 目前我所做的是打开一个套接字与客户端连接,并每隔3秒轮询MongoDB以获取新数据,如下所示: from flask import Flask from flask_sockets import Sockets import dateti

我正在用Flask框架、WSGIServer和geventwebsockets编写一个pythonweb应用程序

我有一个线程池,工作人员在做繁重的处理工作,然后将完成的数据插入MongoDB数据库。我希望能够向站点上的用户显示来自MongoDB的实时新数据流

目前我所做的是打开一个套接字与客户端连接,并每隔3秒轮询MongoDB以获取新数据,如下所示:

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()
从烧瓶导入烧瓶
从U形插座导入插座
导入日期时间
app=烧瓶(名称)
套接字=套接字(应用程序)
@sockets.route(“/echo”)
def回波_插座(ws):
last_tweet_printed=datetime.datetime.utcnow()-datetime.timedelta(秒=55)#从1分钟前开始打印tweet,直到赶上。
尽管如此:
从数据库函数导入数据库函数
导入时间
databaseFunctions=databaseFunctions()
tweets=databaseFunctions.loadTweets()#从数据库中提取最新的推文(过去1分钟的所有推文)
限制=5#可立即打印到浏览器的最大值
索引=0
对于推文中的推文:
如果(限制!=索引):
if(last_tweet_printed“+str(上次打印的tweet\u)+”
”) 其他: print('数据库中没有新的tweet,等待下次轮询。\n') 指数+=1 其他: 打破 打印('休眠…\n') 时间。睡眠(3)#再次轮询mongoDB之前,先睡眠3秒钟。 @应用程序路径(“/”) def hello(): 返回\ ''' 实时测试 var ws=newwebsocket(“ws://“+location.host+”/echo”); ws.onmessage=函数(evt){ 收到的var_msg=evt.data; document.getElementById('mark_test')。innerHTML+=“Tweet:“+received_msg+”
”; //警报(收到消息); }; ws.onopen=函数(){ 发送(“你好,马克!”); }; 实时流: ''' 如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu': 从gevent导入pywsgi 从geventwebsocket.handler导入WebSocketHandler server=pywsgi.WSGIServer(“”,5000),app,handler\u class=WebSocketHandler) 服务器。永远为您服务()

写这篇文章的方式有什么限制吗?是否有更高效/最佳实践的替代方案可以为用户提供更无缝的流?我希望应用程序能够处理更多对数据库的请求。

您的方法存在两个问题。第一,连接到此Flask服务器的每个客户端分别轮询数据库,因此,如果连接了100个客户端,则每3秒执行100次查询。最好让一个后台线程每3秒轮询一次数据库,并更新其他线程
echo_socket
可以在每次更新后等待后台线程通知的全局变量

代码的另一个问题是短轮询MongoDB,而这可能是长轮询。长轮询将降低消息到达数据库和向用户广播消息之间的延迟,将减少服务器上的负载。考虑灵感。