php curl localhost медленен при выполнении параллельных запросов

Я нахожу интересный вопрос, который я не уверен в первопричине. У меня есть сервер и два виртуальных хоста A и B с портом на 80 и 81 соответственно. Я пишу простой код php на A, который выглядит так

<?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) 

Может ли кто-нибудь объяснить, почему это произошло? Я действительно хочу знать причину. Это проблема скручивания? Он не похож на узкое место в сети или проблему с открытым файлом, так как параллелизм составляет всего 5. Кстати, я также пытаюсь сделать то же самое с guzzlehttp, но результат тот же. Я использую ab на своем ноутбуке, и сервер находится в одной локальной сети. Кроме того, это, безусловно, не имеет ничего общего с пропускной способностью сети, поскольку запросы между хостами A и B выполняются на локальном хосте.


Я изменяю код, поэтому мы можем проверить его более гибко.

 <?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, все методы хороши. Но все они начинают понижаться, когда увеличивается параллелизм.


Я думаю, что я нашел что-то, связанное с этой проблемой, поэтому я просто отправляю другой вопрос, параллельный завиток не может решить хост . Это может быть основной причиной, но у меня пока нет ответа.


Попытавшись так долго, я думаю, что это определенно связано с разрешением имени. И вот скрипт php, который может выполняться на параллельном уровне 500

 <?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 как прокси.

И вот результат теста ab

 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, если не использовать localhost как прокси?


Настройка виртуального хоста очень простая и чистая, и почти все в конфигурации по умолчанию. Я не использую iptables на этом сервере, ни я ничего не настраиваю.

 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; } } 

Найдите что-нибудь интересное! Если вы выполните еще один тест ab сразу после первого за 3 секунды. Второй тест ab довольно быстрый.

Без использования localhost в качестве прокси

 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. 

Использование localhost в качестве прокси-сервера

 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 proxy, это не работает! Обновите другие детали позже.


Решено, не связано с прокси-сервером или что-то еще. Основной причиной является pm.start_servers в php- www.conf в www.conf .

Хорошо, после стольких дней, пытаясь решить эту проблему, я наконец узнаю, почему. И это не разрешение имен. Я не могу поверить, что для отслеживания основной причины, которая является числом pm.start_servers в php- www.conf 's www.conf , www.conf . Первоначально я установил число pm.start_servers на 3, поэтому тест ab на localhost всегда ухудшается после уровня параллелизма 3 . Хотя php-cli не имеет проблемы с ограниченным числом php-процессов, php-cli всегда отлично работает. После увеличения значения pm.start_servers до 5 результат теста ab выполняется так же быстро, как и php-cli. Если это причина, по которой ваш php-fpm медленный, вы также должны подумать об изменении числа pm.min_spare_servers , pm.max_spare_servers , pm.max_children и всего, что связано.