बनाता है मुझे अपाचे सर्वर, php ऐप के साथ एक बड़ी समस्या है।PHP readfile() कभी समाप्त नहीं होता है और अपाचे सर्वर को
सर्वर एक बहुत अधिक यातायात वेबसाइट की सेवा कर रहा है जो php के साथ चल रहा है।
हर 24h या 48h, apache hangs, और मुझे वेबसाइट को फिर से एक्सेस करने में सक्षम होने के लिए इसे रीबूट करना होगा। मुझे इसे रीबूट करना है, क्योंकि अपाचे अधिकतम प्रक्रियाओं/सर्वरों (मेरे लिए 16000) तक पहुंचता है, और यह अन्य प्रक्रियाओं को मुक्त नहीं कर सकता है क्योंकि अन्य प्रक्रियाएं सभी सक्रिय हैं।
इस सर्वर पर होस्ट की गई वेबसाइट एक php ऐप है, जो अंत में एक फ़ाइल की सेवा करती है: मान लें कि यह एक डाउनलोड सर्वर है।
ब्राउज़र द्वारा उन अनुरोधों के माध्यम से अनुरोध किया जाता है जो POST अनुरोध सबमिट करते हैं।
समस्या यह है कि यह पोस्ट अनुरोध कभी खत्म नहीं होता है (मैं देख सकता हूं कि मेरी सर्वर स्थिति पर लगभग सभी 16000 प्रक्रियाएं POST अनुरोध हैं)।
सेवा की जाने वाली फ़ाइलें बड़ी फ़ाइलें (10 एम से 2 जी) हैं, और मैं उन्हें php readfile फ़ंक्शन के साथ सेवा करता हूं (मैं उन्हें एक href लिंक के साथ सेवा नहीं करना चाहता, इसलिए मैं एक फॉर्म POST अनुरोध का उपयोग करता हूं ताकि उपयोगकर्ता कभी नहीं देखता कि फ़ाइल मेरे फाइल सिस्टम पर कहां है)।
फ़ंक्शन रीडफ़ाइल का उपयोग करने वाला फ़ंक्शन कभी भी समाप्त नहीं होता है, भले ही मैं इसके अंत में बाहर निकलें() का उपयोग करता हूं (नीचे कोड स्निपेट देखें)।
मैं यहां अपने PHP कोड के कारण होने वाले कभी भी समाप्त होने वाले POST अनुरोधों से बचने के लिए यहां नहीं कह रहा हूं। मैं फाइलों की सेवा करने का सबसे अच्छा तरीका रखना चाहता हूं।
सबसे पहले मेरी conf:
- उबंटू सर्वर 14.04
- अपाचे 2.4 mpm prefork साथ
- php 5.5.9 (आधुनिक php)
- हार्डवेयर: 128 जी रैम
मेरी 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
मेरी अपाचे लॉग फाइल: कुछ भी नहीं मेरी समस्या
एक Munin ग्राफ पता चलता है कि जब इस मुद्दे को होता है के लिए दिलचस्प:
मेरे अपाचे सर्वर स्थिति ऐसा लगता है:
और अपने सर्वर वर्ग (कोड है कि समस्या पैदा कर रहा है):
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();
}
}
कोई एक समाधान कभी नहीं खत्म होने वाली पोस्ट अनुरोध से बचने के लिए किया गया है है? यदि मैं इस मुद्दे को हल कर सकता हूं तो php की तुलना में अन्य चीज़ों के माध्यम से फ़ाइलों को सेवा देना ठीक है।
कृपया कोई डुप्लिकेट, मैं इस सवाल का विशिष्ट :)
एक आसान तरीका है कि कोड के 50% से छुटकारा पाने के एक http रीडायरेक्ट, उर्फ हैडर स्थान के साथ serveFileFromUrl() भाग को बदलने के लिए किया जाएगा। यह किसी भी किस्मत के साथ आपकी समस्या को भी ठीक कर सकता है। – Calimero
आपने अपना टाइमिलिमिट 0 पर सेट कर दिया है। टीआईएस निश्चित रूप से एक फिक्स नहीं है, लेकिन इसे 10 घंटों की तरह सेट करें, यह आपके सर्वर को जीवित रखेगा, भले ही कुछ ऐसा विफल हो जाए, और अब, यह संभवतः, आप जो करते हैं उसके साथ गड़बड़ नहीं करते हैं। एक स्क्रिप्ट लेते समय आपको दोगुना सेट करें। – Elentriel
@Calimero अगर मैं केवल हेडर का उपयोग करता हूं स्थान, फ़ाइल (यह एक वीडियो फ़ाइल है) ब्राउज़र में खेला जाता है। मैं फ़ाइल को डाउनलोड करना चाहता हूं। – hedi