Flask-socketio: socketio hangs after 250 concurrent connections

Created on 14 Sep 2017  路  15Comments  路  Source: miguelgrinberg/Flask-SocketIO

I have an application utilizing socket.io. At one point it started hanging under a slightly increased load. Only websocket traffic going on is the PING-PONG, http requests get timed out. I haven't reached this problem when disabling websocket and forcing polling. However, then a part of my app that has quite heavy websocket traffic, get super slow and kind of freezes for half a minute or a minute. This could be related to the original problem.

I managed to replicate the bug by simply opening aroudn 250 connections from my browser.

Client side code. The following equates to making 500 connections during 250 seconds. The freeze happens at around 250 connections.

for (var i = 0; i<500; i++) {
    (function (index) {
        setTimeout(function () {
            console.log(index)
            var client_socket = io.connect('URL/client', {'path': '/test_socket.io'});
            client_socket.on('connect', function(data) {
                console.log('client connected')
            });
        }, index * 500);
    })(i);
}

Server side code:

@socketio.on('connect', namespace='/client')
def client_connect():
    sid = request.sid
    connected_client_sids.add(sid)
    log.info('connected clients count {}'.format(len(connected_client_sids)))
    emit('helpdesk status', helpdesk_status())

Server side logs

INFO 2017-09-11 15:46:04,857 client_connect views.py connected clients count 254
INFO 2017-09-11 15:46:04,857 emit         server.py emitting event "helpdesk status" to eb29a1d7e31f4de3b9d4120e496e6f5c [/client]
INFO 2017-09-11 15:46:04,857 send         socket.py eb29a1d7e31f4de3b9d4120e496e6f5c: Sending packet MESSAGE data 2/client,["helpdesk status",[{"category":"billing","segment":"private","langu
age":"et"}]]
INFO 2017-09-11 15:46:04,857 send         socket.py eb29a1d7e31f4de3b9d4120e496e6f5c: Sending packet MESSAGE data 0/client
INFO 2017-09-11 15:46:04,867 send         socket.py c60470765bfc4adb95a57389da09de34: Sending packet NOOP data None
INFO 2017-09-11 15:46:04,880 handle_get_request socket.py ce855ceca9814045bfc2b840be13baf9: Received request to upgrade to websocket
INFO 2017-09-11 15:46:04,881 _websocket_handler socket.py d3cc9b7dfa5548c18a6c8b836f05a3aa: Upgrade to websocket successful
INFO 2017-09-11 15:46:04,902 send         socket.py ff00fbf2859b4cc5b105b65dc4452e8d: Sending packet OPEN data {'sid': 'ff00fbf2859b4cc5b105b65dc4452e8d', 'pingInterval': 25000, 'pingTimeout'
: 60000, 'upgrades': ['websocket']}
INFO 2017-09-11 15:46:04,903 send         socket.py ff00fbf2859b4cc5b105b65dc4452e8d: Sending packet MESSAGE data 0
INFO 2017-09-11 15:46:04,914 receive      socket.py 8d01079b60964c779c962f51885b3134: Received packet PING data None
INFO 2017-09-11 15:46:04,914 send         socket.py 8d01079b60964c779c962f51885b3134: Sending packet PONG data None
INFO 2017-09-11 15:46:04,917 _websocket_handler socket.py c60470765bfc4adb95a57389da09de34: Upgrade to websocket successful
INFO 2017-09-11 15:46:04,920 send         socket.py ce855ceca9814045bfc2b840be13baf9: Sending packet NOOP data None
INFO 2017-09-11 15:46:04,936 handle_get_request socket.py eb29a1d7e31f4de3b9d4120e496e6f5c: Received request to upgrade to websocket
INFO 2017-09-11 15:46:04,947 receive      socket.py ff00fbf2859b4cc5b105b65dc4452e8d: Received packet MESSAGE data 0/client,
INFO 2017-09-11 15:46:04,947 client_connect views.py connected clients count 255
INFO 2017-09-11 15:46:04,947 emit         server.py emitting event "helpdesk status" to ff00fbf2859b4cc5b105b65dc4452e8d [/client]
INFO 2017-09-11 15:46:04,947 send         socket.py ff00fbf2859b4cc5b105b65dc4452e8d: Sending packet MESSAGE data 2/client,["helpdesk status",[{"category":"billing","segment":"private","langu
age":"et"}]]
INFO 2017-09-11 15:46:04,948 send         socket.py ff00fbf2859b4cc5b105b65dc4452e8d: Sending packet MESSAGE data 0/client
INFO 2017-09-11 15:46:04,948 _websocket_handler socket.py ce855ceca9814045bfc2b840be13baf9: Upgrade to websocket successful
INFO 2017-09-11 15:46:04,955 send         socket.py eb29a1d7e31f4de3b9d4120e496e6f5c: Sending packet NOOP data None
INFO 2017-09-11 15:46:04,992 _websocket_handler socket.py eb29a1d7e31f4de3b9d4120e496e6f5c: Upgrade to websocket successful
INFO 2017-09-11 15:46:05,008 send         socket.py 32bd5a9001e147759f72e2690945892b: Sending packet OPEN data {'sid': '32bd5a9001e147759f72e2690945892b', 'pingInterval': 25000, 'pingTimeout'
: 60000, 'upgrades': ['websocket']}
INFO 2017-09-11 15:46:05,008 send         socket.py 32bd5a9001e147759f72e2690945892b: Sending packet MESSAGE data 0
INFO 2017-09-11 15:46:05,036 receive      socket.py 32bd5a9001e147759f72e2690945892b: Received packet MESSAGE data 0/client,
INFO 2017-09-11 15:46:05,037 client_connect views.py connected clients count 256
INFO 2017-09-11 15:46:05,037 emit         server.py emitting event "helpdesk status" to 32bd5a9001e147759f72e2690945892b [/client]
INFO 2017-09-11 15:46:05,037 send         socket.py 32bd5a9001e147759f72e2690945892b: Sending packet MESSAGE data 2/client,["helpdesk status",[{"category":"billing","segment":"private","langu
age":"et"}]]
INFO 2017-09-11 15:46:05,037 send         socket.py 32bd5a9001e147759f72e2690945892b: Sending packet MESSAGE data 0/client
INFO 2017-09-11 15:46:05,052 receive      socket.py cdacf614f7114eaeba0e4eddc2fc9ca7: Received packet PING data None
INFO 2017-09-11 15:46:05,052 send         socket.py cdacf614f7114eaeba0e4eddc2fc9ca7: Sending packet PONG data None
INFO 2017-09-11 15:46:05,211 send         socket.py 112fa78735644b1ab5a93a06cda38b35: Sending packet OPEN data {'sid': '112fa78735644b1ab5a93a06cda38b35', 'pingInterval': 25000, 'pingTimeout'
: 60000, 'upgrades': ['websocket']}
INFO 2017-09-11 15:46:05,211 send         socket.py 112fa78735644b1ab5a93a06cda38b35: Sending packet MESSAGE data 0
INFO 2017-09-11 15:46:05,238 receive      socket.py 112fa78735644b1ab5a93a06cda38b35: Received packet MESSAGE data 0/client,
INFO 2017-09-11 15:46:05,239 client_connect views.py connected clients count 257
INFO 2017-09-11 15:46:05,239 emit         server.py emitting event "helpdesk status" to 112fa78735644b1ab5a93a06cda38b35 [/client]
INFO 2017-09-11 15:46:05,239 send         socket.py 112fa78735644b1ab5a93a06cda38b35: Sending packet MESSAGE data 2/client,["helpdesk status",[{"category":"billing","segment":"private","langu
age":"et"}]]
INFO 2017-09-11 15:46:05,239 send         socket.py 112fa78735644b1ab5a93a06cda38b35: Sending packet MESSAGE data 0/client
INFO 2017-09-11 15:46:05,249 receive      socket.py 3cc020e944f941afa97db91b4d921c88: Received packet PING data None
INFO 2017-09-11 15:46:05,250 send         socket.py 3cc020e944f941afa97db91b4d921c88: Sending packet PONG data None
INFO 2017-09-11 15:46:05,382 receive      socket.py 3756ecb991434d4bbf94a4515a7afb45: Received packet PING data None
INFO 2017-09-11 15:46:05,382 send         socket.py 3756ecb991434d4bbf94a4515a7afb45: Sending packet PONG data None
INFO 2017-09-11 15:46:05,383 receive      socket.py 22bf1e6e5fc54db087944b03caeabd1a: Received packet PING data None
INFO 2017-09-11 15:46:05,383 send         socket.py 22bf1e6e5fc54db087944b03caeabd1a: Sending packet PONG data None
INFO 2017-09-11 15:46:05,386 receive      socket.py 006cff65347d467c880e2049e9ffb541: Received packet PING data None
INFO 2017-09-11 15:46:05,386 send         socket.py 006cff65347d467c880e2049e9ffb541: Sending packet PONG data None
INFO 2017-09-11 15:46:05,425 send         socket.py 240c096dbfb74453ac792806c2f45289: Sending packet OPEN data {'sid': '240c096dbfb74453ac792806c2f45289', 'pingInterval': 25000, 'pingTimeout'
: 60000, 'upgrades': ['websocket']}
INFO 2017-09-11 15:46:05,425 send         socket.py 240c096dbfb74453ac792806c2f45289: Sending packet MESSAGE data 0
INFO 2017-09-11 15:46:05,452 receive      socket.py 240c096dbfb74453ac792806c2f45289: Received packet MESSAGE data 0/client,
INFO 2017-09-11 15:46:05,453 client_connect views.py connected clients count 258
INFO 2017-09-11 15:46:05,453 emit         server.py emitting event "helpdesk status" to 240c096dbfb74453ac792806c2f45289 [/client]
INFO 2017-09-11 15:46:05,453 send         socket.py 240c096dbfb74453ac792806c2f45289: Sending packet MESSAGE data 2/client,["helpdesk status",[{"category":"billing","segment":"private","langu
age":"et"}]]
INFO 2017-09-11 15:46:05,453 send         socket.py 240c096dbfb74453ac792806c2f45289: Sending packet MESSAGE data 0/client
INFO 2017-09-11 15:46:05,473 receive      socket.py a7fbdfbf105249ec8c69c1fcf0770335: Received packet PING data None
INFO 2017-09-11 15:46:05,473 send         socket.py a7fbdfbf105249ec8c69c1fcf0770335: Sending packet PONG data None
INFO 2017-09-11 15:46:05,483 receive      socket.py 9c66a3f3548247409f2e076932890587: Received packet PING data None
INFO 2017-09-11 15:46:05,483 send         socket.py 9c66a3f3548247409f2e076932890587: Sending packet PONG data None
INFO 2017-09-11 15:46:05,591 receive      socket.py 5b8982018b0240dba541047cfa60ba7b: Received packet PING data None
INFO 2017-09-11 15:46:05,591 send         socket.py 5b8982018b0240dba541047cfa60ba7b: Sending packet PONG data None
INFO 2017-09-11 15:46:05,609 send         socket.py 2a0f96f1c28f42ef95477674f307d91a: Sending packet OPEN data {'sid': '2a0f96f1c28f42ef95477674f307d91a', 'pingInterval': 25000, 'pingTimeout'
: 60000, 'upgrades': ['websocket']}
INFO 2017-09-11 15:46:05,609 send         socket.py 2a0f96f1c28f42ef95477674f307d91a: Sending packet MESSAGE data 0
INFO 2017-09-11 15:46:05,646 receive      socket.py 2a0f96f1c28f42ef95477674f307d91a: Received packet MESSAGE data 0/client,
INFO 2017-09-11 15:46:05,647 client_connect views.py connected clients count 259
INFO 2017-09-11 15:46:05,647 emit         server.py emitting event "helpdesk status" to 2a0f96f1c28f42ef95477674f307d91a [/client]
INFO 2017-09-11 15:46:05,647 send         socket.py 2a0f96f1c28f42ef95477674f307d91a: Sending packet MESSAGE data 2/client,["helpdesk status",[{"category":"billing","segment":"private","langu
age":"et"}]]
INFO 2017-09-11 15:46:05,647 send         socket.py 2a0f96f1c28f42ef95477674f307d91a: Sending packet MESSAGE data 0/client
INFO 2017-09-11 15:46:05,648 receive      socket.py 95f70f0437884fb795d976d1161a8cf6: Received packet PING data None
INFO 2017-09-11 15:46:05,648 send         socket.py 95f70f0437884fb795d976d1161a8cf6: Sending packet PONG data None
INFO 2017-09-11 15:46:05,657 receive      socket.py 9f39495052a04b2da3cd945d468884d2: Received packet PING data None
INFO 2017-09-11 15:46:05,658 send         socket.py 9f39495052a04b2da3cd945d468884d2: Sending packet PONG data None
INFO 2017-09-11 15:46:05,806 send         socket.py 8e9d92dbec804abd85df9e48059bce14: Sending packet OPEN data {'sid': '8e9d92dbec804abd85df9e48059bce14', 'pingInterval': 25000, 'pingTimeout'
: 60000, 'upgrades': ['websocket']}
INFO 2017-09-11 15:46:05,806 send         socket.py 8e9d92dbec804abd85df9e48059bce14: Sending packet MESSAGE data 0
INFO 2017-09-11 15:46:05,851 receive      socket.py cc5fbab5c7aa4832a7835cccdcf6a964: Received packet PING data None
INFO 2017-09-11 15:46:05,851 send         socket.py cc5fbab5c7aa4832a7835cccdcf6a964: Sending packet PONG data None
INFO 2017-09-11 15:46:05,851 receive      socket.py 737be393783f496e8d79d77712f03c2e: Received packet PING data None
INFO 2017-09-11 15:46:05,851 send         socket.py 737be393783f496e8d79d77712f03c2e: Sending packet PONG data None
INFO 2017-09-11 15:46:05,852 receive      socket.py 8e9d92dbec804abd85df9e48059bce14: Received packet MESSAGE data 0/client,
INFO 2017-09-11 15:46:05,852 client_connect views.py connected clients count 260
INFO 2017-09-11 15:46:05,853 emit         server.py emitting event "helpdesk status" to 8e9d92dbec804abd85df9e48059bce14 [/client]
INFO 2017-09-11 15:46:05,853 send         socket.py 8e9d92dbec804abd85df9e48059bce14: Sending packet MESSAGE data 2/client,["helpdesk status",[{"category":"billing","segment":"private","langu
age":"et"}]]
INFO 2017-09-11 15:46:05,853 send         socket.py 8e9d92dbec804abd85df9e48059bce14: Sending packet MESSAGE data 0/client
INFO 2017-09-11 15:46:06,054 receive      socket.py b9157310770e4863b163901fde6f9bd8: Received packet PING data None
INFO 2017-09-11 15:46:06,054 send         socket.py b9157310770e4863b163901fde6f9bd8: Sending packet PONG data None
INFO 2017-09-11 15:46:06,081 receive      socket.py a4cc2f8f967b4d0499cf53e110b2f3da: Received packet PING data None
INFO 2017-09-11 15:46:06,081 send         socket.py a4cc2f8f967b4d0499cf53e110b2f3da: Sending packet PONG data None
INFO 2017-09-11 15:46:06,197 receive      socket.py d124dd5c8bfb4d3f92873948e4f8cf76: Received packet PING data None
INFO 2017-09-11 15:46:06,197 send         socket.py d124dd5c8bfb4d3f92873948e4f8cf76: Sending packet PONG data None
INFO 2017-09-11 15:46:06,231 receive      socket.py 8120d76ea2144d6bb5e83ca2749696ae: Received packet PING data None
INFO 2017-09-11 15:46:06,231 send         socket.py 8120d76ea2144d6bb5e83ca2749696ae: Sending packet PONG data None
INFO 2017-09-11 15:46:06,251 receive      socket.py 2cc492a3f93e49438204de0a2efa2afd: Received packet PING data None
INFO 2017-09-11 15:46:06,251 send         socket.py 2cc492a3f93e49438204de0a2efa2afd: Sending packet PONG data None
INFO 2017-09-11 15:46:06,432 receive      socket.py f244d00a387544e1a7554c0700294b67: Received packet PING data None
INFO 2017-09-11 15:46:06,432 send         socket.py f244d00a387544e1a7554c0700294b67: Sending packet PONG data None
INFO 2017-09-11 15:46:06,437 receive      socket.py 2c476c7d45e144e083741f15d20ece3a: Received packet PING data None
INFO 2017-09-11 15:46:06,437 send         socket.py 2c476c7d45e144e083741f15d20ece3a: Sending packet PONG data None
INFO 2017-09-11 15:46:06,639 receive      socket.py 2ef3829ed415498a84347f9b2d82fca3: Received packet PING data None
INFO 2017-09-11 15:46:06,639 send         socket.py 2ef3829ed415498a84347f9b2d82fca3: Sending packet PONG data None
INFO 2017-09-11 15:46:06,643 receive      socket.py 62bbbc9f78d74d94b2935ee81a72c8bf: Received packet PING data None
INFO 2017-09-11 15:46:06,643 send         socket.py 62bbbc9f78d74d94b2935ee81a72c8bf: Sending packet PONG data None
INFO 2017-09-11 15:46:06,836 receive      socket.py 23ca0a4d125347a891f30301168726dd: Received packet PING data None
INFO 2017-09-11 15:46:06,836 send         socket.py 23ca0a4d125347a891f30301168726dd: Sending packet PONG data None
INFO 2017-09-11 15:46:06,849 receive      socket.py 93d3e4fda2aa465fa71744e7545c3cbb: Received packet PING data None
INFO 2017-09-11 15:46:06,850 send         socket.py 93d3e4fda2aa465fa71744e7545c3cbb: Sending packet PONG data None
INFO 2017-09-11 15:46:07,042 receive      socket.py 44463b65b3b5445d9b707053250e4c33: Received packet PING data None
INFO 2017-09-11 15:46:07,042 send         socket.py 44463b65b3b5445d9b707053250e4c33: Sending packet PONG data None
INFO 2017-09-11 15:46:07,199 receive      socket.py 80f8e65bdc6746c0b25872b5514c204f: Received packet PING data None
INFO 2017-09-11 15:46:07,200 send         socket.py 80f8e65bdc6746c0b25872b5514c204f: Sending packet PONG data None
INFO 2017-09-11 15:46:07,239 receive      socket.py da8c45032ba4466d97923ee551503c58: Received packet PING data None
INFO 2017-09-11 15:46:07,239 send         socket.py da8c45032ba4466d97923ee551503c58: Sending packet PONG data None
INFO 2017-09-11 15:46:07,395 receive      socket.py 39f5cdaf62c9475793428baa5af628c7: Received packet PING data None
INFO 2017-09-11 15:46:07,395 send         socket.py 39f5cdaf62c9475793428baa5af628c7: Sending packet PONG data None
INFO 2017-09-11 15:46:07,432 receive      socket.py ae7b696155e243edbb4b2fe5d5afd141: Received packet PING data None
INFO 2017-09-11 15:46:07,433 send         socket.py ae7b696155e243edbb4b2fe5d5afd141: Sending packet PONG data None
INFO 2017-09-11 15:46:07,464 receive      socket.py a0346ff8152644c4bf5521d75aff5ca6: Received packet PING data None
INFO 2017-09-11 15:46:07,465 send         socket.py a0346ff8152644c4bf5521d75aff5ca6: Sending packet PONG data None
INFO 2017-09-11 15:46:07,649 receive      socket.py b2fe383335a843afb9f0546785a1ed73: Received packet PING data None
INFO 2017-09-11 15:46:07,650 send         socket.py b2fe383335a843afb9f0546785a1ed73: Sending packet PONG data None
INFO 2017-09-11 15:46:07,663 receive      socket.py c110c9bf03e34d8f86f2894b2b3a537b: Received packet PING data None
INFO 2017-09-11 15:46:07,663 send         socket.py c110c9bf03e34d8f86f2894b2b3a537b: Sending packet PONG data None
INFO 2017-09-11 15:46:07,853 receive      socket.py b9c738e6de344b4eb034701c64979f3a: Received packet PING data None
INFO 2017-09-11 15:46:07,853 send         socket.py b9c738e6de344b4eb034701c64979f3a: Sending packet PONG data None
INFO 2017-09-11 15:46:07,871 receive      socket.py 1818cd0a1a064a45aceffa72741faad7: Received packet PING data None
INFO 2017-09-11 15:46:07,871 send         socket.py 1818cd0a1a064a45aceffa72741faad7: Sending packet PONG data None
INFO 2017-09-11 15:46:08,037 receive      socket.py 5703faaa64a542bb9b53dde876f4c754: Received packet PING data None
INFO 2017-09-11 15:46:08,037 send         socket.py 5703faaa64a542bb9b53dde876f4c754: Sending packet PONG data None
INFO 2017-09-11 15:46:08,056 receive      socket.py f13d8750f7f64863b8c1f6fca71bae0d: Received packet PING data None
INFO 2017-09-11 15:46:08,056 send         socket.py f13d8750f7f64863b8c1f6fca71bae0d: Sending packet PONG data None
INFO 2017-09-11 15:46:08,246 receive      socket.py 1e0a56d30ad0419ba583a034698b4953: Received packet PING data None
INFO 2017-09-11 15:46:08,246 send         socket.py 1e0a56d30ad0419ba583a034698b4953: Sending packet PONG data None
INFO 2017-09-11 15:46:08,284 receive      socket.py cabda4e2305241d3ad6e37b6fb84a1a0: Received packet PING data None
INFO 2017-09-11 15:46:08,285 send         socket.py cabda4e2305241d3ad6e37b6fb84a1a0: Sending packet PONG data None
INFO 2017-09-11 15:46:08,447 receive      socket.py 70d7e866289849f4a2e5e10842a3f53a: Received packet PING data None

Client logs:

socket.io-client:url parse https://URL/client +0ms
socket.io-client new io instance for https://URL/client +2ms
socket.io-client:manager readyState closed +1ms
socket.io-client:manager opening https://URL/client +1ms
engine.io-client:socket creating transport "polling" +1ms
engine.io-client:polling polling +2ms
engine.io-client:polling-xhr xhr poll +1ms
engine.io-client:polling-xhr xhr open GET: https://URL/test_socket.io/?EIO=3&transport=polling&t=Lvm89kF +4ms
engine.io-client:polling-xhr xhr data null +1ms
engine.io-client:socket setting transport polling +2ms
socket.io-client:manager connect attempt will timeout after 20000 +1ms
socket.io-client:manager readyState opening +2ms
socket.io-client:manager connect attempt timed out after 20000 +20s
engine.io-client:socket socket close with reason: "forced close" +1ms
engine.io-client:polling transport not open - deferring close +1ms
engine.io-client:socket socket closing - telling transport to close +0ms
socket.io-client:manager connect_error +1ms
socket.io-client:manager cleanup +0ms
socket.io-client:manager will wait 1298ms before reconnect attempt +1ms
socket.io-client:manager attempting reconnect +1s
socket.io-client:manager readyState closed +1ms
socket.io-client:manager opening https://URL/client +0ms
engine.io-client:socket creating transport "polling" +0ms
engine.io-client:polling polling +1ms
engine.io-client:polling-xhr xhr poll +0ms
engine.io-client:polling-xhr xhr open GET: https://URL/test_socket.io/?EIO=3&transport=polling&t=Lvm8ExG +1ms
engine.io-client:polling-xhr xhr data null +1ms
engine.io-client:socket setting transport polling +1ms
socket.io-client:manager connect attempt will timeout after 20000 +2ms
socket.io-client:manager connect attempt timed out after 20000 +21s
engine.io-client:socket socket close with reason: "forced close" +1ms
engine.io-client:polling transport not open - deferring close +0ms
engine.io-client:socket socket closing - telling transport to close +0ms
socket.io-client:manager connect_error +0ms
socket.io-client:manager cleanup +1ms
socket.io-client:manager reconnect attempt error +0ms
socket.io-client:manager will wait 1185ms before reconnect attempt +0ms
socket.io-client:manager attempting reconnect +2s
socket.io-client:manager readyState closed +1ms
socket.io-client:manager opening https://URL/client +0ms
engine.io-client:socket creating transport "polling" +0ms
engine.io-client:polling polling +1ms
engine.io-client:polling-xhr xhr poll +0ms
engine.io-client:polling-xhr xhr open GET: https://URL/test_socket.io/?EIO=3&transport=polling&t=Lvm8KVO +0ms
engine.io-client:polling-xhr xhr data null +1ms
engine.io-client:socket setting transport polling +1ms
socket.io-client:manager connect attempt will timeout after 20000 +0ms
socket.io-client:manager connect attempt timed out after 20000 +20s
engine.io-client:socket socket close with reason: "forced close" +1ms
engine.io-client:polling transport not open - deferring close +0ms
engine.io-client:socket socket closing - telling transport to close +0ms
socket.io-client:manager connect_error +0ms
socket.io-client:manager cleanup +0ms
socket.io-client:manager reconnect attempt error +1ms
socket.io-client:manager will wait 4274ms before reconnect attempt +0ms
socket.io-client:manager attempting reconnect +4s
socket.io-client:manager readyState closed +1ms
socket.io-client:manager opening https://URL/client +0ms
engine.io-client:socket creating transport "polling" +1ms
engine.io-client:polling polling +1ms
engine.io-client:polling-xhr xhr poll +0ms
engine.io-client:polling-xhr xhr open GET: https://URL/test_socket.io/?EIO=3&transport=polling&t=Lvm8QQx +1ms
engine.io-client:polling-xhr xhr data null +0ms
engine.io-client:socket setting transport polling +1ms
socket.io-client:manager connect attempt will timeout after 20000 +1ms

I have the test and production application on the same server at the moment.

Production had 70 websocket connections, test crashed at 255 connections.
Closed the production app, so it was 0 websocket connections from live, test crashed at 260.
This is indicative of it being an app problem?

The open file limit should not be the problem here:

$ prlimit -p 5212
RESOURCE   DESCRIPTION                             SOFT      HARD UNITS
NOFILE     max number of open files                1024     65536

After the freezing: 

$ lsof -p *ID* | wc -l
474
$ lsof | wc -l
29772

The versions and libraries associated with the project:

eventlet==0.21.0
SQLAlchemy==1.1.13
Flask_Migrate==2.0.4
estnltk==1.4.1.1
pandas==0.19.2
Flask_SQLAlchemy==2.2
alembic==0.9.2
nltk==3.2.2
requests==2.13.0
Flask_Script==2.0.5
Flask_SocketIO==2.8.6
regex==2017.6.23
fuzzywuzzy==0.15.1
Flask==0.12

Monkey patching.

When I run the project, the first line of code is

from project import app, socketio

the first two lines in project module:

import eventlet
eventlet.monkey_patch()

So it should apply, as it should be the first command thing that is run.

question

All 15 comments

Going as basic as possible, the following code and on localhost, I get the same result. I find it hard to believe socket.io supports only 250 concurrent connections. Is there something I'm missing here? Perhaps this kind of debugging does not simulate the real world, and the production behaviour is due to something else?

The following code can be used to replicate the problem at least on my computer.

main.py

from flask import Flask, render_template
from flask_socketio import SocketIO
from flask_socketio import send, emit
from logging.config import fileConfig
import logging

fileConfig('logging.conf')

log = logging.getLogger(__name__)

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app, allow_upgrades=True, engineio_logger=log, logger=log)

@socketio.on('connect')
def test_connect():
    emit('response', {'data': 'Connected'})

if __name__ == '__main__':
    socketio.run(app, debug=True)

test.html

<!DOCTYPE html>
<html>
<head>
    <title>test socket</title>
</head>
<body>

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.slim.js"></script>
<script type="text/javascript" charset="utf-8">
    clients = []
    for (var i = 0; i<500; i++) {
        (function (index) {
            setTimeout(function () {
                console.log(index)
                var client_socket = io.connect('http://localhost:5000');
                client_socket.on('connect', function(data) {
                    console.log('client connected')
                });
                clients.push(client_socket)
            }, index * 300);
        })(i);
    }
</script>
</body>
</html>

logging.conf

[loggers]
keys=root

[handlers]
keys=stream_handler,file_handler

[formatters]
keys=formatter

[logger_root]
level=DEBUG
handlers=stream_handler,file_handler

[handler_stream_handler]
class=StreamHandler
level=DEBUG
formatter=formatter
args=(sys.stdout,)

[handler_file_handler]
class=handlers.TimedRotatingFileHandler
level=INFO
formatter=formatter
args=('bot-api.log', 'D', 7)

[formatter_formatter]
format=%(levelname)s %(asctime)s %(funcName)-12s %(filename)-8s %(message)s

Environment:

$ pipdeptree -p Flask-SocketIO
Flask-SocketIO==2.8.6
  - Flask [required: >=0.9, installed: 0.10.1]
    - itsdangerous [required: >=0.21, installed: 0.24]
    - Jinja2 [required: >=2.4, installed: 2.8]
      - MarkupSafe [required: Any, installed: 1.0]
    - Werkzeug [required: >=0.7, installed: 0.10.4]
  - python-engineio [required: >=1.0.0, installed: 1.5.4]
    - six [required: >=1.9.0, installed: 1.10.0]
  - python-socketio [required: >=1.5.0, installed: 1.7.5]
    - python-engineio [required: >=1.2.1, installed: 1.5.4]
      - six [required: >=1.9.0, installed: 1.10.0]
    - six [required: >=1.9.0, installed: 1.10.0]

Update: the 250 comes from chrome limitation. Cannot do load testing using the browser (or must increase the limit).

Currently stuck at the point, that pure websocket connections go as far as needed, but polling connections get stuck at 1024. So I can get pure websocket connections using the Tornado framework, but socketio requires long polled connections before websocket and fails to go over 1024.

You can do the following to bypass the long-polling connection:

var socket = io.connect(location.origin + '/chat', {transports: ['websocket']});

I'm using Artillery for load testing.
I have a simple Tornado application, enabling a ws:// connection, and a simple flask-socketio application, enabling a socketio connection.

The Tornado app allows for as many websocket connections, as set by ulimit (4096), but the flask-socketio app hangs at 1024. Using either transports method.

Maybe this helps:

flask-socketio

from flask import Flask, render_template
from flask_socketio import SocketIO
from flask_socketio import send, emit
from logging.config import fileConfig
import logging

fileConfig('logging.conf')

log = logging.getLogger(__name__)

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
# socketio = SocketIO(app, allow_upgrades=True, engineio_logger=log, logger=log)
socketio = SocketIO(app, allow_upgrades=True)

connected_clients_count = 0

@socketio.on('connect')
def test_connect():
    global connected_clients_count
    connected_clients_count += 1
    print(connected_clients_count)
    # emit('response', {'data': 'Connected'})

@app.route('/')
def render_load_test():
    return render_template('test-socketio.html')

import resource
if __name__ == '__main__':
    print(resource.getrlimit(resource.RLIMIT_NOFILE))
    socketio.run(app, debug=True)

Tornado

from tornado import websocket, web, ioloop, options
import json

options.define("debug", default=True, help="run in debug mode")

cl = []

class IndexHandler(web.RequestHandler):
    def get(self):
        self.render("tornado-test.html")

class SocketHandler(websocket.WebSocketHandler):
    def check_origin(self, origin):
        return True

    def open(self):
        if self not in cl:
            cl.append(self)
            print(len(cl))

    def on_close(self):
        if self in cl:
            cl.remove(self)

    def on_message(self, message):
        print("got message", message)

class ApiHandler(web.RequestHandler):

    @web.asynchronous
    def get(self, *args):
        self.finish()
        id = self.get_argument("id")
        value = self.get_argument("value")
        data = {"id": id, "value" : value}
        data = json.dumps(data)
        for c in cl:
            c.write_message(data)

    @web.asynchronous
    def post(self):
        pass

app = web.Application([
    (r'/', IndexHandler),
    (r'/ws', SocketHandler),
    (r'/api', ApiHandler),
    (r'/(rest_api_example.png)', web.StaticFileHandler, {'path': './'}),
], debug=True)

if __name__ == '__main__':
    print(1234)
    app.listen(8888)
    ioloop.IOLoop.instance().start()

Artillery YAML files
tornado

config:
  target: "ws://localhost:8888/ws"
  phases:
    - duration: 100
      arrivalRate: 2000
  ws:
    # Ignore SSL certificate errors
    # - useful in *development* with self-signed certs
    rejectUnauthorized: false
scenarios:
  - engine: "ws"
    flow:
    flow:
      - loop:
        - send: "hello"
        - think: 1
      - count: 50

socketio

config:
  target: "http://localhost:5000"
  phases:
    - duration: 100
      arrivalRate: 100
  socketio:
    transports: ["websocket"]
scenarios:
  - engine: "socketio"
    flow:
      - loop:
        - emit:
            channel: "echo"
            data: "hello"
        - think: 1
      - count: 50

Are you using eventlet by any chance? See the max_size config option for the WSGI server: http://eventlet.net/doc/modules/wsgi.html#eventlet.wsgi.server. You can pass this or other server options in the socketio.run() call, anything this function does not recognize it passes down to the server.

Great! It worked! Will have to verify this in the production environment as well though, but looking good atm. Many thanks Miguel!

The above script now freezes at 3000 connections. Searching for the new limit. @miguelgrinberg do you know what a reasonable limit for socketio connections should be?

The server is single-threaded and single-process, so it really depends on how much work each connection requires. A few thousand should be doable for a lightweight server.

Both Tornado on flask-socketio freeze at 3000 connections point. These are empty connections doing very little work (one emit per 50 sec). This seems like another limit set by the system somewhere, any ideas?

Well this is interesting, they freeze at 3000 only at a certain connections/sec. At 100 connections /sec it does, at 500 it does not. Will try with a slower one.

10 connections/sec does not either.

Arrived at 20k connections, that should be suitable. Another story is if they have the production load as well, but that wont be related with the current issue. Thanks again!

@andmekaevur can you share your production setup please and how you arrived at 20k? Thanks a lot!

The main things were that I increased the system file limits (i'm on ubuntu) and the max_size config option for the WSGI server Miguel talks about above. Googling around I found some network connectivity parameters people had to tweak as well, but on ubuntu 14 and 16 the deafults were sufficient. @xarg

Thanks @andmekaevur

Was this page helpful?
0 / 5 - 0 ratings