引子
最近接觸了一個抽獎的項目,由于用戶量比較大,而且第三方提供的認證接口并發量有限,為了保證服務的高可用性,所以對高并限制發有一定的要求。經過一系列研究和討論,做出了以下一些優化方案。
需求分析
-
根據用戶量和日活情況,估算出并發值在100左右,所以該項目的并發量就當在100上以,初期目標定為600-800
-
特定頁面的并發量不超過300,為了保證不對第三方服務造成訪問壓力,特將并發控制在150以內
-
由于獎品數量有限,故得獎時,需要進行并發寫入控制,防止獎品超發
實施步驟
前端方面
減少客戶端訪問次數。
-
使用CDN對網站的靜態資源進行優化,可以答復靜態請求次數。
-
抽獎結果一次性生成。
每個用戶有有一次抽獎機會,但只能有一次中獎,其他兩次隨機彈出推薦產品。所以有一次抽獎中,只需要訪問一次服務器的抽獎接口。
- 使用本地緩存。
將抽獎次數,是否中獎等信息記錄在本地,避免超次抽獎和多余的服務器請求。例如,一旦該用戶中過將,就不需要再訪問服務器抽獎接口。
服務端優化
使用緩存
- 使用服務端緩存。
將頁面和相關數據查詢進行緩存,減少數據庫訪問次數。
部分業務邏輯異步處理
對于不需要實時處理的業務邏輯,壓入隊列,實現異步處理。例如優惠券的發放。
Nginx 優化
- 提高 Nginx 處理性能
使用 worker_processes
,worker_cpu_affinity
,worker_rlimit_nofile
, worker_connections
,open_file_cache
等命令,提高nginx的處理性能。
- Nginx 并發控制。
先看實例,如下:
limit_req_zone $binary_remote_addr zone=req_ip:10m rate=40r/s; // #每個IP平均處理的請求頻率為每秒40次limit_conn_zone $binary_remote_addr zone=conn_ip:10m;limit_conn_zone $server_name zone=conn_server:10m;limit_conn conn_ip 5; // #限制某個IP來源的連接并發數,此處為5個limit_conn conn_server 600; //#限制某個虛擬服務器的總連接數,此處為600個limit_req zone=req_ip burst=5; //小為5的緩沖區, 當有大量請求過來時,超過了訪問頻次限制的請求可以先放到這個緩沖區內
在這里,限制了每個IP的請求頻率,限制了同一IP的并發連接數,限制了服務器的總連接數
- 使用 Docker 實現負載均衡
配置 nginx, 使用負載均衡
upstream icontact_pool {server web:9000 weight=5 max_fails=3 fail_timeout=10s;server web2:9000 weight=5 max_fails=3 fail_timeout=10s;server web3:9000 weight=5 max_fails=3 fail_timeout=10s;...}
如上,通過 Docker 啟動多個處理請求的服務容器,在 nginx 中配置每個服務的地址,權重等信息,擴大請求的處理能力
- 其他服務器環境優化
例如,增加服務器配置(CPU,內存,帶寬),如果是PHP, 開啟 opcache, 并使用較新版本(php7+), 各種依賴盡量使用最新版本。
zend_extension=opcache.so
opcache.enable=1
opcache.enable_cli=1
參考資料
- Nginx限制IP并發連接數和請求數的研究