Для ускорения работы программы широко применяется практика асинхронного выполнения задач. Это значит, что операции выполняются непоследовательно, отложенно.
Выбор асинхронного решения всегда нетривиален, особенно в случае выполнения PHP.
Если в качестве веб-сервера используется Nginx, то к вашим услугам отличный менеджер процессов FastCGI (FPM).
К примеру, отправка почты в асинхронном режиме будет выглядеть так:
$to = $_POST['email'];
if ( $to )
{
echo ‘Подтверждение отправлено на почту’;
**fastcgi_finish_request();
mail($to, ‘Подтверждение’, ‘Это ваш ящик?’);**
}
else
{
echo ‘Введены не все данные’;
}
## После вызова fastcgi_finish_request() посетитель сразу увидит ответ от сервера
Больше настроек и примеров в материале Асинхронность в PHP и FPM.
По умолчанию сокет открывается в блокирующем режиме, то есть дожидается полного соединения, прежде чем возвратить значение. Так что для выполнения асинхронных вызовов пригодится дополнительная директива socket_set_nonblock:
function multiHTTP ($urlArr) {
$sockets = Array(); // массив сокетов
$urlInfo = Array();
$retDone = Array();
$retData = Array();
$errno = Array();
$errstr = Array();
for ($x=0;$x<count($urlArr);$x++) {
$urlInfo[$x] = parse_url($urlArr[$x]);
$urlInfo[$x][port] = ($urlInfo[$x][port]) ? $urlInfo[$x][port] : 80;
$urlInfo[$x][path] = ($urlInfo[$x][path]) ? $urlInfo[$x][path] : “/”;
$sockets[$x] = fsockopen($urlInfo[$x][host], $urlInfo[$x][port],
$errno[$x], $errstr[$x], 30);
**socket_set_nonblock($sockets[$x]); **
$query = ($urlInfo[$x][query]) ? “?” . $urlInfo[$x][query] : “”;
fputs($sockets[$x],”GET ” . $urlInfo[$x][path] . “$query HTTP/1.0rnHost: ” .
$urlInfo[$x][host] . “rnrn”);
}
// чтение данных
$done = false;
while (!$done) {
for ($x=0; $x < count($urlArr);$x++) {
if (!feof($sockets[$x])) {
if ($retData[$x]) {
$retData[$x] .= fgets($sockets[$x],128);
} else {
$retData[$x] = fgets($sockets[$x],128);
}
} else {
$retDone[$x] = 1;
}
}
$done = (array_sum($retDone) == count($urlArr));
}
return $retData;
}
?>
## Функция подключается к массиву URL-ов в асинхронном режиме и возвращает массив результатов
Также можно задействовать неблокирующий режим потока. Для этого используется функция stream_set_blocking . К примеру в неблокирующем режиме вызов fgets() будет сразу возвращаться, не дожидаясь доступности всех данных на потоке.
Небольшой пример использования:
function call_url($url) {
$fp = fopen($url, ‘r’);
**stream_set_blocking($fp, 0);**
$data = fread($fp, 8192);
fclose($fp);
return strlen($data);
}
## Вызов url и моментальный возврат ответа, удобно для запуска других скриптов
Для запуска фоновых процессов curl можно использовать exec. Простой пример выполнения будет выглядеть так:
## Запрос выполняется почти моментально (50 мс), а в фоне запускается нужный длинный скрипт
Процессы curl также можно запустить из под командной оболочки:
curl -X POST -H 'Content-Type: application/json'
-d ‘{“batch”:[{“userId”:”some_user”,”event”:”PHP Fork Event”,”timestamp”:”2016-05-16T14:34:50-08:00″,”context”:{“library”:”analytics-php”},”action”:”track”}]}’
‘https://api.somesite.com/import’ > /dev/null 2>&1 &
## Запуск и раздвоение скрипта
Для PHP есть многопоточное расширение [http://pthreads.org/ pthreads].
Оно не входит в ядро PHP, так что его нужно установить:
pecl install pthreads
## Расширение доступно в репозитории PECL и совместимо с ZTS
Простейший пример для проверки работоспособности расширения будет выглядеть так:
}
public function run(){
while(true){
echo “Worker {$this->i} ran” . PHP_EOL;
sleep(1);
}
}
}
for($i=0;$i<7;$i++){
**$workers[$i]=new workerThread($i);**
$workers[$i]->start();
}
?>
## Вывод номеров воркеров в 8 потоков
Если веб-приложение большое, то логичнее воспользоваться сервером очередей, который даст больше возможностей и функций.
Например Gearman, который содержит множество клиентов, в том числе для PHP. С его помощью достаточно легко реализовать асинхронные операции, как отправку почты.
Выбор метода асинхронного выполнения полностью зависит от ваших задач. Но самыми производительными и надежными будут решения с использованием модуля PHP-FPM и сервера очередей.
Прокси (proxy), или прокси-сервер — это программа-посредник, которая обеспечивает соединение между пользователем и интернет-ресурсом. Принцип…
Согласитесь, было бы неплохо соединить в одно сайт и приложение для смартфона. Если вы еще…
Повсеместное распространение смартфонов привело к огромному спросу на мобильные игры и приложения. Миллиарды пользователей гаджетов…
В перечне популярных чат-ботов с искусственным интеллектом Google Bard (Gemini) еще не пользуется такой популярностью…
Скрипт (англ. — сценарий), — это небольшая программа, как правило, для веб-интерфейса, выполняющая определенную задачу.…
Дедлайн (от англ. deadline — «крайний срок») — это конечная дата стачи проекта или задачи…