V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
picasso250
V2EX  ›  PHP

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

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


    请不吝赐教,万分感谢。
    第 1 条附言  ·  2013-08-20 16:47:22 +08:00
    ps 我们的并发不大,一天的PV才不到10万。

    总结

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

    缺点:
    进程开销大,数量有限,不适合高并发
    会出现很多僵尸进程
    第 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   ·   实用小工具   ·   5382 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 03:44 · PVG 11:44 · LAX 19:44 · JFK 22:44
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.