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 提供此解决方案!
背景
我正在使用 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 提供此解决方案!