I have a big problem with an apache server, php app.
The server is serving a quite high traffic website which is running with php.
Every 24h or 48h, apache hangs, and i have to reboot it to be able to access the website again. I have to reboot it, because apache reaches the maximum number of allowed processes/servers (16000 for me), and it cannot free other processes because other processes are all active.
The website hosted on this server is a php app, that serve a file at the end: let say it is a download server.
Files are requested by the browser via a form that submit a POST request.
The problem is that this post request seems to never end (i can see that nearly all the 16000 processes on my server status are POST requests).
Files that are served are big files (10M to 2G), and i serve them with php readfile function (i don't want to serve them with a href link, so i use a form POST request so that the user never see where the file is on my filesystem).
The function that use php readfile seems to never end even if i use exit() at the end of it (see code snipet below).
I am asking here for a way to avoid this never ending POST requests that are caused by my php code. I want to keep POST way of serving files.
First my conf:
my mpm_prefork.conf file:
<IfModule mpm_prefork_module>
StartServers 512
MinSpareServers 512
MaxSpareServers 1024
ServerLimit 16000 # no problem with my server ram
MaxRequestWorkers 16000
MaxConnectionsPerChild 10000
</IfModule>
my apache2.conf file:
...
Timeout 300
KeepAlive On
MaxKeepAliveRequests 500
KeepAliveTimeout 5
...
My php.ini file:
max_execution_time = 7200
my apache log files: nothing interesting for my problem
A munin graph that shows when the issue happens:
My apache server status at looks like that:
And my server class (the code that is causing the issue):
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();
}
}
Does someone has a solution to avoid the never ending POST requests? I am ok to serve files via other thing than php if it can solve the issue.
Please no duplicate, i have added enough code, conf snippet and pictures to make this question specific :)
mod_xsendfile is a good alternative to PHP delivering files.
https://tn123.org/mod_xsendfile/
Else you could simply add a timelimit to your PHP script, so it cannot run forever.
http://php.net/manual/de/function.set-time-limit.php
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With