Flask + gevent 服务器在更新 HTML element/using socketio 时比 Flask 开发服务器慢

Flask + gevent server slower at updating HTML element/using socketio than flask development server

背景

我正在使用 flask/python 制作网络仪表板。我程序的主要任务是一个循环,每 3 秒向我的 index.html 中的 javascript 脚本发送一些信息(通过 flask-socketio)。 javascript 使用 socketio 不断地监听这个信息,当它收到它时,它更新一个 HTML 元素来显示新数据,使用 ajax/jquery 只重新加载相关的 div.

问题

当您启动 flask 时,它会警告您默认的 flask 服务器是“仅供开发使用的开发服务器”。所以我开始使用 gevent,但这有一个奇怪的副作用: 网页在更新 HTML 元素时变慢了,即使 js 确实通过 socketio 接收消息,因为它正在打印我制作的 console.log 消息。

烧瓶开发服务器运行良好;它会每 3 秒更新一次 HTML 元素。但是当我切换到 gevent 时,更新之间开始出现随机间隙,而不是所需的 3s。它会做一些随机的事情,比如在某些时候有 2 秒的间隔,然后是 10 秒,然后是 5 秒,等等。

代码

main.py

from flask import Flask, render_template
from flask_socketio import SocketIO, emit
import threading
import time
from queue import Queue
import random

app = Flask(__name__)
socket = SocketIO(app)

def main():
    q = Queue()
    threading.Thread(target=update_dash, args=(q,), daemon=True).start() #thread for updating the dash

    threading.Thread(target=gen_numbers, args=(q,), daemon=True).start()  #threading for the flask application

    socket.run(app, host="0.0.0.0")


def gen_numbers(q):
    while True:
        time.sleep(3)

        print("----------------------")
        print("sending to update_dash")

        x = random.randint(1, 100)
        q.put(x) #send the data to the update_dash thread



def update_dash(q):
    while True:
        if not q.empty(): #received some data from main()
            data = q.get() #retrieve the data that main() sent
            msg = f"random number sent by main thread: {data}"

            print("sending data to the socket")
            socket.emit("update", msg, broadcast=True)
            print("data sent!")

        time.sleep(0.5)


@app.route("/")
def index():
    return render_template("index.html")

if __name__ == "__main__":
    main()

index.html

<!doctype html>
<html>
  <head>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.4.1/socket.io.js"></script>
    <script type="text/javascript" language="javascript">

      $(document).ready(function() {
        var socket = io.connect("http://" + document.domain + ":" + location.port);

        socket.on("connect", function() {
          console.log("connected");
        });

        socket.on("update", function(msg) {
          console.log("received");
          $("#main").text(msg);
        });
      });

    </script>
  </head>

  <body>
    <div id="main">
        initial message, will be updated every 3s by the js script
    </div>
  </body>

</html>

我研究了这个问题,我发现一个答案建议如果你没有安装 gevent-websockets(以及 gevent 本身),网页将使用轮询而不是 websocket 协议。但是我试过了,但我仍然遇到同样的问题。 (我也试过安装 gevent-eventemitter)

谁能告诉我为什么gevent会导致页面更新时断时续、慢,不胜感激

谢谢

我通过添加

解决了这个问题
from gevent import monkey
monkey.patch_all()

在我的程序的最开始。

感谢@Miguel Grinberg 提供此解决方案!