我正在开发一个php脚本,它使用curl对另一台服务器进行数千次http调用。我注意到在运行类似于下面的php代码时,apache进程的数量不断增加:
$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(),我可以理解这样的进程无法结束。所以我在curl_init()调用之前放了session_write_close(),然后apache进程的数量仍然很低。
所有curl调用都正常,所有http调用都成功,数据到达等等。
所以我最后得到了几个悬而未决的问题:
答案 0 :(得分:1)
我不认为您遇到的问题与curl的使用有关。
有关会话的默认PHP配置是基于文件的会话存储机制。访问文件是独家的。这样做的结果是每个会话一次只能由一个脚本使用。如果第二个脚本使用相同的会话ID调用session_start()
,它将在该调用时阻塞,直到第一个脚本完成其执行并关闭会话文件。结果将(或可能)是您可能会看到等待进程的增加,特别是如果在所有请求都阻止的情况下一次又一次地尝试访问该网站。
此问题的解决方案是在不再需要会话处理程序时(使用session_write_close
)关闭会话处理程序,尤其是在耗时的任务之前(例如发送readfile()
文件或执行长文件运行CURL请求)。
因此,你的解决方案对我来说似乎很好,只是解释方向错误。