2012-03-07 20 views
1

我有兩個文件client.php和server.php。 客戶端文件向服務器文件發送HTTP請求。服務器文件處理請求的速度非常慢,所以我只希望它能夠回答客戶端「確定請求是正確的,結果將通過電子郵件發送」。直接從服務器中斷HTTP請求

但我不知道要使服務器關閉具有合適標頭的HTTP請求並繼續其工作。如果我指定1秒的超時時間,則無法知道該請求是否會被服務器接受。

那麼有可能在PHP?你知不知道怎麼 ?

client.php:

<?php 

$resource = curl_init(); 
curl_setopt($resource, CURLOPT_URL, 'http://localhost/server.php'); 
curl_setopt($resource, CURLOPT_RETURNTRANSFER, true); 
curl_setopt($resource, CURLOPT_TIMEOUT, 30); 
curl_exec($resource); 

server.php

<?php 

header('200 OK'); 
echo 'OK the request is correct, the result will be sent by email'; 

// How to write the method below? 
send_result_to_client(); 

// Simulates a slow process 
sleep(60); 

好,我找到了解決辦法。 在功能send_result_to_client有人似乎是:

function send_result_to_client() 
{ 
    $myString = '...'; 
    $size = strlen($myString); 
    header("Content-Length: $size"); 
    header('Connection: close'); 
    flush(); 
} 

回答

0

對不起,但發送Connection:closeflush()而不是解決方案 - 不可移植跨服務器或瀏覽器。它可能似乎是一個解決方案,因爲它似乎工作時,您運行一個簡單的測試。如果您有

send_result_to_client(); 
sleep(60); // simulate a job... 
mail(...); // ...ENDING with a mail message 

嘗試一下,然後什麼都不做,或者更糟,做任何用戶都行 - 只要關閉該窗口,他看到了「你會通過電子郵件通知」 - 你會發現在大多數平臺上,電子郵件永遠不會被髮送,並且工作永遠不會完成。如果已收到Connection:closeContent-Length字節

curl可以終止,但RFC 2616

HTTP/1.1 defines the "close" connection option for **the sender** to signal that the connection will be closed after completion of the response. 

但服務器沒有關閉連接,而不是真的。在作業處理完成之前,需要使用die()exit()

因此,您的腳本將繼續執行,直到瀏覽器實際關閉連接 - 此時(通常爲),處理將中止。也許在某些平臺上它不會,但不要指望它。

您可以嘗試改善與其他黑客的情況:

set_time_limit(VERY_LONG_TIME); 
    ignore_user_abort(); 

,但它確實是一個黑客。

沒有真正的便攜式解決方案。通常,如Manatok所建議的,作業在其他地方排隊,而隊列由另一個線程異步處理。這可能是最好的解決方案。

其他可能性涉及到使用atd和at命令(或Windows下的等效命令)對作業進行排隊的不同方法,也許更簡單。您可以通過管道一個新的PHP腳本由atd執行打造的「作業控制」與shell_exec

shell_exec("echo 'php -q /path/to/script.php \"param1\" \"param2\" | at now"); 

(或更高效,運行「at now」與popen和寫入命令來執行其stdin) 。

見例如:

https://github.com/treffynnon/PHP-at-Job-Queue-Wrapper

您也可以嘗試產卵併發工作,通過popenshell_exec,但你需要從服務器進程分離,或者你會發現系統被作業可執行文件的副本佔用(如果在Windows下執行此操作,則爲CMD.EXE)。

請參見:

Asynchronous shell exec in PHP

1

我知道這是不是正是你問什麼(不知道這是可能的),但我會被另一個線程處理的隊列。請求進入服務器,它將細節添加到隊列(可以在數據庫中)並響應客戶端。然後您可以擁有一個運行並稍後處理隊列的cron。

+0

好,我找到了解決辦法。我編輯了我原來的帖子。 – 2012-03-07 13:22:30

+0

aaah有道理,很好:) – Manatok 2012-03-07 13:26:24

+0

這是可能的,就像你說的。使用atd(或者Scheduler,或者周圍的任何不同的端口和包裝器)來做到這一點。或者另一個PHP腳本,從crontab運行。 – LSerni 2012-07-05 17:28:01