本帖最后由 匿名 于 2015-8-11 21:57 编辑
去年底的时候发过一次,这半年一直在使用中不断改进&完善,现在基本没什么问题了。 =============================================================== 演示代码
(程序更新过,mp_msg函数的参数类型改为string,可变数量)
运行效果(图1)
运行效果(图2)
主要封装函数
multi_process();
根据参数,创建指点数目的子进程。
亮点功能1:子进程各种异常退出,比如segment fault, Allowed memory size exhausted等,中断一个子进程后,父进程会重新fork一个新进程顶上去,保持子进程数量。如果子进程里完成任务(比如判断tid达到10000),可以在子进程里exit(9),父进程会收到这个退出状态(9),然后等待所有子进程退出,最后退出自身进程。
亮点功能2:与curl封装函数一起实现了一统计功能,在程序关闭后会显示出一些主要的统计信息(图2的底部)。
mp_counter();
在父进程以及所有子进程之间通信,负责协调分配各子进程的任务,使用了锁机制。可以设置’init’参数重置计数,可以设置每次更新计数的值。
curl_get();
对curl相关函数的封装,加入了大量的错误机制,支持POST,GET,Cookie,Proxy,下载。
mp_msg();
实现规范之一就是,每条任务处理完,只输出一行信息。
亮点功能:这个函数会判断终端的高度和宽度,实现每一屏内容会显示一条统计信息(图1的紫色行),便于观察程序的执行情况,控制每一行输出的长度,保持一条信息不会超过一行。
rand_exit();
众所周知,PHP存在内在泄露的问题,所以每一个子进程里执行一定次数的任务后就退出,由multi_process()负责自动建立新的子进程(如图1中的绿色行)。 程序效率
本次测试使用的是Vultr的最低配置机器,1 CPU(3.6GHz),768MB RAM,美国LA机房(一定程度上影响了抓取速度)。
执行了十多分钟后,统计信息如下:
运行期间内存占用统计(while true; do psmem | grep php;sleep 10; done)如下:
vmstat 1命令结果如下
iftop带宽监控如下:
简单点解释下:
50个子进程,执行11分55秒,抓取50951次,按这个速度计算,一天可以抓取615万次。
所有进程(1父进程+50子进程)共占用内存约60MB,占用CPU约20%(1核心),带宽占用约7-8Mbps。 按上面的性能参数来看,本机再开5倍的子进程数量是可以承受的,但是目标机器承受不了这么大的压力。 不同进程数量的抓取速度对比:
1个进程
10个进程
100个进程
多进程的封装几乎完美,但curl由于它的功能太过于丰**强大,可能永远也无法达到完美。
PS,这帖子就不再更新了,有需要用到的MJJ,可以保存下上面的地址,以后更新会更新上面的BLOG地址。
|