Flask SocketIO & uWSGI causes 'TypeError: '

2019-08-21 12:48发布

问题:

I'm currently building an app that uses a combination of Flask and Flask SocketIO to handle a combination of HTTP and WebSocket traffic. After deploying my application on a server and adding uWSGI and Nginx as a gateway, the wsgi script gives me the following error in the logs:

TypeError: 'SocketIO' object is not callable
[pid: 4262|app: 0|req: 3/8] XXX.XXX.XXX.XXX () {46 vars in 912 bytes} [Tue Jul 11 14:57:25 2017] GET / => generated 0 bytes in 0 msecs (HTTP/2.0 500) 0 

As stated in the uWSGI documentation, I added set http-websockets flag to true in my configuration file. The Flask SocketIO documentation states that they have support for uWSGI:

The other alternative is to use the uWSGI web server, which comes with WebSocket functionality. The use of gevent is also a performant option, but slightly lower than eventlet.

Does anyone know what I'm doing wrong? I'm using the latest version of Nginx. Thanks for the help in advance. My setup:

Flask server (mymod.server)

from flask import Flask
from flask_socketio import SocketIO, emit


server = Flask(__name__)
io = SocketIO(server)

@server.route("/")
def index():
    return server.send_static_file("index.html")

@io.on("ping")
def ping():
    emit("pong")

WSGI script (root of the project)

from mymod.server import io

if __name__ == "__main__":
    io.run(host="127.0.0.1", port=8080)

WSGI config

# Configuration file for Nginx
[uwsgi]
module = wsgi:io
master = true
processes = 5
buffer-size=32768
http-websockets = true
socket = server.sock
chmod-socket = 666
vacuum = true
die-on-term = true
logto = /var/log/uwsgi/%n.log

Nginx config

server {
    listen 443 http2 ssl;
    listen [::]:443 http2 ssl;

    server_name _;
    server_tokens off;

    location / {
        include uwsgi_params;
        uwsgi_pass unix:/home/user/project/server.sock;
    }

    location /socket.io/ {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_pass http://unix:/home/user/project/server.sock;
    }
}

How I start my server

$ uwsgi --ini config.wsgi.ini

回答1:

Turns out Flask-SocketIO simply mounts onto the original app object, replacing the following:

[uwsgi]
module = wsgi:io

To:

[uwsgi]
module = wsgi:app

Would work, but uwsgi still has terrible support for SocketIO, making gunicorn a better option as from what I've heard.