推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
2225377fjs
V2EX  ›  Python

一种比较别扭的 python 多进程 HTTP 服务实现方式,大家觉得如何。?

  •  
  •   2225377fjs · Apr 14, 2016 · 6303 views
    This topic created in 3693 days ago, the information mentioned may be changed or developed.

    对于 Python 而言,在线上部署 HTTP 服务的时候,一般都是采用多进程的方式来做的,毕竟没有 Java 的并行多线程,所以常规的方式是前面通过一个 Nginx 来做反向代理,后端启动多个 Python 进程,监听多个端口。(当然还有一种方式是通过子进程共享 listen 文件描述符来实现,但是这种方式对于 Python 而言会有一些不好的问题)

    在 linux 下还有另外一种实现方式,因为有 sendmsg 和 recvmsg 两个方法: 通过启动一个进程,专门来做 tcp 的监听,然后启动多个进程来做 worker ,通过 Unix 域 socket 与监听进程建立连接,监听进程将接收到的文件描述符通过 sendmsg 方法发送给 worker 进程,然后 worker 进程将文件描述符放入自己的 IOLoop ,当做一个正常的 Tcp 连接处理就好了。。。

    这种方式的优点: 对于 http 服务器而言,少了一个反向代理的过程,本身 nginx 那部分 http 解析的过程可以省掉一些 CPU ,而且对于 python 进程而言部署相对方便一些,不用去设置多个端口。 缺点: 只支持物理单服务器,不可能扩展到多个物理服务器,不支持 Windows , python 本身 socket 不带有 sendmsg API ,需要些 C 扩展。

    其实这个功能最开始是为了做 Tcp 服务器搞的,在架设 gate 系统的时候,只监听一个端口,然后可以方便的扩展出一些负载均衡的功能。

    http://blog.csdn.net/fjslovejhl/article/details/50481961

    26 replies    2016-04-16 23:06:22 +08:00
    zhicheng
        1
    zhicheng  
       Apr 14, 2016
    监听进程将接收到的 **文件描述符** 通过 sendmsg 方法发送给 worker 进程
    gkiwi
        2
    gkiwi  
       Apr 14, 2016
    用的第二种方法。。打算在多服务器时候,做一个类似 nginx 的路由系统,,,
    clino
        3
    clino  
       Apr 14, 2016 via Android
    用 uwsgi 不就好了 你要的功能它都有
    9hills
        4
    9hills  
       Apr 14, 2016
    人生苦短,我用 Python
    人生苦太短,我用 Gunicorn

    没必要重复造轮子
    maemual
        5
    maemual  
       Apr 14, 2016
    说了半天不就是 Gunicorn/uWSGI 么。。。
    2225377fjs
        6
    2225377fjs  
    OP
       Apr 14, 2016
    @maemual 额,不太清楚 Gunicorn/uWSGI ,没有用过,最开始是用在 Tcp 服务的,因为需要将客户端的连接分散在多个 gate 进程上,而且有一些负载均衡的处理,这样子做会相对比较方便,后来自己把它也搞到了 Http 的部分, worker 用的是 gevent 的 wsgi server , tornado 的 webapplication ,这样子所有进程都可以同一个 python 入口启动,好像用起来还可以,吞吐量什么的都还 ok 。
    2225377fjs
        7
    2225377fjs  
    OP
       Apr 14, 2016
    @9hills 哈哈,也是逼不得已,不然也不想造这玩意的。
    c4pt0r
        8
    c4pt0r  
       Apr 14, 2016
    你这个就是 wsgi
    micyng
        9
    micyng  
       Apr 14, 2016 via Android
    更像 fastcgi ,部署很蛋疼
    子进程共享描述符有啥不好了?
    BOYPT
        10
    BOYPT  
       Apr 14, 2016
    发现帖子里面有 4 个“对。。。而言”
    est
        11
    est  
       Apr 14, 2016
    > 监听进程将接收到的文件描述符通过 sendmsg 方法发送给 worker 进程

    据说并发大了,你 master 进程连 fd 都分发不过来。
    micyng
        12
    micyng  
       Apr 14, 2016 via Android
    gunicorn 没记错的话也是子进程共享的模式
    peter999
        13
    peter999  
       Apr 14, 2016
    用 python 的 github 上找得到的轮子我都不想自己撸
    msg7086
        14
    msg7086  
       Apr 14, 2016
    如果你不需要支持 Windows 的话,直接让一堆进程监听同一个端口不就行了吗。
    maemual
        15
    maemual  
       Apr 14, 2016
    @2225377fjs 正常 Python 单机多实例部署的时候,也都是前面有一层 Gunicorn/uWSGI 来实现的,实现你说的各种功能。。。。
    2225377fjs
        16
    2225377fjs  
    OP
       Apr 14, 2016
    @BOYPT 囧,我也发现了,表达能力有限,当年读书的时候没有好好学语文。。。
    2225377fjs
        17
    2225377fjs  
    OP
       Apr 14, 2016
    @est 还好吧,暂时没有遇到过这种极端的情况,因为我们生产环境机器相对好一些?一个监听进程,然后多开几个 worker 进程,简单的 ab 测试 http 请求, 2W 的 qps 的时候好像也没有出过这种情况,也还好,暂时没有测试过单个监听进程 accept 和 sendmsg 的极限吞吐量,反正肯定足够用了。
    2225377fjs
        18
    2225377fjs  
    OP
       Apr 14, 2016
    @micyng 如果是 nginx 那种方式来实现进程间共享监听的话,可能确实不错,但是如果不加改造,简单的启动多个 python 进程共享同一个监听的话,会发现大多数的连接都被同一个进程拿到了,对于短连接可能还好,但是对于长连接的 TCP 服务的话应该是不能容忍的。
    vincenttone
        19
    vincenttone  
       Apr 14, 2016
    启动一个主进程,先建立一个 socket ,然后 fork ,用子进程去 accept ,子进程加锁,拿到锁的可以 accept 。
    2225377fjs
        20
    2225377fjs  
    OP
       Apr 14, 2016
    @maemual 对于现在 python 开发 web 的部署方式不是很熟,毕竟这个 http 只是附带的功能。主要是用来实现将 tcp 连接相对比较均匀的分散到 worker 进程上面去,然后 worker 可以自己确定是否还要接收 tcp 连接,如果达到 worker 的阈值的话, worker 可以断开与监听进程的连接来,等以后负载降下来了再自己连上去。
    micyng
        21
    micyng  
       Apr 14, 2016 via Android
    @2225377fjs 你现在说的这些东西其实 Nginx 已经成熟地支持了
    另外子进程共享的方式,操作系统会处理好 accept 分发的事
    还有如果特别针对多进程环境下 TCP 长连接的情况,大可不必担心,因为这种模型不会用于推送的场景,而是处理较大流数据的上传下载业务,用一段时间就关了,跟一个 http 请求其实没什么两样
    换做推送场景的话,也不会用多进程模型了,而是得考虑分布式节点了
    micyng
        22
    micyng  
       Apr 14, 2016 via Android
    @2225377fjs 你现在说的这些东西其实 Nginx 已经成熟地支持了
    另外子进程共享的方式,操作系统会处理好 accept 分发的事
    还有如果特别针对多进程环境下 TCP 长连接的情况,大可不必担心,因为这种模型不会用于推送的场景,而是处理较大流数据的上传下载业务,用一段时间就关了,跟一个 http 请求其实没什么两样
    换做推送场景的话,也不会用多进程模型了,而是得考虑分布式节点了
    micyng
        23
    micyng  
       Apr 14, 2016 via Android
    我的 1%被识别成安卓猴了😈
    wuyadong
        24
    wuyadong  
       Apr 14, 2016
    uwsgi
    clino
        25
    clino  
       Apr 14, 2016
    @2225377fjs uwsgi 也支持 gevent 和 virtualenv 的
    可以自身作为 http server,也可以用自定义的 socket 协议和 nginx 交互,当然自身作为 http server 再被 nginx 反代也行
    tomZhao
        26
    tomZhao  
       Apr 16, 2016
    一般而言,会使用 gunicorn/uwsgi 做 server 来处理也就是你说的第二种。老实说,我比较不喜欢这种方式,
    使用 supervisord 来启动多进程,监听多个端口, nginx 反向代理,则是第一种方式,也可以。我比较喜欢。可以做一些小的优化,比如 cpu 绑定之类的。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   3230 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 58ms · UTC 13:11 · PVG 21:11 · LAX 06:11 · JFK 09:11
    ♥ Do have faith in what you're doing.