0

I'm setting up a socket.io server, and we have several background threads that call long, blocking methods which poll data. We also want to emit data to the socket.io client from these threads. We were running into issues where these threads would emit something and it would take forever for it to be pushed to clients, until we switched to async_mode='threading'. Then everything worked perfectly, except we now get the warning:

WebSocket transport not available. Install eventlet or gevent and gevent-websocket for improved performance.

These modules are installed, but not being used when using threading mode. How can we have both background threads that always run and don't call socketio.sleep, while at the same time using Websocket transport instead of threading? Thanks

C. Dill
  • 1
  • 1
  • 2

1 Answers1

4

I'm the author of Flask-SocketIO and the Socket.IO server on which it is built.

The short answer is that you need someone to add standalone support for WebSocket to the python-engineio package, one of the core dependencies of Flask-SocketIO.

Here is the long answer. A WebSocket server based on standard threads is in general a bad idea, that is why I have never implemented it myself. WebSocket servers are very demanding, because they require a permanent connection with each client. If you have 100 connected clients, then you need 100 active connections. In a threaded server, that means you need 100 threads all running concurrently, and for a potentially long time. Unfortunately the number of threads you can have in a Python process is somewhat limited. You can probably have 100, but 1000 might be a challenge. Pretty much all WebSocket implementations use asynchronous servers, because this type of server can easily maintain a high number of active connections.

Hopefully that gives you the justification for why I have never implemented WebSocket for threads. With that said, for servers that have low client numbers a thread per client might be okay, so I'm open to add this functionality if someone decides to implement it and contribute it.

Miguel Grinberg
  • 65,299
  • 14
  • 133
  • 152
  • Thank you for your thoughtful response. It is not necessarily important that we have one thread per client, but we want to always have a few threads polling data in the background and then emitting results to every client. Is there some way to use eventlet or gevent but still have other threads that aren't tied into the event loop? Could we tell socketio to read from a queue that other threads write to, and periodically emit data from that queue? Do we have to use an external dependency like Redis? Thanks – C. Dill May 16 '19 at 20:03
  • Communication between the eventlet thread and other threads is hard, because for that to be effective it needs to be done in a non-blocking way. Eventlet supports having a pool of worker threads where jobs can be sent. See https://eventlet.net/doc/threading.html for more information on this feature. – Miguel Grinberg May 17 '19 at 17:23