工作需要,做一TCP服务器,主进程监听,一旦有连接就分一个子进程去处理。优缺点是什么? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
picasso250
V2EX    PHP

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

  •  
  •   picasso250 2013-08-20 13:16:10 +08:00 8466 次点击
    这是一个创建于 4485 天前的主题,其中的信息可能已经有所发展或是发生改变。


    请不吝赐教,万分感谢。
    第 1 条附言    2013-08-20 16:47:22 +08:00

    总结

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

    缺点:
    进程开销大,数量有限,不适合高并发
    会出现很多僵尸进程
    第 2 条附言    2013-08-21 18:01:26 +08:00
    僵尸进程可以用

    pcntl_signal(SIGCHLD, SIG_IGN);

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

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

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


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

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

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


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

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

    以下是网上摘抄:
    while true; do { echo -e 'HTTP/1.1 200 OK\r\n'; cat index.html; } | nc -l 8080; done
    picasso250
        32
    picasso250  
    OP
       2013-08-21 14:51:18 +08:00
    @pubby 确实出现了很多僵尸进程。
    bixuehujin
        33
    bixuehujin  
       2013-08-21 15:15:05 +08:00   1
    可以考虑单线程异步解决方案,PHP下有个reactphp,类似nodejs。
    nofeeling
        34
    nofeeling  
       2013-09-11 22:57:22 +08:00   1
    可以使用swoole框架,用C扩展实现的高性能高并发TCP Server。做一个健壮完善的Socket Server不是那么容易的,stream_socket_server和sockets扩展,或者是libevent, reactphp这些都不是完整的Server方案。
    http://www4swoole.sinaapp.com/
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5608 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 01:49 PVG 09:49 LAX 17:49 JFK 20:49
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86