php curl localhost在发出并发请求时很慢

我发现一个有趣的问题,我不确定的根本原因。 我有一台服务器和两个虚拟主机A和B,端口分别为80和81。 我写了一个简单的PHP代码,看起来像这样

<?php echo "from A server\n"; 

另一个简单的PHP代码在B服务器上

 <?php echo "B server:\n"; // create curl resource $ch = curl_init(); // set url curl_setopt($ch, CURLOPT_URL, "localhost:81/a.php"); //return the transfer as a string curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // $output contains the output string $output = curl_exec($ch); // close curl resource to free up system resources curl_close($ch); echo $output; 

当使用ab进行并发请求时,我得到以下结果:

 ab -n 10 -c 5 http://192.168.10.173/b.php This is ApacheBench, Version 2.3 <$Revision: 1706008 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking 192.168.10.173 (be patient).....done Server Software: nginx/1.10.0 Server Hostname: 192.168.10.173 Server Port: 80 Document Path: /b.php Document Length: 26 bytes Concurrency Level: 5 Time taken for tests: 2.680 seconds Complete requests: 10 Failed requests: 0 Total transferred: 1720 bytes HTML transferred: 260 bytes Requests per second: 3.73 [#/sec] (mean) Time per request: 1340.197 [ms] (mean) Time per request: 268.039 [ms] (mean, across all concurrent requests) Transfer rate: 0.63 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.1 0 1 Processing: 2 1339 1408.8 2676 2676 Waiting: 2 1339 1408.6 2676 2676 Total: 3 1340 1408.8 2676 2677 Percentage of the requests served within a certain time (ms) 50% 2676 66% 2676 75% 2676 80% 2676 90% 2677 95% 2677 98% 2677 99% 2677 100% 2677 (longest request) 

但是使1000个并发级别为1的请求速度非常快:

 $ ab -n 1000 -c 1 http://192.168.10.173/b.php This is ApacheBench, Version 2.3 <$Revision: 1706008 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking 192.168.10.173 (be patient) Completed 100 requests Completed 200 requests Completed 300 requests Completed 400 requests Completed 500 requests Completed 600 requests Completed 700 requests Completed 800 requests Completed 900 requests Completed 1000 requests Finished 1000 requests Server Software: nginx/1.10.0 Server Hostname: 192.168.10.173 Server Port: 80 Document Path: /b.php Document Length: 26 bytes Concurrency Level: 1 Time taken for tests: 1.659 seconds Complete requests: 1000 Failed requests: 0 Total transferred: 172000 bytes HTML transferred: 26000 bytes Requests per second: 602.86 [#/sec] (mean) Time per request: 1.659 [ms] (mean) Time per request: 1.659 [ms] (mean, across all concurrent requests) Transfer rate: 101.26 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.1 0 1 Processing: 1 1 10.3 1 201 Waiting: 1 1 10.3 1 201 Total: 1 2 10.3 1 201 Percentage of the requests served within a certain time (ms) 50% 1 66% 1 75% 1 80% 1 90% 1 95% 1 98% 1 99% 2 100% 201 (longest request) 

谁能解释为什么会发生这种情况 我真的想知道根本原因。 这是curl的问题吗? 它并不像networking瓶颈或开放文件的问题,因为并发只是5.顺便说一句,我也尝试与guzzlehttp同样的事情,但结果是一样的。 我在笔记本电脑上使用ab,服务器位于同一本地networking中。 另外,它与networking带宽无关,因为主机A和B之间的请求是在本地主机完成的。


