2009-04-15 90 views
7

我有一個定期運行腳本(每小時)的計劃任務。該腳本與數據庫和文件系統進行了一些繁重的交互,並且需要花費幾分鐘時間才能運行。問題是,腳本運行時服務器的cpu使用率會激增,並會降低正常運行速度。有沒有辦法來限制這個過程,以便它花費更長的時間,但不會消耗盡可能多的資源?限制PHP腳本的建議/技巧

我已經看過不同的PHP配置選項,但似乎沒有任何符合我的需求。

將php.ini中的memory_limit設置爲較低的值會導致我的數據對象很容易溢出。

我見過類似的帖子,其中人們建議在腳本中的某些點使用sleep(),但這不會阻止腳本插入服務器。

最佳解決方案是告訴Lamp(在這種情況下爲Wamp)堆棧以僅使用10%max cpu利用率的某種方式。我並不關心運行時間,如果它意味着每秒鐘節省CPU週期,它會花費更長的時間。我的替代解決方案是使用數據庫複製來設置不同的服務器,以便cron可以在不減速其他任何事情的情況下進入城鎮。

環境:Windows服務器2K3,阿帕奇2.2.11,PHP 5.2.9,MySQL 5.1中

我明白任何洞察到這種情況。

編輯:我欣賞所有的答案,即使是* nix特定的答案。在我的情況下,改變託管環境還爲時尚早。不管操作系統如何,希望這個問題能夠幫助別人。

回答

8

這是一個棘手的問題。如果您通過命令行運行PHP腳本,則可以將進程的調度優先級設置爲低(我相信start /low php.exe myscript.php)。如果您的PHP腳本本身實際上正在執行大部分正在佔用您的CPU的處理,這可能會起作用。但是,你說你正在做一些繁重的數據庫和文件系統交互,這個解決方案不會有幫助。它看起來像有一個MySQL提示「LOW_PRIORITY」爲INSERT和UPDATE查詢,可以幫助你,但我還沒有嘗試過的。

1

這可能是一個困難的改變,但它可能值得它重構你的數據結構到迭代器中。另外,如果在代碼中有循環引用,請提供一個像clearReferences()這樣的方法來清除這些對象。順便說一下,這是PHP 5.3中解決的一個問題。

所以,如果您有:

class Row 
{ 
    protected $_table; 

    public function __construct($table) 
    { 
     $this->_table = $table; 
    } 
} 

class Table 
{ 
    protected $_row; 

    public function __construct() 
    { 
     $this->_row = new Row($this); 
    } 
} 

添加clearReferences()方法的行類:

class Row 
{ 
    public function clearReferences() 
    { 
     $this->_table = null; 
    } 
} 

這就是我能想出的時刻。

0

如果您將Apache(Apache)作爲服務運行,則可以更改Win控制中心/服務中的優先級 設置。 無論如何,你的CPU使用率會激增,但其他程序將被調度程序首選爲 。 也嘗試將數據庫/服務器放在與您的 應用程序不同的高清上。

2

您是否可以使用nice更改您的cron條目以啓動您的腳本?

+0

哎呀,對不起。我看到你正在運行Windows。我被'燈'和'cron'標籤拋棄了! – grossvogel 2009-04-15 16:09:17

2

不是一個好主意使用服務器來服務客戶端和分析數據。

因此,如果您正在尋找最終解決方案,請對應用程序進行一些重新設計,並將數據分析從前端和實時數據庫卸載到專用於此任務的另一個系統。

即使您可以成功調節分析儀,它也會耗盡寶貴的資源,否則將可用於爲用戶提供服務。

1

我有一大堆的腳本,我從cron以類似的方式使用好的運行:

0 * * * *漂亮-n19 PHP myscript.php

這將不利於內存使用率(僅改變腳本編寫可以做到這一點的方式),但只使用了CPU,否則將處於閒置狀態。

編輯:沒有看到這個問題涉及到Windows環境下,遺憾......在離開這個具有相同問題的任何* nix的用戶..

3

UNIX(LAMP)我設法通過繼續循環

function get_server_load($windows = 0) { 
    $os = strtolower(PHP_OS); 
    if(strpos($os, "win") === false) { 
     if(file_exists("/proc/loadavg")) { 
     $load = file_get_contents("/proc/loadavg"); 
     $load = explode(' ', $load); 
     return $load; 
     } 
     elseif(function_exists("shell_exec")) { 
     $load = explode(' ', `uptime`); 
     return $load; 
     } 
     else { 
     return ""; 
     } 
    } 
} 

for(... ... ...){ 
    $data = get_server_load(); 
    if($data[0] < 0.2){ 
    // continue 
    }else{ 
     sleep(1); 
    } 
} 

這個功能也應該工作在Windows之前檢查服務器的負載解決這個問題,但我不能保證這一點。在Linux上它可以讓你回來的最後1分鐘的負載的陣列,5分鐘和15分鐘的

另外,還要考慮到啓動腳本(如果CLI)優先級較低(在Linux上,使用「好」 )

在繼續循環之前,您還可以使用其他值,如Apache活動進程的數量(如果啓用了httpd.conf中的mod_status,則可以解析頁面127.0.0.1/server_status?auto),或者MySQL的情況(活動連接?)

1

也許你的腳本只是試圖做太多的一次。如果它每小時運行三次,它會減少嗎?

另一種解決方案可能是設置一個額外的服務器來運行這種'後端'處理。如果它不會在數據庫中加載不適當的負載,那麼這將特別有效,就像Web服務器一樣。

另一種方法來看待是無論是工作可以在不同的方向進行劃分。這些腳本通常有幾個大的SQL語句,這些語句會生成用於生成大量小SQL語句的結果。如果後者可以放在某個地方,則可以在後面的步驟中針對數據庫運行它們。這種方法也可以讓你使用一個無緩衝查詢來獲取可能由PHP代碼顯著減少內存消耗預加工數據。