哎, socket.io 对于 python 容器 多 worker 模式 来说好像是个死局

2016-07-22 12:32:57 +08:00
 awanabe
不管是 gunicorn 或者 uwsgi , 只要开启了多 worker , 就是多进程。
socket.io polling 的时候就会大部分的找不到对应 connection 。

所以官方推荐用 gunicorn 的原因是,用单 worker 可以发挥 协程 的最大作用。

而 uwsgi 因为对协程支持不好,转而用 多 worker 突破 python 全局锁提高并发的方式, 对于 socket.io 来说就是死局。
6361 次点击
所在节点    Python
34 条回复
ccl
2016-07-22 14:48:08 +08:00
socket.io 为了兼容旧浏览器开启的 polling 让多核化环境 handshake 报错。
引入 socket.io-client 时,请覆盖 `transports`,例如 `io( '/chat', { transports: [ 'websocket' ]})`,只用 websocket 。
此时,后端负载均衡器就不用每次都绑定同一台机了。
yxaaa123
2016-07-22 14:51:08 +08:00
可以把 polling 关掉。
rrfeng
2016-07-22 14:52:35 +08:00
@awanabe
如果用容器的话就是一个容器一个进程,开启多个容器,在容器外部做负载均衡。
50vip
2016-07-22 14:54:39 +08:00
确实这个挺坑的,但是这个问题搜都搜不到,后面老老实实看官方文档,才发现这个~~~囧
awanabe
2016-07-22 15:08:20 +08:00
@2225377fjs 不是很明白你说的 python 直接的解决方案
awanabe
2016-07-22 15:31:37 +08:00
@rrfeng 你可以把 uwsgi , gunicorn 的这些多 worker 进程的看做一个容器。 他们外面也是要套一层负载均衡的。
这个容器 是为 python 服务的, 所有就有因为 PythonGIL 问题做了多进程模型。。

所以还是 Python GIL 的问题

我们两个不在一个维度上说事情
jeffreylea
2016-07-22 15:47:28 +08:00
已经放弃 socket.io 改用 ws.js
2225377fjs
2016-07-22 15:59:46 +08:00
@awanabe 楼主你缺少一个好用而且用的熟练的 python 分布式服务化框架。
我猜楼主是要做一个基于 websocket 的网关或者推送服务吧,想要维持大量的客户端连接,所以需要多个进程来支撑,那么可以单独做 connector 系统,专门用来维护与客户端的连接,多开进程,自然就能承受更多的客户端连接了( gevent , tornado 都能很方便的实现)。

当然系统又不可能只是维护连接就好了,例如可能业务层面上需要主动向特定客户推送一些数据,那么就涉及到别的业务系统向当前的 connector 系统发送数据,然后推送给指定客户端的需求,也就发展成了各个系统间通信交互或者说 RPC 调用的需求。
如果楼主有用的 6 的 Python 分布式框架就能解决了。。。

我最开始的回复其实就是想说,可以更发散一些,不能总是用做 web 系统的思维来做所有的业务,毕竟 Python 也是可以做分布式, RPC ,服务化的。有时候业务变得复杂了,或者是要求变高了,例如需要更高的承载,更高的吞吐量,用简单做 web 系统的方式可能就不能满足需求了。

(不过,现在 Python 环境对分布式,服务系统这些东西讨论的还真的很少,也难得见到有好用的开源框架放出来,相反这方面 Java 环境倒是做的最好的,毕竟人家做各种大型业务系统成功案例多,自然就有东西放出来讨论了)

楼主说的 GIL 问题,既然是多进程的系统,那就不该考虑线程的问题了。既要维护大量的连接,又要做比较复杂的业务间的交互,能够单进程当然是最好的,毕竟多线程之间(或者协程并发)的交互是最方便的,但是 Python 做不了这个事情,楼主倒是可以考虑 Java ,如果一定要选择 Python ,那就只有多进程,分布式的方案了。

自己的见解,有不对的地方楼主还请指出来。自己用 python 做过可能跟楼主类似的东西,所以看到了帖子就多说了点。
awanabe
2016-07-22 16:50:57 +08:00
@2225377fjs 理解, 还是灵活的调整吧, 你的意思就是尽量拆分服务, 每种服务都可以有自己的实现嘛。

至于通知的话,现在可行的方案, 可以起一个 NodeJS 的 socketIO 服务器(集群)就可以规避掉这个问题。也相当于拆服务嘛。

只是现在还没到拆分服务的阶段。单机有单机的玩法, 就先用单 worker 扛着呗, 需要扩容了就拆。
rrfeng
2016-07-22 17:15:28 +08:00
@awanabe
嗯这个我是了解的。所以一开始我就说了和主题关系不大~
cppgohan
2016-07-23 11:41:13 +08:00
@glasslion "WSGI 本来就不支持持久化连接和服务端推送"

对 WSGI 一知半解, 从文档看: https://www.python.org/dev/peps/pep-0333/

> Applications and middleware are forbidden from using HTTP/1.1 "hop-by-hop" features or headers, any equivalent features in HTTP/1.0, or any headers that would affect the persistence of the client's connection to the web server. These features are the exclusive province of the actual web server, and a server or gateway should consider it a fatal error for an application to attempt sending them, and raise an error if they are supplied to start_response() . (For more specifics on "hop-by-hop" features and headers, please see the Other HTTP Features section below.)

单看文档感觉使用 WSGI 在约束 HTTP Server 的情况下, 它是能够保证持久化连接的? 所以并不算 WSGI 的问题, 算是 uWSGI 在多 worker 情况下没法满足 wsgi 的约束?
clino
2016-07-23 22:00:08 +08:00
@awanabe 我测试了一下果然有这个问题,我插,想想有没有什么办法解决
clino
2016-07-28 09:26:33 +08:00
@awanabe 不对,我看 werkzeug 有针对处理的:
https://github.com/pallets/werkzeug/blob/master/werkzeug/local.py#L20
我用 flask 测过也没有问题,不同的 gevent 之间的这些 local 变量不会共享
clino
2016-07-28 09:32:22 +08:00
@awanabe 明白了,原来那篇文章也没说错,他说的是 uwsgi --ugreen 有问题,但是如果 uwsgi --gevent 就可以,因为 werkzeug 本来有对 greenlet 做了处理, 不过 uwsgi 的 ugreen 我基本没用过了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/294165

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX