V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
picasso250
V2EX  ›  PHP

工作需要,做一TCP服务器,主进程监听,一旦有连接就分一个子进程去处理。优缺点是什么?

  •  
  •   picasso250 · Aug 20, 2013 · 8718 views
    This topic created in 4639 days ago, the information mentioned may be changed or developed.


    请不吝赐教,万分感谢。
    Supplement 1  ·  Aug 20, 2013
    ps 我们的并发不大,一天的PV才不到10万。

    总结

    优点:
    模型简单
    健壮性好(进程间相互独立)

    缺点:
    进程开销大,数量有限,不适合高并发
    会出现很多僵尸进程
    Supplement 2  ·  Aug 21, 2013
    僵尸进程可以用

    pcntl_signal(SIGCHLD, SIG_IGN);

    解决。
    34 replies    1970-01-01 08:00:00 +08:00
    v8ex
        1
    v8ex  
       Aug 20, 2013   ❤️ 1
    随着连接的增加会增加N个进程(消耗系统资源),建议用队列和线程;
    picasso250
        2
    picasso250  
    OP
       Aug 20, 2013
    刚刚看了一下,貌似php中专门有一个函数建立服务器的,是stream_socket_server
    picasso250
        3
    picasso250  
    OP
       Aug 20, 2013
    @v8ex 1. 但我的子进程会自杀。也会消耗系统资源吗?
    2. 队列的话,如何保证实时处理?(用php-resque可以做吗?)
    3. 线程编写起来有些麻烦,且不是php的强项。有没有成熟的tcp服务器,可以调用php脚本?如果没有,那么用php编写线程也是无奈之举。
    jasontse
        4
    jasontse  
       Aug 20, 2013 via iPad   ❤️ 1
    用pthreads吧,感觉fork写起来会很麻烦
    timonwong
        5
    timonwong  
       Aug 20, 2013   ❤️ 1
    优点是模型简单,可以处理长业务,健壮性也还好。最大的缺点就是消耗很多的系统资源(并发数高的话)。

    这个看你需要多少并发,业务内容是什么。
    ipconfiger
        6
    ipconfiger  
       Aug 20, 2013   ❤️ 1
    @picasso250 优点是不会阻塞主进程,缺点是在高并发的时候很快就会将你系统的最大进程数耗尽,或者是内存。很多进程操作系统在切换的时候也响应不过来,然后就会变得很慢。
    picasso250
        7
    picasso250  
    OP
       Aug 20, 2013
    @jasontse 我本来是觉得用pthreads写起来会麻烦一些。不过线程还有一个问题就是一旦死掉,会连累其他线程。
    cdfmr
        8
    cdfmr  
       Aug 20, 2013   ❤️ 1
    并发数不高的话,这个方案没什么问题。
    picasso250
        9
    picasso250  
    OP
       Aug 20, 2013
    @timonwong 谢谢。并发不大,一天的PV才不到10万,能有多少并发…… 业务也并非长业务。
    daoluan
        10
    daoluan  
       Aug 20, 2013   ❤️ 1
    优点,简单;缺点,进程创建开销大,而且数量非常有限。
    Shieffan
        11
    Shieffan  
       Aug 20, 2013
    简单粗暴但稳定。效率(并发性能)一般,进程所耗资源相对大,系统内可fork的进程数有限,而且进程频繁切换耗费比较大,特别是高IO的进程,效率会大大降低。

    一句话,如果并发要求没那么高而且是高CPU的任务,用多进程比较合理。
    如果是高IO,高并发的,建议用其它并发模型。
    v8ex
        12
    v8ex  
       Aug 20, 2013   ❤️ 1
    @picasso250 每次都要fork 肯定会消耗资源的;
    线程可以绑定CPU;
    PHP不懂,还以为你用C/C++呢;
    jseanj
        13
    jseanj  
       Aug 20, 2013
    当并发量很大时,如果请求是cpu型操作,那么你的负载就会很高,每个子进程都会占用cpu,latency会变高。如果请求是io型操作,那么你的cpu就会闲置,导致资源浪费。当然,如果并发量不大的话是没什么问题的。如果io操作多一些的话,可以考虑nginx。
    xunyu
        14
    xunyu  
       Aug 20, 2013
    我也有过类似的需求,后来是通过tornado分配新线程处理的
    Ever
        15
    Ever  
       Aug 20, 2013
    这样写肯定会出现很多僵尸进程的
    xiaoye5200
        16
    xiaoye5200  
       Aug 20, 2013
    epoll?
    bjzhush
        17
    bjzhush  
       Aug 20, 2013
    我也是PHPer,感觉PHP不是很适合做这个场景的工作
    比如你如何运行这个脚本 ? 以后如果需要相互通信又如何做 ?
    lj0014
        18
    lj0014  
       Aug 20, 2013   ❤️ 1
    优点:逻辑简单,每个连接独立进程即使挂了也不影响其它进程和父进程
    缺点:每个连接一个进程开销大,不适合连接数高的应用
    harrymoo
        19
    harrymoo  
       Aug 20, 2013
    可以搞个进程池,不用每次都创建销毁进程,快一点。 这个是以前做C的经验,PHP不懂。
    pubby
        20
    pubby  
       Aug 20, 2013   ❤️ 1
    @Ever
    @picasso250


    Ever : "这样写肯定会出现很多僵尸进程的"

    赞同,而且会非常严重,内存耗尽或者达到每用户进程数上限为止

    楼主得记得加上:
    pcntl_signal(SIGCHLD, SIG_IGN);


    结构简单,稳定可靠。
    这点pv确实没啥性能讲究,用着先吧。
    huaiyinhou
        21
    huaiyinhou  
       Aug 20, 2013
    一旦大量并发,问题就会出来。
    建议还是队列或线程
    picasso250
        22
    picasso250  
    OP
       Aug 20, 2013
    @pubby pcntl_signal(SIGCHLD, SIG_IGN); 已加。但有个疑问是:这个SIGCHLD信号默认就会被忽略的吧?

    而且僵尸进程该如何解决?重启服务器吗……
    jasontse
        23
    jasontse  
       Aug 20, 2013 via iPad   ❤️ 1
    有COW的存在,创建进程的开销不大。跟CGI还是不一样的,exec和fork代价不同。
    epoll如果业务逻辑没有长时间阻塞的操作可以试一下。
    多进程有利于缓解php的内存泄漏
    picasso250
        24
    picasso250  
    OP
       Aug 20, 2013
    @jasontse 多谢解释。但COW和进程是如何关联的?在C语言中,进程一定会复制一份自己内存。在php中,解释器能使zval在多个进程间共享吗?
    pubby
        25
    pubby  
       Aug 20, 2013
    @picasso250 反正我找遍了所有的避免僵尸方法,最后就这个管用 (PHP 5.3.10 / FreeBSD 8.2 amd64)
    picasso250
        26
    picasso250  
    OP
       Aug 20, 2013
    @pubby ....
    pubby
        27
    pubby  
       Aug 20, 2013
    Ever
        28
    Ever  
       Aug 20, 2013   ❤️ 1
    除了用信号, fork改成double fork也能处理掉僵尸
    msg7086
        29
    msg7086  
       Aug 20, 2013
    如果要性能更好的话就要改用event/epoll来做。PHP可能局限性太大,可以考虑上py或者rb之类的,甚至是上functional programming
    dogfeet
        30
    dogfeet  
       Aug 20, 2013
    不会PHP.
    如果要图快,使用一门带协程的语言不错。
    如果可以,试下scala golang clojure等等嘛。
    darasion
        31
    darasion  
       Aug 20, 2013
    如果业务非常简单,貌似可以用shell:

    以下是网上摘抄:
    while true; do { echo -e 'HTTP/1.1 200 OK\r\n'; cat index.html; } | nc -l 8080; done
    picasso250
        32
    picasso250  
    OP
       Aug 21, 2013
    @pubby 确实出现了很多僵尸进程。
    bixuehujin
        33
    bixuehujin  
       Aug 21, 2013   ❤️ 1
    可以考虑单线程异步解决方案,PHP下有个reactphp,类似nodejs。
    nofeeling
        34
    nofeeling  
       Sep 11, 2013   ❤️ 1
    可以使用swoole框架,用C扩展实现的高性能高并发TCP Server。做一个健壮完善的Socket Server不是那么容易的,stream_socket_server和sockets扩展,或者是libevent, reactphp这些都不是完整的Server方案。
    http://www4swoole.sinaapp.com/
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   760 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 74ms · UTC 21:03 · PVG 05:03 · LAX 14:03 · JFK 17:03
    ♥ Do have faith in what you're doing.