我一直在按照本教程尝试使用Flask SocketIOnginx使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'

Supervisor中,我使用以下命令调用我的应用程序:
[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

使用此配置,我的应用程序(不使用Flask SocketIO)可以正常工作。

我只是对如何使用socketIO感到困惑。如果我转到地址http://localhost:8000/socket.io,则会得到响应Internal Server Error

示例HTML/Javascript(https://github.com/miguelgrinberg/Flask-SocketIO/blob/master/example/templates/index.html)包含以下行:
var socket = io.connect('http://' + document.domain + ':' + location.port + namespace);

我有两个问题:

1)此变量应指向什么地址?

2)我的配置(nginxgunicorn)是否正确?

抱歉,这个问题很傻。我对应该如何使用所有这些功能感到困惑。

谢谢你的帮助。

**更新**

当我尝试访问http://localhost/socket.io时,这是nginx error.log文件的输出。
2015/06/20 14:05:08 [debug] 1917#0: *1 http cleanup add: 00000000009F2170
2015/06/20 14:05:08 [debug] 1917#0: *1 get 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 to 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

不确定这有什么帮助,但我不知道在其他地方可以找到更多信息。

我也很好奇为什么可以访问它:http://localhost/socket.io123abc

还是得到Internal Server Error而不是Not Found错误?

我还根据以下supervisord.conf答案更新了Miguel's文件:

administratord.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.

此列表会持续一段时间。

最佳答案

首先,我会提到我完全不建议使用SocketIO。它在WebSockets上添加了一些有用的功能,但是除非您使客户端对单个工作人员具有粘性或使用Redis之类的东西在他们之间共享状态信息,否则它不可能实现与多个工作人员真正的负载平衡(水平扩展)。我建议看一下:

https://github.com/youen/gevent-websocket

native WebSocket变得越来越简单,并且可以跨多个前端工作人员进行扩展,以实现真正的负载平衡。实现聊天室逻辑所需的代码非常少。

话虽如此,这是您的问题的答案:



您的 namespace 将为“”。 (根据Flask-SocketIO的作者Miguel所述,Javascript客户端会自动插入“socket.io”部分。)

因此,您的io.connect网址应为“http://[hostname]/”。



Ngnix配置似乎正确(尽管请参阅下一节)。如果决定使用WebSockets,则可以考虑添加proxy_read_timeout 3600;。否则,除非您有健谈协议(protocol),否则Nginx将每分钟丢弃一次WebSocket(默认值)。 (此外,根据Miguel所说,SocketIO具有处理此问题的心跳。)

Gunicorn配置不正确。有了SocketIO,您有两种选择:

  • 在gunicorn中设置workers = 1,以便每个SocketIO客户端都与同一个工作进程通信。
  • 更改您的nginx配置以使用ip-hash命令,这将导致通过客户端IP地址将客户端分配给工作程序。
  • 使用Redis或其他数据库来允许每个工作人员共享状态信息(尽管尚不清楚任何人在Gevent SocketIO上都可以工作)。

  • 这些选择是强制性的,因为SocketIO使用有状态的设置机制,当您尝试水平缩放时,该机制会中断。有关更多信息,请参见此问题:https://github.com/abourget/gevent-socketio/issues/112

    这里是指向SocketIO文档的链接,它也对此进行了讨论:http://socket.io/docs/using-multiple-nodes/

    如果获取的是Internal Server Error,则可能在某处记录了异常。尝试查找下来并将其添加到您的问题中。

    请注意,您无法通过在浏览器的地址栏中点击该URL来进行测试-默认情况下,浏览器不会使用正确的WebSocket协议(protocol),因此对您没有任何帮助。必须使用Javascript API设置WebSocket连接。

    另外,尝试使用端口号访问该URL会绕过nginx-这可能不是您想要的。 Nginx通常监听80/443,并将请求转发到localhost:8000(这称为“反向代理”设置)。

    关于python - Flask SocketIO的正确配置,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30936567/

    10-12 18:04