简体   繁体   中英

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

Background

I'm making a web dashboard with flask/python. My program's main task is a loop that sends some information to a javascript script in my index.html (through flask-socketio), every 3 seconds. The javascript uses socketio to constantly listen for this info, and when it receives it, it updates an HTML element to show the new data, using ajax/jquery to only reload the relevant div.

Issue

When you start flask it warns you that the default flask server is "a development server for development use only". So I started using gevent, but this had a weird side effect: the webpage became slow at updating the HTML element, even though the js was definitely receiving the messages through socketio, as it was printing the console.log messages I made it do.

The flask development server worked fine; it would update the HTML element every 3 seconds as it should. But when I switched to gevent, there started being random gaps between the updates, instead of the required 3s. It would do random things like having a gap of 2 seconds at some points but then 10 seconds, and then 5 seconds, etc.

Code

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>

I have researched this problem, and an answer I found suggested that the webpage will use polling instead of websocket protocol if you don't have gevent-websockets installed (as well as gevent itself). However I tried this but I'm still getting the same issues. (I also tried installing gevent-eventemitter too)

If anyone can tell me why gevent makes the page updates sporadic and slow, i would be very grateful

Thank you

I solved this by adding

from gevent import monkey
monkey.patch_all()

at the very start of my program.

Thank you to @Miguel Grinberg for this solution!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM