У меня большая проблема с сервером Apache, приложением php.
Сервер обслуживает сайт с довольно высоким трафиком, который работает с php.
Каждые 24 часа или 48 часов зависает apache, и мне приходится перезагружать его, чтобы снова получить доступ к веб-сайту. Я должен перезагрузить его, потому что apache достигает максимального количества разрешенных процессов / серверов (16000 для меня), и он не может освободить другие процессы, потому что все другие процессы активны.
Веб-сайт, размещенный на этом сервере, является приложением php, которое в конце концов обслуживает файл: допустим, это сервер загрузки.
Файлы запрашиваются браузером через форму, которая отправляет запрос POST.
Проблема в том, что этот почтовый запрос никогда не заканчивается (я вижу, что почти все 16000 процессов на моем сервере являются запросами POST).
Файлы, которые обслуживаются, представляют собой большие файлы (от 10M до 2G), и я передаю их с помощью функции php readfile (я не хочу предоставлять им ссылку href, поэтому я использую запрос POST формы, чтобы пользователь никогда не видел, где находится файл находится в моей файловой системе).
Функция, использующая php readfile, кажется, никогда не завершится, даже если я использую exit () в конце (см. Фрагмент кода ниже).
Я прошу здесь, чтобы избежать этого бесконечного POST-запроса, вызванного моим php-кодом. Я хочу сохранить POST способ подачи файлов.
Сначала мой конф:
мой файл 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, если это может решить проблему.
Пожалуйста, не дублируйте, я добавил достаточное количество кода, фрагмент кода и картинки, чтобы конкретизировать этот вопрос 🙂
mod_xsendfile — хорошая альтернатива доставке файлов на PHP.
https://tn123.org/mod_xsendfile/
В противном случае вы можете просто добавить ограничение времени к вашему сценарию PHP, чтобы он не мог работать вечно.
Других решений пока нет …