標籤:nginx php 高並發
線上運行了一套輔助系統是利用了開源的PHP改的,之前也沒怎麼玩過PHP,沒想到這玩意兒還是有不少坑的。突然某一天一個使用者做線上活動推廣,然後短時間內湧進來了上萬的請求,然後資料庫連接耗盡,短時間內幾乎拖垮了整個系統。導致系統奔潰的有多方面原因,今天主要針對PHP沒有資料庫連接池的原因來分析。
在PHP裡,資料庫連接在請求到達時建立,請求結束時釋放。如果同時幾千個請求到達,那就同時會建立幾千個資料庫連接,非常恐怖。而且PHP木有比較好的資料庫連接池驅動方案,所以我們得另想辦法。
解決這種問題有三種辦法:
1.使用Mysql Proxy中介軟體。Mysql Proxy提供了串連池管理的功能。但是我們沒有採用此方法,因為情況緊急,沒有人熟悉這玩意兒。
2.使用PHP-FPM。PHP-FPM是PHP的一個FastCGI進程管理器。通過配置可以控制同時處理PHP請求的進程數。
具體可以參考:http://www.linuxde.net/2013/06/14638.html
但是我們也沒用使用此方案,因為安裝配置過程比較麻煩。
3.使用Nginx的ngx_http_limit_req_module來控制請求。
此模組可以通過自訂的索引值來限制請求頻率。限制的方法就像漏鬥,每秒固定處理請求數,然後延遲超出的請求,最後超出最大值的直接503返回拒絕。
我們使用了此方案,是因為只需簡單配置,而且可以靈活控制限制請求的情境。例如,對於靜態資源的請求我們不做限制,而對於PHP的請求做限制。還可以從URL地址裡提取出變數資訊作為鍵,來達到更細的要求節流。
下面貼部分我們的配置給大家講解下。
http { ...... limit_req_zone $limit_key zone=limit_one:50m rate=30r/s; #定義limit_key為Key的變數名,用於後面賦值,每個Key都有自己的計數器。limit_one為zone的名稱。rate表示每秒最多接受30個同時請求。 server { ...... if ( $request_uri ~* .*php.* ) { set $mp_limit_key $binary_remote_addr; #對於全部PHP首先有個預設的Key,使用用戶端的IP作為Key。相當於每個用戶端IP都會在zone的限制內。 } if ( $query_string ~* .*id/(\d+)\.php.* ) { set $mp_limit_key $1; #提取id後面的值作為Key。 } if ( $query_string ~* .*appid/wx(.*)\.html.* ) { set $mp_limit_key $1; #提取appid作為Key。 } limit_req zone=limit_one burst=200; #限制limit_one在此server內的漏鬥容量為200。假設一個Key對應的請求數為200,那麼第一秒內在處理的為30個請求,其餘的170個請求在等待排隊。假設一個Key對應的請求數為300,那麼超出200的部分將直接返回503。 ....... }}
參考:http://www.ttlsa.com/nginx/nginx-limiting-the-number-of-requests-ngx_http_limit_req_module-module/
官方文檔:http://nginx.org/en/docs/http/ngx_http_limit_req_module.html
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
PHP沒有資料庫連接池怎麼破?PHP環境下使用Nginx ngx_http_limit_req_module模組的高負載解決方案