为什么php curl使用fork apache进程和php_start_session()


Why php curl uses forked apache processes and php_start_session()?

我正在编写一个php脚本,该脚本使用curl对另一个服务器进行数千次http调用。我注意到apache进程的数量在运行类似于下面的php代码时不断增加:

$ch = curl_init($this->server);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_HEADER, TRUE);
curl_setopt($ch, CURLINFO_HEADER_OUT, TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        "Content-Type: application/json",
        "Content-Length: ".strlen($data)));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$res = curl_exec($ch);

过了一会儿,我用gdb检查了一些正在运行的apache进程,其中许多我得到了这样的回溯:

#0  0x00007fa1fec1d617 in flock () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x00007fa1fbbaf53b in ?? () from /usr/lib/apache2/modules/libphp5.so
#2  0x00007fa1fbbaf7a2 in ?? () from /usr/lib/apache2/modules/libphp5.so
#3  0x00007fa1fbbae524 in php_session_start () from /usr/lib/apache2/modules/libphp5.so
#4  0x00007fa1fbbaebb9 in ?? () from /usr/lib/apache2/modules/libphp5.so
#5  0x00007fa1fbd6fe8d in ?? () from /usr/lib/apache2/modules/libphp5.so
#6  0x00007fa1fbd209fb in execute () from /usr/lib/apache2/modules/libphp5.so
#7  0x00007fa1fbcfbf60 in zend_execute_scripts () from /usr/lib/apache2/modules/libphp5.so
#8  0x00007fa1fbca85d3 in php_execute_script () from /usr/lib/apache2/modules/libphp5.so
#9  0x00007fa1fbd8b46d in ?? () from /usr/lib/apache2/modules/libphp5.so
#10 0x00007fa1ffa12508 in ap_run_handler ()
#11 0x00007fa1ffa1297e in ap_invoke_handler ()
#12 0x00007fa1ffa21c1c in ap_internal_redirect ()
#13 0x00007fa1f9f74635 in ?? () from /usr/lib/apache2/modules/mod_rewrite.so
#14 0x00007fa1ffa12508 in ap_run_handler ()
#15 0x00007fa1ffa1297e in ap_invoke_handler ()
#16 0x00007fa1ffa225b0 in ap_process_request ()
#17 0x00007fa1ffa1f3d8 in ?? ()
#18 0x00007fa1ffa18fa8 in ap_run_process_connection ()
#19 0x00007fa1ffa27210 in ?? ()
#20 0x00007fa1ffa2797a in ?? ()
#21 0x00007fa1ffa28527 in ap_mpm_run ()
#22 0x00007fa1ff9fd4a4 in main ()

看起来,使用curl会导致启动新的php会话。因为我使用一些遗留包括php代码,它做session_start(),但不使用session_write_close(),我可以理解,这样的进程不能结束。所以我把session_write_close()放在curl_init()调用之前,然后apache进程的数量仍然很低。

所有的curl调用都在工作,所有的http调用都成功,数据到达,等等。

所以我最后有几个没有回答的问题:

    为什么使用php curl会导致apache进程分叉?为什么php curl使用php_start_session(),即使在新的apache进程?
  • 如何使所有的curl函数都成功,但至少,如何才能HTTP传输是成功的,如果它需要一个fork apache的话进程,但在php_start_session()卡住?

我不认为你遇到的问题与curl的使用有任何关系。

关于会话的默认PHP配置是基于文件的会话存储机制。对文件的访问是排他的。这样做的效果是,每个会话一次只能由一个脚本使用。如果第二个脚本使用相同的会话id调用session_start(),它将在该调用时阻塞,直到第一个脚本完成其执行并关闭会话文件。结果将(或可能)是,你可能会看到等待过程的增加,特别是如果一个人试图一次又一次地访问网站,而所有请求都被阻止。

这个问题的解决方案是关闭会话处理程序,只要它不再需要(与session_write_close),特别是在耗时的任务(如发送一个文件与readfile()或执行长时间运行的CURL请求)。

所以你的解决方法对我来说似乎很好,只是解释方向错了。