Hi, I've spent several hours looking online and reading through the issues posted but have not found a solution.
This totally works on dev without gunicorn and eventlet
websocket request return the following error:
~~~
{
"error": "404 Not Found: The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.",
"traceback": [
" File \"/usr/local/lib/python3.7/site-packages/flask/app.py\", line 1813, in full_dispatch_request\n rv = self.dispatch_request()\n",
" File \"/usr/local/lib/python3.7/site-packages/flask/app.py\", line 1791, in dispatch_request\n self.raise_routing_exception(req)\n",
" File \"/usr/local/lib/python3.7/site-packages/flask/app.py\", line 1774, in raise_routing_exception\n raise request.routing_exception\n",
" File \"/usr/local/lib/python3.7/site-packages/flask/ctx.py\", line 336, in match_request\n self.url_adapter.match(return_rule=True)\n",
" File \"/usr/local/lib/python3.7/site-packages/werkzeug/routing.py\", line 1786, in match\n raise NotFound()\n"
]
}
~
I'm running gunicorn like gunicorn --worker-class eventlet --bind :5000 wsgi:app --log-level=debug --log-file=-
my wsgi.py file looks like
~~~
from app import init_app
from flask_socketio import SocketIO
app = init_app()
if __name__ == '__main__':
socketio = SocketIO(app)
socketio.run(app)
~~~
the init_app func is just a wrapper for the usual app = Flask(__name__) no magic there other than setting some variables and environment configs
my nginx config for this is
~~~
location /socket.io {
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://api:5000/socket.io;
}
~
Python packages
~~~
$ pip freeze
aniso8601==6.0.0
blinker==1.4
Click==7.0
dnspython==1.16.0
eventlet==0.24.1
Flask==1.0.2
Flask-Caching==1.5.0
Flask-Mail==0.9.1
Flask-RESTful==0.3.7
Flask-SocketIO==3.2.1
Flask-SQLAlchemy==2.3.2
greenlet==0.4.15
gunicorn==19.9.0
itsdangerous==1.1.0
Jinja2==2.10.1
MarkupSafe==1.1.1
monotonic==1.5
mysqlclient==1.3.14
PyJWT==1.7.1
python-engineio==3.7.0
python-socketio==4.0.3
pytz==2019.1
six==1.12.0
SQLAlchemy==1.3.4
Werkzeug==0.15.4
~~~
The error output is obviously being generated by flask.
Otherwise my endpoints work fine.
Any ideas?
By the way, std outputs this for every ws request:
~~~
[2019-05-31 02:20:52 +0000] [9] [DEBUG] GET /socket.io/
[2019-05-31 02:20:52 +0000] [9] [DEBUG] Closing connection.
~~~
this is the console output when I run in debug mode
~~~
bind: [':5000']
backlog: 2048
workers: 1
worker_class: eventlet
threads: 1
worker_connections: 1000
max_requests: 0
max_requests_jitter: 0
timeout: 30
graceful_timeout: 30
keepalive: 2
limit_request_line: 4094
limit_request_fields: 100
limit_request_field_size: 8190
reload: False
reload_engine: auto
reload_extra_files: []
spew: False
check_config: False
preload_app: False
sendfile: None
reuse_port: False
chdir: /usr/src/app
daemon: False
raw_env: []
pidfile: None
worker_tmp_dir: None
0
group: 0
umask: 0
initgroups: False
tmp_upload_dir: None
secure_scheme_headers: {'X-FORWARDED-PROTOCOL': 'ssl', 'X-FORWARDED-PROTO': 'https', 'X-FORWARDED-SSL': 'on'}
forwarded_allow_ips: ['127.0.0.1']
accesslog: None
disable_redirect_access_to_syslog: False
access_log_format: %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"
errorlog: -
loglevel: debug
capture_output: False
logger_class: gunicorn.glogging.Logger
logconfig: None
logconfig_dict: {}
syslog_addr: udp://localhost:514
syslog: False
syslog_prefix: None
syslog_facility: user
enable_stdio_inheritance: False
statsd_host: None
statsd_prefix:
proc_name: None
default_proc_name: wsgi:app
pythonpath: None
paste: None
on_starting:
on_reload:
when_ready:
pre_fork:
post_fork:
post_worker_init:
worker_int:
worker_abort:
pre_exec:
pre_request:
post_request:
child_exit:
worker_exit:
nworkers_changed:
on_exit:
proxy_protocol: False
proxy_allow_ips: ['127.0.0.1']
keyfile: None
certfile: None
ssl_version: 2
cert_reqs: 0
ca_certs: None
suppress_ragged_eofs: True
do_handshake_on_connect: False
ciphers: TLSv1
raw_paste_global_conf: []
[2019-05-31 02:28:23 +0000] [7] [INFO] Starting gunicorn 19.9.0
[2019-05-31 02:28:23 +0000] [7] [DEBUG] Arbiter booted
[2019-05-31 02:28:23 +0000] [7] [INFO] Listening at: http://0.0.0.0:5000 (7)
[2019-05-31 02:28:23 +0000] [7] [INFO] Using worker: eventlet
[2019-05-31 02:28:23 +0000] [10] [INFO] Booting worker with pid: 10
[2019-05-31 02:28:23 +0000] [7] [DEBUG] 1 workers
~~~
just updated all related packages to latest version and issue still persists.
~
aniso8601==6.0.0
blinker==1.4
Click==7.0
dnspython==1.16.0
eventlet==0.25.0
Flask==1.0.3
Flask-Caching==1.7.2
Flask-Mail==0.9.1
Flask-RESTful==0.3.7
Flask-SocketIO==4.0.0
Flask-SQLAlchemy==2.3.2
greenlet==0.4.15
gunicorn==19.9.0
itsdangerous==1.1.0
Jinja2==2.10.1
MarkupSafe==1.1.1
monotonic==1.5
mysqlclient==1.4.2.post1
PyJWT==1.7.1
python-engineio==3.7.0
python-socketio==4.0.3
pytz==2019.1
six==1.12.0
SQLAlchemy==1.3.4
Werkzeug==0.15.4
~
Your SocketIO object needs to be moved to the global scope:
from app import init_app
from flask_socketio import SocketIO
app = init_app()
socketio = SocketIO(app)
if __name__ == '__main__':
socketio.run(app)
Thanks for your reply, that fixed it!. It did not occurred to me to try this since it works in dev. I gather that Eventlet's concurrency has something to do with that. If you can shed any light on why this is, I'd appreciate it but otherwise thanks for your time.
It's not eventlet, the SocketIO object is what instantiates the Socket.IO server. That line needs to execute both for development and production deployments. When you had it inside the if statement it only executed for development.
Most helpful comment
It's not eventlet, the
SocketIOobject is what instantiates the Socket.IO server. That line needs to execute both for development and production deployments. When you had it inside theifstatement it only executed for development.