DomenForum.net

DomenForum.net (https://domenforum.net/index.php)
-   Программирование (https://domenforum.net/forumdisplay.php?f=26)
-   -   PHP. Параллельные запросы (https://domenforum.net/showthread.php?t=210222)

Port_Artur 08.04.2017 11:40

PHP. Параллельные запросы
 
Исходные данные: VPS с 10-12 ядрами.

PHP код:

for( $i 1$i <= 10$i++ )

{

$content=file_get_contents("https://****/$i/***/");



Время выполнения цикла 3,65 секунды.

Задача.
Нужно все 10 file_get_contents выполнить одновременно, сократив время в 10 раз.

Вопрос.
Как?

pastuhoff 08.04.2017 13:39

Ищите по запросу "multicurl".

Port_Artur 08.04.2017 14:11

Попробовал:

curl_multi_init();

curl_multi_exec();

curl_multi_close();

Время:1,68 сек.

Прогресс есть, но всего в 2 раза быстрее.
Маловато.

добавлено через 29 минут
Первый раз был удачней. Сейчас стабильно 2 секунды.

Шуранов 08.04.2017 16:05

Ненулевая вероятность, что это время параллельного отклика. На ваши запросы должен сформироваться ответ, идущий, к тому-же через защищенное соединение.
Можете вместо curl_multi сделать pcntl_fork несколько раз, получите параллельное исполнение в виде нескольких процессов.

Port_Artur 08.04.2017 16:45

Шуранов, а как будет через pcntl_fork выглядеть вот этот пример:

PHP код:

$urls = array(
   
'http://www.google.ru/',
   
'http://www.altavista.com/',
   
'http://www.yahoo.com/'
    
);
$mh curl_multi_init();
foreach (
$urls as $i => $url) {
    
$conn[$i]=curl_init($url);
    
curl_setopt($conn[$i],CURLOPT_RETURNTRANSFER,1);  //ничего в браузер не давать
    
curl_setopt($conn[$i],CURLOPT_CONNECTTIMEOUT,10); //таймаут соединения
    
curl_multi_add_handle ($mh,$conn[$i]);
}
//Пока все соединения не отработают
do { curl_multi_exec($mh,$active); } while ($active);
//разбор полетов
for ($i 0$i count($urls); $i++) {
    
//ответ сервера в переменную
    
$res[$i] = curl_multi_getcontent($conn[$i]); 
    
curl_multi_remove_handle($mh$conn[$i]);
    
curl_close($conn[$i]);
}
curl_multi_close($mh);
print_r($res); 

Я и с curl_multi не работал никогда, просто нашёл пример удачный, а вот с pcntl_fork вообще никак.
Помогите пожалуйста.

Drow 08.04.2017 17:17

Попробуй неблокирующие сокеты. В сети есть примеры.

Port_Artur 08.04.2017 17:24

Направление, - это хорошо. Но лучше бы рабочий пример по условию темы.

Vitaliy 08.04.2017 20:14

Мне когда такое понадобилось - просто сделал дополнительный скрипт-запускалку параллельных процессов. Вот такой примерно:

PHP код:

<?php
for ($i=0;$i<10;$i++){
    
$headers="GET $path HTTP/1.1\r\n";
    
$headers .="Host: $host\r\n";
    
$headers .="Connection: Close\r\n\r\n";
        
    
$sock=fsockopen($host,80);
    
fputs($sock,$headers);
    
fclose($sock);
}
?>

$path - это адрес вашего скрипта с для которого нужны параллельные процессы.

Он за доли секунды запускает сколько указать в цикле параллельных процессов.

Port_Artur 08.04.2017 20:59

А $host ?

Полученные данные как сохранить?

PHP код:

$content=file_get_contents("https://****/$i/***/"); 


Vitaliy 08.04.2017 22:07

Цитата:

Сообщение от Port_Artur (Сообщение 1421295)
А $host ?

Полученные данные как сохранить?

PHP код:

$content=file_get_contents("https://****/$i/***/"); 


$host - это домен вашего сайта (или можно по ip).

А на счет сохранить - как вам надо так и сохраняете. Вариантов масса. Например, каждый поток может сохранять в свой файл. Чтобы названия файлов отличались можно вызывать эти потоки пронумеровано, например так:

PHP код:

<?php
$host
="domain.com"
$script_name="/script.php"//имя вашего скрипта

for ($i=0;$i<10;$i++){
    
    
$path=$script_name."?n=$i";
    
    
$headers="GET $path HTTP/1.1\r\n";
    
$headers .="Host: $host\r\n";
    
$headers .="Connection: Close\r\n\r\n";
        
    
$sock=fsockopen($host,80);
    
fputs($sock,$headers);
    
fclose($sock);
}
?>

А в свой вызываемый скрипт вносите дополнение, чтобы он определял с каким номером его вызвали и с тем же номером создавал файл. Всё просто и понятно вроде...

Port_Artur 09.04.2017 13:29

Здесь я результат запроса сохраняю в переменную.
Цитата:

$content=file_get_contents("https://****/$i/***/");
А в вашем примере, что сохранять в этой перменной?
:confused:

добавлено через 39 минут
Мне нужно получить данные с https:

https://адрес/чпу/

$host='адрес сайта без http://';
$path='чпу'

$headers="GET $path HTTPS/1.1\r\n"; - добавляю S

$content=$sock;

результат пустой ответ

добавлено через 50 минут
PHP код:

$host="сайт";  

for (
$i=0;$i<10;$i++){ 
     
    
$path=чпу
     
    
$headers="GET $path HTTP/1.1\r\n"
    
$headers .="Host: $host\r\n"
    
$headers .="Connection: Close\r\n\r\n"
         
    
$sock=fsockopen($host,80); 
    
fputs($sock,$headers); 
    
fclose($sock); 

$content[$i]=$sock;


добавлено через 51 минуту
В указанном примере пропусти S в HTTP , - у меня в примере S стоит

добавлено через 54 минуты
так тоже ответ пустой

PHP код:

    $sock=fsockopen($host,80);
    
fputs($sock,$headers);
    
$contrew[$i]=$sock;
    
fclose($sock); 


Vitaliy 09.04.2017 16:19

Port_Artur, судя по последним вопросам, вы совсем не поняли мою идею, как создавать параллельные запросы :(
Предложенный мной скрипт не качает информацию из сети, это делает ваш скрипт. А мой скрипт просто запускает N-ое раз ваш скрипт и эти N запушенных ваших скриптов параллельно качают, что вам надо.

Port_Artur 09.04.2017 16:46

Теперь-то я понял. Думаю вот, как мне это реализовать, чтобы результаты потом использовать в скрипте.

добавлено через 6 минут
Дело в том, что время критично, - поэтому лишние траты на запись в файл, потом его чтение, могут невилировать выигрыш по времени.

добавлено через 2 часа 28 минут
Максимальное время одного запроса 0,46 секунды, вот если бы сократить хотя бы до 0,5-0,6 сек. Было бы супер!

Vitaliy 09.04.2017 21:02

Так в файлы пишутся результаты, а запросы то вы быстро отправите и получите. Плюс vps на SSD дисках пошустрее будут. Плюс еще можно ваш скрипт пробовать ускорить. Например, когда CURL хочет открыть какую-то страницу, он предварительно обращается к DNS чтобы узнать ip. А вы можете этот ip заранее определить, вбить в настройки соединения и в итоге без обращения к DNS получится чуть быстрее.
Еще в ваш скрипт можно попробовать всунуть функцию времени ожидания: например потоки запускаем заранее (за минуту или несколько секунд до часа Х), далее они просто ждут уже активированные в памяти сервера, а в нужную миллисекунду фигачат. Так вообще сверхскорость можно получить.
Можно и другие способы ускорения придумать.

Port_Artur 09.04.2017 21:43

Десятки посетителей сайтов одновременно, страниц сотни таких запросов в 10 раз больше. Не понимаю как хранить столько файлов, под каким именем, как разбирать потом нужные?

Vitaliy 09.04.2017 23:04

Я вообще думал вы домены с такой скоростью хотите перехватывать :) А файлы я в качестве примера привел. Но если вам файлы не нравятся - используйте базу данных.

ekubachev 10.04.2017 00:31

Цитата:

Сообщение от Port_Artur (Сообщение 1421372)
Максимальное время одного запроса 0,46 секунды, вот если бы сократить хотя бы до 0,5-0,6 сек.

Это не сократить получается, а увеличить. 0.5-0.6 > 0.46

Port_Artur 10.04.2017 00:47

Цитата:

Задача.
Нужно все 10 file_get_contents выполнить одновременно, сократив время в 10 раз.
запросов 10

речь об общем времени

ibatanov 21.05.2017 21:56

Цитата:

Сообщение от Port_Artur (Сообщение 1421440)
запросов 10
речь об общем времени

Возможно вы выбрали не верный стек технологий под свою задачу. Попробуйте посмотреть на более производительные языки в качестве "прослойки" для запросов. Например java+spring.


Текущее время: 01:58. Часовой пояс GMT +4.

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Техническая поддержка — DevArt.PRO. Перевод: zCarot.