我修改了代码,所以我们可以更灵活地testing它。

 <?php require 'vendor/autoload.php'; use GuzzleHttp\Client; $opt = 1; $url = 'http://localhost:81/a.php'; switch ($opt) { case 1: // create curl resource $ch = curl_init(); // set url curl_setopt($ch, CURLOPT_URL, $url); //return the transfer as a string curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // $output contains the output string $output = curl_exec($ch); curl_close($ch); echo $output; break; case 2: $client = new Client(); $response = $client->request('GET', $url); echo $response->getBody(); break; case 3: echo file_get_contents($url); break; default: echo "no opt"; } echo "app server:\n"; 

我尝试了file_get_contents,但切换到file_get_contents时没有明显的区别。 当并发性为1时,所有方法都是好的。 但是,当并发性增加时,它们都开始降级。


我想我发现有关这个问题,所以我只是发表另一个问题并发curl不能parsing主机 。 这可能是根本原因,但我还没有任何答案。


经过这么长时间以后,我认为这与名称parsing无关。 这里是可以在500级同时执行的php脚本

 <?php require 'vendor/autoload.php'; use GuzzleHttp\Client; $opt = 1; $url = 'http://localhost:81/a.php'; switch ($opt) { case 1: // create curl resource $ch = curl_init(); // set url curl_setopt($ch, CURLOPT_URL, $url); //return the transfer as a string curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_PROXY, 'localhost'); // $output contains the output string $output = curl_exec($ch); curl_close($ch); echo $output; break; case 2: $client = new Client(); $response = $client->request('GET', $url, ['proxy' => 'localhost']); echo $response->getBody(); break; case 3: echo file_get_contents($url); break; default: echo "no opt"; } echo "app server:\n"; 

真正重要的是curl_setopt($ch, CURLOPT_PROXY, 'localhost');$response = $client->request('GET', $url, ['proxy' => 'localhost']); 。 它告诉curl使用localhost作为代理。

这里是abtesting的结果

 ab -n 1000 -c 500 http://192.168.10.173/b.php This is ApacheBench, Version 2.3 <$Revision: 1528965 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking 192.168.10.173 (be patient) Completed 100 requests Completed 200 requests Completed 300 requests Completed 400 requests Completed 500 requests Completed 600 requests Completed 700 requests Completed 800 requests Completed 900 requests Completed 1000 requests Finished 1000 requests Server Software: nginx/1.10.0 Server Hostname: 192.168.10.173 Server Port: 80 Document Path: /b.php Document Length: 182 bytes Concurrency Level: 500 Time taken for tests: 0.251 seconds Complete requests: 1000 Failed requests: 184 (Connect: 0, Receive: 0, Length: 184, Exceptions: 0) Non-2xx responses: 816 Total transferred: 308960 bytes HTML transferred: 150720 bytes Requests per second: 3985.59 [#/sec] (mean) Time per request: 125.452 [ms] (mean) Time per request: 0.251 [ms] (mean, across all concurrent requests) Transfer rate: 1202.53 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 6 4.9 5 14 Processing: 9 38 42.8 22 212 Waiting: 8 38 42.9 22 212 Total: 11 44 44.4 31 214 Percentage of the requests served within a certain time (ms) 50% 31 66% 37 75% 37 80% 38 90% 122 95% 135 98% 207 99% 211 100% 214 (longest request) 

但是,仍然为什么在不使用本地主机作为代理时,并发级别5名称parsing失败?


虚拟主机设置非常简单,干净,几乎所有的设置都是默认configuration。 我不在这个服务器上使用iptables,我也没有configuration任何特殊的东西。

 server { listen 81 default_server; listen [::]:81 default_server; root /var/www/html; index index.html index.htm index.nginx-debian.html; server_name _; location / { try_files $uri $uri/ =404; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php7.0-fpm.sock; } } 

找点有意思的东西 如果您在大约3秒钟之后在第一个testing之后再进行一次abtesting。 第二个abtesting很快。

不使用本地主机作为代理

 ab -n 10 -c 5 http://192.168.10.173/b.php <-- This takes 2.8 seconds to finish. ab -n 10 -c 5 http://192.168.10.173/b.php <-- This takes 0.008 seconds only. 

使用本地主机作为代理

 ab -n 10 -c 5 http://192.168.10.173/b.php <-- This takes 0.006 seconds. ab -n 10 -c 5 http://192.168.10.173/b.php <-- This takes 0.006 seconds. 

我认为这仍然意味着问题是解决名称问题。 但为什么?


假设:nginx不听localhost:81

我试着添加listen 127.0.0.1:81; 到nginx,并没有显示任何效果。

发现自己在使用curl代理时犯了一些错误, 这是行不通的! 稍后更新其他细节。


解决,不涉及代理,或任何东西。 根本原因是php-fpm的www.conf pm.start_servers

好吧,经过这么多天的试图解决这个问题,我终于明白了为什么。 这不是名称解析。 我不能相信需要这么多天才能pm.start_servers php-fpm的www.confpm.start_servers数量的根本原因。 最初,我将pm.start_servers的数量设置为3,这就是为什么本地主机的ab测试在并发级别3之后总是变差的原因。 虽然php-cli没有限制php进程的数量,因此,php-cli总是表现的很好。 在将pm.start_servers增加到5之后,ab测试结果与php-cli一样快。 如果这是你的php-fpm速度慢的原因,你也应该考虑改变pm.min_spare_serverspm.max_spare_serverspm.max_children和其他相关的数量。