2014-01-30 25 views
5

在AWS 1.7GB服務器中一次接收到2000個請求。應用程序試圖處理這個問題,但以內存耗盡錯誤結束。我對PHP腳本和MySQL數據庫進行了優化,直到我知道和收集的任何內容。LAMP服務器中的PHP請求平衡

因此,這裏是我決定的,是

我想處理在服務器200個請求,並拒絕第一次1800級的要求。下次200請求將被處理,1600被拒絕。這樣我就可以處理所有的請求。

問題:1如何做到這一點?

我計劃來實現這個像下面

  1. 要獲得Apache進程數,如果它是超越了120,然後我打算拒絕來自服務器的請求。

  2. 要監視基於我計劃拒絕請求的服務器RAM空閒內存。

建議所需:這是實現最好的選擇?

如果有其他建議也歡迎。

問題:2如何使用PHP獲得apache進程的計數?

問題:3如何使用PHP獲得可用的RAM內存大小?

注意:拒絕請求不是問題,我可以再回來。如果我拒絕來自服務器的請求,那麼沒有問題,並且服務器是正常的。一旦我處理了這2000個請求,那麼在我總是減少負載之後就沒有問題了。

+0

對於如何拒絕請求,您有具體要求嗎?通過使用5XX HTTP狀態碼進行響應怎麼樣? – jdhildeb

+0

我決定我在計劃部分下提到..你可以分享你的想法是很好的。如果不錯,如何實現這個 – Sundar

+0

我的建議是:1.檢查,如果你啓用了Apache [ExpiresActive from mod_expires.c]; 2.使用php-cgi,如:php-fpm或hhvm(PHP的HipHop虛擬機)。它可以真正有所作爲。 3.除了處理部分請求之外,請使用緩存服務 - 例如:varnish,除非所有請求都需要不同的內容; 4.將靜態內容移動到cdn服務器; 5.使用AWS平衡服務器 - 種類豐富 - 我沒有真正的建議。只要一個一個地做,你會發現很快就有所不同。 – Zac

回答

2

首先,我建議不要使用系統調用,特別是當你有這麼多的請求時。運行外部進程可能會導致嚴重的性能問題,因爲在您的情況下,不會。的進程/內存使用情況迅速變化(您一次說出2000個請求),您不能使用cronjob來緩存這些值(即使您每秒運行一次cron,也無法確定這些值是否爲100%實數) 。你可以得到你的腳本的內存使用情況,近似於no。您一次可以處理的流程,並且應該這樣做。

現在,據我所知,你想按特定的順序處理請求:處理請求1-200,然後201-400,等等?如果是這種情況,則需要跟蹤已處理的請求。

一個簡單的方式實現這一目標將是保持一個請求隊列在數據庫中 - 如果你可以使用memcached的或類似的東西,甚至更好:

    每次你得到一個請求時,
  • ,你檢查隊列並確保您沒有超過200個活動請求;
  • 下一步將檢查請求是否應該運行(這意味着您可以唯一標識每個請求,即通過檢查GET/POST中的某個值) - 這可以確保如果處理請求#200時,讓我們說在最後一分鐘,你會忽略它,並允許請求#201運行;
  • 如果請求檢出,則將其添加到隊列中並將其標記爲已完成/將其從隊列中刪除;

但是,如果請求順序對您無關緊要,而不是請求隊列,您可以只保留一個請求數,並確保您永遠不會超過某個限制。

+0

這是個好主意。這應該在我不知道爲什麼之前執行。現在n生產服務器我不能修改代碼。 而不是拒絕呼叫我傾倒了表中的200個工作請求這是一個較小的數據庫負載。我們可以管理這個。對於這種請求隊列,我們​​不需要拒絕任何東西。 但是這個邏輯已經在當前的版本代碼中實現了。仍然需要在服務器上完成升級。 – Sundar

1

根據您對服務器的訪問權限,您可以通過讀取兩條命令的輸出來執行您想要的操作。我假設你在Linux服務器上,如果情況並非如此,那麼必須使用另一個命令/選項。

  • PS^h -U阿帕奇(得到所有的apache線程)
  • 執行cat/proc/meminfo中

我會使用,例如,一個cron作業編寫信息的PHP可以讀取並在腳本上使用該信息的文件。

對於進程數量,它就像計算文件行數一樣簡單。

對於可用內存,您將不得不做一些計算。 meminfo的輸出很長並且很詳細,但是你只需要取兩個值,memfree和swapfree。如果系統是專用的,並且沒有其他類型的進程正在工作,那麼您也可以包含緩存值,因爲這些值很可能已經被apache使用。

如果您不能/不想在系統上使用cron作業,但您可以執行來自PHP的命令,您可以執行這些命令,但我認爲最好將作業的每個部分分開。

1

我覺得最好是嘗試一下,以可擴展的方式實現您的目標,而不是拒絕請求並依賴系統度量標準。過去我使用過相同的設置來處理視頻。

如果是我,我會設置它就像這樣:

  1. 開始有彈性負載均衡

  2. 內部負載平衡器按需創建小EC2的自動伸縮羣實例(如果你的預算非常緊張,你甚至可以使用微型)。組的大小將根據您的工作負載類型而有所不同。確保使用CloudWatch根據負載平衡器的工作負載來擴展組。

  3. 這些實例將負責接收處理請求並將它們中繼到SQS隊列。實例不需要非常努力地工作,因爲他們所做的只是將請求轉發到SQS隊列。

    注意:如果您的客戶端能夠將請求直接推送到SQS隊列,您實際上可以完全繞過步驟1-3。

  4. 現在讓我們讓你的工作力量。設置另一個具有更多小實例的自動縮放組,但是該組將由實例組成。將組的最小大小設置爲0,將最大大小設置爲10.同時將現貨實例價格設置爲允許實例在大多數情況下分散的事件,但如果現貨價格高漲,則不會花費大量資金。

  5. 使用CloudWatch,監視SQS隊列並在SQS隊列中包含一些項時觸發worker自動擴展組。

  6. 您的工作者強制實例應設置爲開始輪詢SQS隊列,並在請求開始後立即處理請求。它由您來決定他們消耗這個隊列的速度。

額外的閱讀:

+0

是的,我可以使用這個,但公司沒有興趣爲此花費任何錢,因爲問題發生是由於我們的錯誤,我們必須用現有資源解決問題。感謝您的信息 – Sundar

2

我做了一個原型使用APC一個PHP程序限制的。

<?php 

    $processes = apc_fetch('processes'); 
    if(!$processes) { // Initial Status 
     $processes=1; 
    } 
    if ($processes > 3) { 
     echo "Reject: ". $processes; 
     // Return HTTP/403 ... 
     exit -1; 
    } 

    $processes ++; 
    apc_store('processes', $processes); 

    // Long memory hunger code 
    sleep(10); 
    // .... your code .....// 

    // Implement global MUTEX?? 
    $processes = apc_fetch('processes'); 
    echo "Pending process: ". ($processes -1); 
    $processes --; 
    apc_store('processes', $processes); 
?> 
+0

問題在於內存。沒有足夠的內存來處理數據,如果我們使用APC緩存,我必須分配額外的內存。在這種情況下,這是行不通的。這個邏輯很好,我可以在其他一些問題中使用它。 – Sundar

+0

你只需要存儲一個變量與APC。 – KikoV

+0

是的,但模塊需要一些內存來安裝 – Sundar