2
votes

I am working on Flask app that uses WebSockets to communicate with frontend. It hosted on Amazon EC2 behind nginx and serverd by uwsgi.

Here is uwsgi config I am using to serve then app:

[uwsgi]
plugins=python3,logfile
chdir=/srv/myapp/
master=true
home=/srv/myapp/.venv
module=application
callable=flask_app
uid=uwsgi
gid=myapp
socket=/srv/myapp/uwsgi.sock
chown-socket=uwsgi:myapp
chmod-socket=660
logto = /srv/myapp/logs/uwsgi.log
for-readline = /srv/myapp/.vars
  env = %(_)
endfor =

And excerpt from nginx config that covers socketio endpoint:

location /socket.io/ {
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    proxy_http_version 1.1;
    proxy_buffering off;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_pass http://unix:///srv/myapp/uwsgi.sock;
}

Without websockets everything works fine. Locally (I am using Windows) everything works perfect too - I just added transport: ['websockets', 'polling'] on the client to ensure that correct protocol will be chosen.

Locally I am running it as recommended in Flask-SocketIO documentation and also I installed eventlet (I don't know why but in Windows x64 gevent wrapper works badly with Werkzeug dev server).

When app is deployed I see only errors websocket.js:112 WebSocket connection to 'ws://myapp.com/socket.io/?EIO=3&transport=websocket' failed: Error during WebSocket handshake: Unexpected response code: 502 in browser. On the server side I have following in uwsgi log: invalid request block size: 21573 (max 4096)...skip. Increasing of the buffer size changes nothing.

In nginx logs I have: *413 upstream prematurely closed connection while reading response header from upstream, client: 171.6.248.10, server: localhost,, request: "GET /socket.io/?EIO=3&transport=websocket HTTP/1.1", upstream: "http://unix:///srv/myapp/uwsgi.sock:/socket.io/?EIO=3&transport=websocket", host: "myapp.com"

I tried to add these lines to uwsgi.ini:

gevent=1000
http-websockets=true

without any success

What is it and how it can be solved?

1
Couple of comments. The gevent and http-websockets configuration items in uwsgi are required. The only way WebSocket works with uwsgi is through gevent. Also, I don't understand your reference to the Werkzeug dev server in conjunction with gevent, since gevent uses its own WSGI server, completely unrelated to Werkzeug. As far as the main problem, can you check if the async mode that Flask-SocketIO selects is gevent_uwsgi? - Miguel
@Miguel unfortunately my app uses Python3 while gevent plugin for uwsgi (at least for Red Hat) supports still only Python2.7 - Alex G.P.
Well, uwsgi without gevent is not a supported configuration, you may be able to get long-polling to work, but WebSocket is not possible. Have you tried installing uwsgi with pip instead of using the one packaged by your OS? - Miguel
No I didn't. I just returned to my Ginucorn configuration. - Alex G.P.

1 Answers

1
votes

It is not actual answer to my question, just a bit of information

My application uses Python 3 and RedHat provides Python3.4 from EPEL. Nevertheless UWSGI can works with WebSockets only using gevent. So, as @Miguel mentioned there is only one way - to use long-polling.

Solution

Finally I changed appserver to Gunicorn that served WebSockets out of box.