PHP readfile () никогда не заканчивается и заставляет сервер Apache зависать

У меня большая проблема с сервером Apache, приложением php.

Сервер обслуживает сайт с довольно высоким трафиком, который работает с php.

Каждые 24 часа или 48 часов зависает apache, и мне приходится перезагружать его, чтобы снова получить доступ к веб-сайту. Я должен перезагрузить его, потому что apache достигает максимального количества разрешенных процессов / серверов (16000 для меня), и он не может освободить другие процессы, потому что все другие процессы активны.

Веб-сайт, размещенный на этом сервере, является приложением php, которое в конце концов обслуживает файл: допустим, это сервер загрузки.

Файлы запрашиваются браузером через форму, которая отправляет запрос POST.

Проблема в том, что этот почтовый запрос никогда не заканчивается (я вижу, что почти все 16000 процессов на моем сервере являются запросами POST).

Файлы, которые обслуживаются, представляют собой большие файлы (от 10M до 2G), и я передаю их с помощью функции php readfile (я не хочу предоставлять им ссылку href, поэтому я использую запрос POST формы, чтобы пользователь никогда не видел, где находится файл находится в моей файловой системе).

Функция, использующая php readfile, кажется, никогда не завершится, даже если я использую exit () в конце (см. Фрагмент кода ниже).

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

Сначала мой конф:

  • Ubuntu сервер 14.04
  • Apache 2.4 с MPM Prefork
  • php 5.5.9 (мод php)
  • аппаратное обеспечение: 128G RAM

мой файл mpm_prefork.conf:

<IfModule mpm_prefork_module>
StartServers              512
MinSpareServers           512
MaxSpareServers          1024
ServerLimit             16000 # no problem with my server ram
MaxRequestWorkers       16000
MaxConnectionsPerChild  10000
</IfModule>

мой файл apache2.conf:

...
Timeout 300
KeepAlive On
MaxKeepAliveRequests 500
KeepAliveTimeout 5
...

Мой файл php.ini:

max_execution_time = 7200

мои файлы журнала apache: ничего интересного для моей проблемы

Мунинский график, показывающий, когда возникает проблема:
введите описание изображения здесь

Состояние моего сервера Apache выглядит следующим образом:
введите описание изображения здесь

введите описание изображения здесь

И мой класс сервера (код, который вызывает проблему):

class Server
{
/* the file is served from a remote url source */
public function serveFileFromUrl()
{
if (empty($_POST)) {
return;
}

$url  = $_POST['file_url'];
$mime = $_POST['mime'];
$name = sanitizeFileName($_POST['name']) . uniqid() . '.' . $mime;
$size = $_POST['size'];

if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) {

// for Internet Explorer
if ($mime == 'mp3') {
header('Content-Type: "audio/' . $mime . '"');
} else {
header('Content-Type: "video/' . $mime . '"');
}
header('Content-disposition: attachment; filename="' . $name . '"');
header('Expires: 0');
if ($size !== '') {
header('Content-Length: ' . $size);
}
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-Transfer-Encoding: binary");
header('Pragma: public');

} else {

// not for internet Explorer
if ($mime == 'mp3') {
header('Content-Type: "audio/' . $mime . '"');
} else {
header('Content-Type: "video/' . $mime . '"');
}
header('Content-disposition: attachment; filename="' . $name . '"');
header('Expires: 0');
if ($size !== '') {
header('Content-Length: ' . $size);
}
header("Content-Transfer-Encoding: Binary");
header('Pragma: no-cache');

}

ob_end_clean(); // fix memory problems with readfile (http://heap.tumblr.com/post/119127049/a-note-about-phps-output-buffer-and-readfile)
flush();        // fix memory problems with readfile
readfile($url);
@ob_end_flush();
exit();
}

/* file is served from my filesystem */
public function serveFileFromPath()
{
if (empty($_POST)) {
return;
}

$url  = APP_PATH . '/download/' . $_POST['file_name'];
$mime = $_POST['mime'];
$name = sanitizeFileName($_POST['name']) . '-' . uniqid() . '.' . $mime;
$size = $_POST['size'];

if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) {

// for Internet Explorer
if ($mime == 'mp3') {
header('Content-Type: "audio/' . $mime . '"');
} else {
header('Content-Type: "video/' . $mime . '"');
}
header('Content-disposition: attachment; filename="' . $name . '"');
header('Expires: 0');
if ($size !== '') {
header('Content-Length: ' . $size);
}
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-Transfer-Encoding: binary");
header('Pragma: public');

} else {

// not for internet Explorer
if ($mime == 'mp3') {
header('Content-Type: "audio/' . $mime . '"');
} else {
header('Content-Type: "video/' . $mime . '"');
}
header('Content-disposition: attachment; filename="' . $name . '"');
header('Expires: 0');
if ($size !== '') {
header('Content-Length: ' . $size);
}
header("Content-Transfer-Encoding: Binary");
header('Pragma: no-cache');

}

ob_end_clean(); // fix memory problems with readfile (http://heap.tumblr.com/post/119127049/a-note-about-phps-output-buffer-and-readfile)
flush();        // fix memory problems with readfile
readfile($url);
@ob_end_flush();
exit();
}
}

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

Пожалуйста, не дублируйте, я добавил достаточное количество кода, фрагмент кода и картинки, чтобы конкретизировать этот вопрос 🙂

9

Решение

mod_xsendfile — хорошая альтернатива доставке файлов на PHP.

https://tn123.org/mod_xsendfile/

В противном случае вы можете просто добавить ограничение времени к вашему сценарию PHP, чтобы он не мог работать вечно.

http://php.net/manual/de/function.set-time-limit.php

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]