Я нахожу интересную проблему, о которой я не уверен в первопричине. У меня есть сервер и два виртуальных хоста A и B с портом на 80 и 81 соответственно. Я пишу простой код PHP на А, который выглядит следующим образомphp curl localhost медленный при одновременных запросах
<?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 -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, все методы хороши. Но все они начинают понижаться, когда увеличивается параллелизм.
Я думаю, что найти что-то связанное с этим вопросом, так что я просто опубликовать еще один вопрос concurrent curl could not resolve host. Это может быть основной причиной, но у меня пока нет ответа.
После долгих попыток, я думаю, что это определенно связано с разрешением имени. А вот скрипт, который может выполняться на уровне параллельного 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 -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 не слушает локальный хост: 81
Я попытался добавить listen 127.0.0.1:81;
в Nginx, и он не проявляет никакого эффекта.
Обнаружение ошибок при использовании curl proxy, , что не работает! Обновите другие детали позже.
Решенный, не имеющий отношения к прокси-серверу или чему-либо еще. Основной причиной является pm.start_servers
в php-fpm's www.conf
.
Это радикально изменится, если вы используете другой уровень параллелизма (например, 2) или URL fopen() вместо этого (например, file_get_contents («http: // localhost: 81/a.php»);)? –
@BJBlack at concurrcy = 2,3,4,5, время 0,018 с, 0,87 с, 1,75 с, 2,42 с соответственно. Я подозреваю, что это имеет какое-то отношение к низкоуровневому поведению Linux. – cwhsu
@cwhsu В этом случае вы можете сжать linux в качестве тега – Goose