2015-09-01 37 views
1

嘗試在新的共享服務器帳戶上運行一些PHP腳本,腳本經常掛起並超時而沒有錯誤消息。只有在使用Web開發者控制檯運行Chrome中的腳本時,我纔會得到一些提示:「net :: ERR_INCOMPLETE_CHUNKED_ENCODING」就是這樣說的。錯誤:在PHP腳本中不完整的塊編碼

Fiddler2略有更具體:

Fiddler.Network.ProtocolViolation - [#165]傳輸編碼:分塊的響應沒有用正確的零大小的塊終止。

...和:

Fiddler.Network.ProtocolViolation - [#165] [HTTPLint#M012該HTTP響應分塊體是不完全的;最有可能缺乏最終的0尺寸塊。

我做了一個測試腳本來演示這個問題。它所做的只是隨機20-60秒的sleep(),然後顯示一個隨機字符串。默認情況下爲10次迭代。

但是這個託管服務提供商的服務檯一直堅持認爲它與php環境中的60秒超時有關,我知道這是hogwash。所以我放了第二個測試腳本,它使用Ajax連續多次調用另一個腳本。再一次,它是簡單的骨頭,只是一個睡眠(),隨機時間在40到55秒之間,然後生成並顯示一個短的隨機字符串。

因此,執行永遠不會超過60秒。但它仍然保持失敗,儘管在Chrome控制檯中xhr調用的「net :: ERR_EMPTY_RESPONSE」而不是「net :: ERR_INCOMPLETE_CHUNKED_ENCODING」。

當我向他們展示這件事時,他們實際上承認存在一個問題,這感覺像是一場勝利。但它是短暫的。第二天,他們回來說,很抱歉,他們無法弄清楚是什麼原因造成的,他們無能爲力,我是否考慮升級到vps?

我已經變得有點癡迷了。我想知道這究竟是什麼造成的。

第一個測試腳本代碼中,我寫道:

<?php 

set_time_limit(3600); 
error_reporting(E_ALL); 
ini_set('display_errors', TRUE); 
ini_set('display_startup_errors', TRUE); 


function generateRandomString($length = 10) { 
    $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; 
    $charactersLength = strlen($characters); 
    $randomString = ''; 
    for ($i = 0; $i < $length; $i++) { 
     $randomString .= $characters[mt_rand(0, $charactersLength - 1)]; 
    } 
    return $randomString; 
} 

isset($_REQUEST["limit"]) ? $limit = $_REQUEST["limit"] : $limit = 10; 



echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 
<html> 
<head> 
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">'; 

echo "<title>Test Script</title></head><body>"; 

//ob_start(); 
echo "<br><br>A random delay between 20 and 60 seconds will be generated, then a randomly generated string will be displayed<br>The default limit on iterations is ten<br>When the script terminates normally, the phrase \"test complete\" will be output at the bottom<br><br>"; 
flush(); 


for ($i = 0; $i < $limit; $i++) { 
    $delay = mt_rand (20, 60); 
    echo "<br><br><br>iteration ".($i+1)." - script will now sleep for $delay seconds"; 
    flush(); 
    sleep ($delay); 
    echo "<br><br>Here is a random string:<br>"; 
    $length = mt_rand (50, 100); 
    echo generateRandomString($length); 
    flush(); 
} 


echo '<br><br>...test complete</body></html>'; 
ob_end_flush(); 
?> 

你可以去這個頁面:http://www.scripttest1.cu.cc/test_script.php看到自己時,它在此服務器上運行會發生什麼。

第二個測試腳本代碼:

<?php 
set_time_limit(600); 
error_reporting(E_ALL); 
ini_set('display_errors', TRUE); 
ini_set('display_startup_errors', TRUE); 

isset($_REQUEST["limit"]) ? $limit = $_REQUEST["limit"] : $limit = 15; 
isset($_REQUEST["longorshort"]) ? $longorshort = $_REQUEST["longorshort"] : $longorshort = "long"; 
$start = 1; 

echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 
<html> 
<head> 
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">'; 

echo "<title>Test Script 2</title></head><body>"; 
echo '<script src="test_script_js7.js"></script>'; 

echo " 
    <br>Clicking the button below will start the script running 
    <br>The script called via XMLHttpRequest will generate a random delay between 40 and 55 seconds (5-10 seconds if \"longorshort\" is set to \"short\" in the url string), then a randomly generated string will be displayed in the table on the bottom 
    <br>The default limit on iterations is fifteen 
    <br>When the process terminates normally, the phrase \"test complete\" will be output in the \"Main Info\" cell 
    <br><b>The script called via XMLHttpRequest will <u>never take more than 60 seconds</u> to complete processing</b> 

"; 
//echo "<img src=http://nzbstar.info/download_batch.png onclick=\"getter($limit, '$start', '$longorshort')\"><br>"; 
echo "<br><img src=start.jpg onclick=\"getter_outer($limit, '$start', '$longorshort')\"><br><a href=\"javascript:master_switch();\">click here to abort</a> "; 

echo "<table border=1><tr>"; 
echo "<td valign=top><div id=main_info>Main Info:</div></td>"; 
echo "<td valign=top><div id=iteration>Iterations:</div></td>"; 
echo "<td valign=top><div id=message>Messages:</div></td>"; 
echo "</tr></table>"; 

echo "<table border=1 style=table-layout:fixed;><tr>"; 
for ($i = 1; $i <= $limit; $i++) { 
    echo "<td valign=top><div class=getter id=post_$i><i>Result $i</i></div></td>"; 
    if (($i%5 == 0)) {echo "</tr><tr>";} 
} 
echo "</tr></table>"; 




echo '</body></html>'; 
?> 

...的JavaScript:

var master_off = false; 
var getter_running_now = false; 

function getter_outer(limit, i, longorshort){ 
    if (getter_running_now) {alert ("Script is already running!"); return;} 
    getter_running_now = true; 

    if (master_off) {document.getElementById("main_info").innerHTML += "<br>master switch off, aborting!"; return;} 
    if (i >= limit) {document.getElementById("main_info").innerHTML += "<br>Got to the next getter when we shouldn't have, there's a bug!"; return;} 
    getter(limit, i, longorshort); 
} 

function getter(limit, i, longorshort){ 
    if (master_off) {document.getElementById("main_info").innerHTML += "<br>master switch off, aborting!"; return;} 
    if (i >= limit) {document.getElementById("main_info").innerHTML += "<br>Got to the next getter when we shouldn't have, there's a bug!"; return;} 

    var post_number_element = "post_" + i; 

    var batch_result_script = "test_script_2a.php?longorshort=" + longorshort; 

    document.getElementById("iteration").innerHTML = "Iterations:<br>Doing iteration: " + i; 
    document.getElementById(post_number_element).innerHTML = "doing this one...<br>"; 
    var xmlhttp=new XMLHttpRequest(); 
    xmlhttp.onreadystatechange=function(){ 
    if (xmlhttp.readyState==4){ 
     if (xmlhttp.status==200){ 
     var result = "<b>result for " + post_number_element + " is:</b><br>" + xmlhttp.responseText + "<br><span style=color:green;>Success!</span>"; 
     document.getElementById(post_number_element).innerHTML = result; 
     i++; 
     if (i >= limit) { 
      document.getElementById("main_info").innerHTML += "<br><span style=color:green;>Test complete!</span>"; 
     } 
     else {getter(limit, i, longorshort);} 
     } 
     else {document.getElementById("message").innerHTML += "<br> - <span style=color:red;>http return status for iteration " + i + " was " + xmlhttp.status + "</span>";} 
    } 
    } 
    xmlhttp.open("GET",batch_result_script,true); 
    xmlhttp.send(); 
} 



function master_switch(){ 
    master_off = true; 
    document.getElementById("main_info").innerHTML += "<br><span style=color:red;>Master Switch Off!</span>"; 

}

...它通過AJAX調用腳本:

<?php 
set_time_limit(600); 
error_reporting(E_ALL); 
ini_set('display_errors', TRUE); 
ini_set('display_startup_errors', TRUE); 


function generateRandomString($length = 10) { 
    $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; 
    $charactersLength = strlen($characters); 
    $randomString = ''; 
    for ($i = 0; $i < $length; $i++) { 
     $randomString .= $characters[mt_rand(0, $charactersLength - 1)]; 
    } 
    return $randomString; 
} 

if (isset($_REQUEST["longorshort"]) && $_REQUEST["longorshort"] == "short") {$delay = mt_rand (5, 10);} 
else {$delay = mt_rand (40, 55);} 


sleep ($delay); 
echo "<br>Here is a random string:<br>"; 
$length = mt_rand (5, 10); 
echo generateRandomString($length); 


?> 

去這裏:http://www.scripttest1.cu.cc/test_script_2.php?longorshort=long在行動中看到它。與第一個腳本不同,它產生的錯誤是「空白迴應」。但我認爲這兩者是相關的。

這兩個腳本都可以在另一個共享服務器以及我有權訪問的LAMP的vps上正常工作。他們也在這臺服務器上工作了一段時間,然後才失敗。第一個測試腳本在死亡之前通常會經歷幾次迭代。第二個,與阿賈克斯,將有時運行直到完成,如果「longorshort」設置爲「短」。

此外,第一個測試腳本完美地從命令行運行。當然,第二個在那個環境下是行不通的。

服務器在Linux下運行PHP版本5.4.44和Apache版本2.4.16。

谷歌並不是我的朋友。我發佈到Stackoverflow,並得到了5(五)個意見,零響應。

這裏至少有人能給我一個線索嗎?或者失敗了,指向我替代Stackoverflow他們可能會真正回答我的問題?

+0

使您的服務器回答HTTP 1.0,並使用類似於nokeepalive force-response-1.0降級-1.0的字符串。在HTTP1.1中引入了塊編碼。一個很大的方面說明,這是一個石膏來彌補腳本中的一個大錯誤,但我不是一個腳本專家,因此提供了石膏。 (與分塊編碼一樣,服務器以更「流」的方式發送數據以節省帶寬(帶有更少的頭部),並保存活動連接打開) – yagmoth555

+0

哇,2天在Stackoverflow上沒有答案,20分鐘在這裏等等已經彈出。謝謝您的回答。我曾考慮過這樣做,但它有點燒燬村莊,以挽救它。我真的需要能夠在輸出生成時看到輸出,而長時間運行而沒有響應的腳本在我的經驗中往往會出現空白頁面。 –

+0

然後做一個wireshark,它的流量很容易跟進。你會看到每個數據包將以http頭後面的數據塊的塊大小開始,並以0結束。 – yagmoth555

回答

0

找到你的wireshark信息的答案,就像所有延遲這樣寫,58秒的延遲竊聽了我。

當Internet Explorer與Web服務器建立持久HTTP連接時(通過使用Connection:Keep-Alive標頭),Internet Explorer將重複使用用於接收初始請求的TCP/IP套接字,直到套接字空閒爲止等一下。 連接空閒一分鐘後,Internet Explorer將重置連接。新的TCP/IP套接字用於接收其他請求。您可能需要更改Internet Explorer中的HTTP KeepAliveTimeout值。

https://support.microsoft.com/en-us/kb/813827

這讓我覺得其他的瀏覽器必須遵循的標準,所以你必須上線送東西,當你運行腳本,以防止關閉連接,因爲你不能要求你的客戶改變他們的超時值。

+0

我不認爲就是這樣。超過60秒閒置時間後會發生超時。同樣的腳本在其他幾個可以在同一瀏覽器中上傳的網站上運行良好。不,它必須與主機有關... –

+0

@MackManhattan在最壞的情況下試試吧,它是KB中的兩個註冊表項目,編輯 – yagmoth555

+0

@ yagmoth555好吧我試過了,不幸的是沒有效果。 –