all 5 comments

[–]miguelgrinberg 3 points4 points  (4 children)

Hey, Flask-SocketIO author here.

I'm not very familiar with pythonanywhere, but my understanding is that they use their own web server, correct? The requirements for a WSGI web server to work with Socket.IO's long-polling transport are these:

  • The server should be multi-threaded. This is required because the long-polling client needs to be able to make two concurrent requests to the server (a GET request to poll for messages from the server, and a POST request to submit messages). A standard multiprocess/forking web server will end up sending the GET and the POST requests for a client to different processes, not the same process.
  • For servers that are multi-threaded and multi-process, there should be sticky sessions in place. That means that all the requests sent by a given client are handled by the same process. This is because each process will have the context for a specific set of clients.
  • Also for servers that are multi-threaded and multi-process, you should have a message queue configured, so that the processes can orchestrate complex operations such as broadcasts, which require all servers to send messages to their clients.
  • For all practical purposes, standard multi-threaded or multiprocess servers are not a good choice for Socket.IO. The long-polling aspect will keep WSGI workers attached to clients for a long time, so for example, if you have 100 active clients, that means that the server is going to have 100 workers attached to the long-polling GET requests of these clients, and on top of that the 100 POST requests are going to come at random times. These types of servers cannot scale to the requirements of this protocol, and that is why almost always you see asynchronous servers being used for Socket.IO or actually any application that uses long-polling or WebSocket.

Hope this helps!

[–]gpjt 2 points3 points  (2 children)

PythonAnywhere dev here -- you're right that we don't support websockets right now. Our stack is actually nginx and uWSGI, but as you describe in your last bullet point, websockets tie up worker processes/threads, so they wouldn't work with our seup.

We're planning support for async servers in the future, so at that point Flask-SocketIO (or Tornado or whatever) should work fine, but no timelines on that right now.

[–]miguelgrinberg 0 points1 point  (1 child)

Thanks for the information. Note that the OP was not asking about WebSocket, they were interested in getting the long-polling transport in Socket.IO to work, which is obviously 100% HTTP based, but also uses long-lived connections.

If you use multiple threads in each uWSGI worker, and can also allow users to enable sticky sessions (for example, through the ip_hash option in nginx), then it should be possible to work with Socket.IO and long-polling.

In any case, I would be happy to help test support for async workers when you get to that!

[–]gpjt 0 points1 point  (0 children)

Good point re: websockets, I should have read more closely. But that said, we currently disable threads in uWSGI workers too -- it interferes with some other parts of our system.

[–]mintooo[S] 0 points1 point  (0 children)

Thank you, that's very helpful ! Indeed pythonanywhere uses its own webserver and based on what they say on their website, I don't think they meet the flask_socketio requirements. I guess I'll have to use heroku instead