python - Correct configuration for Flask SocketIO -
i have been following tutorial try , flask socketio
running using nginx
, gunicorn
.
nginx
server { location / { proxy_pass http://127.0.0.1:8000; proxy_redirect off; proxy_set_header host $host; proxy_set_header x-real-ip $remote_addr; proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for; } location /socket.io { proxy_pass http://localhost:8000/socket.io; proxy_redirect off; proxy_buffering off; proxy_set_header host $host; proxy_set_header x-real-ip $remote_addr; proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for; proxy_http_version 1.1; proxy_set_header upgrade $http_upgrade; proxy_set_header connection "upgrade"; } }
gunicorn_config.py
bind = '127.0.0.1:8000' workers = 2 worker_class = 'socketio.sgunicorn.geventsocketioworker'
in supervisor
call app with:
[program:gunicorn-couponmonk] directory = ~/couponmonk_project command =~/venv/py2.7/bin/python ~/venv/py2.7/bin/gunicorn -c ~/venv/py2.7/lib/python2.7/site-packages/gunicorn/gunicorn_config.py __init__.py stdout_logfile = /var/log/gunicorn/couponmonk-std.log stderr_logfile = /var/log/gunicorn/couponmonk-err.log user = mint
with configuration, app (without using flask socketio
) works fine.
i'm confused @ how use socketio
. if go address http://localhost:8000/socket.io, response internal server error
.
the example html/javascript
(https://github.com/miguelgrinberg/flask-socketio/blob/master/example/templates/index.html) contains line:
var socket = io.connect('http://' + document.domain + ':' + location.port + namespace);
i have 2 questions:
1) address variable supposed point to?
2) configuration (nginx
, gunicorn
) correct?
sorry if question silly. i'm confused how supposed work.
thanks help.
**update**
this output of nginx
error.log
file when try , access http://localhost/socket.io.
2015/06/20 14:05:08 [debug] 1917#0: *1 http cleanup add: 00000000009f2170 2015/06/20 14:05:08 [debug] 1917#0: *1 rr peer, try: 1 2015/06/20 14:05:08 [debug] 1917#0: *1 socket 12 2015/06/20 14:05:08 [debug] 1917#0: *1 epoll add connection: fd:12 ev:80000005 2015/06/20 14:05:08 [debug] 1917#0: *1 connect 127.0.0.1:8000, fd:12 #2 2015/06/20 14:05:08 [debug] 1917#0: *1 http upstream connect: -2 2015/06/20 14:05:08 [debug] 1917#0: *1 posix_memalign: 0000000000a14170:128 @16 2015/06/20 14:05:08 [debug] 1917#0: *1 event timer add: 12: 60000:1434773168437 2015/06/20 14:05:08 [debug] 1917#0: *1 http finalize request: -4, "/socket.io?" a:1, c:2 2015/06/20 14:05:08 [debug] 1917#0: *1 http request count:2 blk:0 2015/06/20 14:05:08 [debug] 1917#0: *1 post event 0000000000a295e0 2015/06/20 14:05:08 [debug] 1917#0: *1 post event 0000000000a29648 2015/06/20 14:05:08 [debug] 1917#0: *1 delete posted event 0000000000a29648 2015/06/20 14:05:08 [debug] 1917#0: *1 http upstream request: "/socket.io?" 2015/06/20 14:05:08 [debug] 1917#0: *1 http upstream send request handler 2015/06/20 14:05:08 [debug] 1917#0: *1 http upstream send request 2015/06/20 14:05:08 [debug] 1917#0: *1 chain writer buf fl:1 s:439 2015/06/20 14:05:08 [debug] 1917#0: *1 chain writer in: 00000000009f21a8 2015/06/20 14:05:08 [debug] 1917#0: *1 writev: 439 2015/06/20 14:05:08 [debug] 1917#0: *1 chain writer out: 0000000000000000 2015/06/20 14:05:08 [debug] 1917#0: *1 event timer del: 12: 1434773168437 2015/06/20 14:05:08 [debug] 1917#0: *1 event timer add: 12: 60000:1434773168437 2015/06/20 14:05:08 [debug] 1917#0: *1 delete posted event 0000000000a295e0 2015/06/20 14:05:08 [debug] 1917#0: *1 http run request: "/socket.io?" 2015/06/20 14:05:08 [debug] 1917#0: *1 http upstream check client, write event:1, "/socket.io" 2015/06/20 14:05:08 [debug] 1917#0: *1 http upstream recv(): -1 (11: resource temporarily unavailable) 2015/06/20 14:05:08 [debug] 1917#0: *1 post event 0000000000a15e38 2015/06/20 14:05:08 [debug] 1917#0: *1 post event 0000000000a29648 2015/06/20 14:05:08 [debug] 1917#0: *1 delete posted event 0000000000a29648 2015/06/20 14:05:08 [debug] 1917#0: *1 http upstream request: "/socket.io?" 2015/06/20 14:05:08 [debug] 1917#0: *1 http upstream dummy handler 2015/06/20 14:05:08 [debug] 1917#0: *1 delete posted event 0000000000a15e38 2015/06/20 14:05:08 [debug] 1917#0: *1 http upstream request: "/socket.io?" 2015/06/20 14:05:08 [debug] 1917#0: *1 http upstream process header 2015/06/20 14:05:08 [debug] 1917#0: *1 malloc: 00000000009e88a0:4096 2015/06/20 14:05:08 [debug] 1917#0: *1 recv: fd:12 244 of 4096 2015/06/20 14:05:08 [debug] 1917#0: *1 http proxy status 500 "500 internal server error" 2015/06/20 14:05:08 [debug] 1917#0: *1 http proxy header: "connection: close" 2015/06/20 14:05:08 [debug] 1917#0: *1 http proxy header: "content-type: text/html" 2015/06/20 14:05:08 [debug] 1917#0: *1 http proxy header: "content-length: 141" 2015/06/20 14:05:08 [debug] 1917#0: *1 http proxy header done 2015/06/20 14:05:08 [debug] 1917#0: *1 xslt filter header 2015/06/20 14:05:08 [debug] 1917#0: *1 http/1.1 500 internal server error server: nginx/1.4.6 (ubuntu) date: sat, 20 jun 2015 04:05:08 gmt content-type: text/html content-length: 141 connection: keep-alive
not sure how helpful don't know else info.
i'm curious why can access this: http://localhost/socket.io123abc
and still internal server error
opposed not found
error?
i updated supervisord.conf
file based on miguel's
answer below:
supervisord.conf
[program:gunicorn-couponmonk] directory = /home/giri/couponmonk_project command = /home/giri/venv/py2.7/bin/python /home/giri/venv/py2.7/bin/gunicorn --worker-class socketio.sgunicorn.geventsocketioworker __init__:app stdout_logfile = /var/log/gunicorn/couponmonk-std.log stderr_logfile = /var/log/gunicorn/couponmonk-err.log user = mint
/var/log/gunicorn/couponmonk-err.log
2015-06-20 14:30:11 [3821] [error] connection in use: ('127.0.0.1', 8000) 2015-06-20 14:30:11 [3821] [error] retrying in 1 second. 2015-06-20 14:30:12 [3821] [error] connection in use: ('127.0.0.1', 8000) 2015-06-20 14:30:12 [3821] [error] retrying in 1 second. 2015-06-20 14:30:13 [3821] [error] connection in use: ('127.0.0.1', 8000) 2015-06-20 14:30:13 [3821] [error] retrying in 1 second.
this list continues on while..
first, i'll mention don't recommend using socketio @ all. adds little bit of useful functionality on websockets makes true load balancing multiple workers (horizontal scaling) impossible unless make clients sticky individual workers or use redis share state information between them. recommend taking at:
https://github.com/youen/gevent-websocket
native websockets simpler , easier , scales across multiple frontend workers true load balancing. code takes implement chat room logic minimal.
having said that, here's answer questions:
1) address variable supposed point to?
your namespace going "". (according miguel, author of flask-socketio, javascript client automatically inserts "socket.io" part.)
so, io.connect
url should "http://[hostname]/".
2) configuration (nginx, gunicorn) correct?
ngnix config seems correct (though see next section). if decide use websockets, might consider adding proxy_read_timeout 3600;
. otherwise, unless have chatty protocol, websocket dropped nginx once minute (the default value). (also, according miguel, socketio has heartbeats deal this.)
gunicorn config not correct. socketio have couple of choices:
- set
workers = 1
in gunicorn each socketio client talking same worker process. - change nginx configuration use
ip-hash
command cause clients assigned workers client ip address. - use redis or other database allow each worker share state information (though it's not clear has working yet gevent socketio).
these choices forced because socketio uses stateful setup mechanism breaks when try scale horizontally. see issue more information: https://github.com/abourget/gevent-socketio/issues/112
and here's link socketio's documentation talking also: http://socket.io/docs/using-multiple-nodes/
if getting internal server error
there exception being logged somewhere. try hunt down , add question.
note can't test hitting url in address bar of browser – browser doesn't speak proper websocket protocol default , nothing useful you. websocket connections must setup using javascript api.
also, trying hit url port number bypasses nginx - not want do. nginx listens @ 80/443 , forwards requests localhost:8000 (that's called "reverse proxy" setup).
Comments
Post a Comment