阿里最新開源配置中心和註冊中心: Nacos 限流最佳實踐


  • Nacos 限流最佳實踐
  • Tomcat 限流
  • Nginx 限流
  • 限制訪問速率
  • 限制併發連接數
  • 黑名單
  • 總結

作者:風卿(Nacos 社區 committer)

本文系投稿。如果胖友有想要投稿的內容,歡迎後臺留言。哇咔咔。

Nacos 限流最佳實踐

Nacos自開源以來,版本迭代速度很快,已經發布了0.9版本,準備發1.0的正式版本,支持企業使用Nacos生產高可用。在生產環境,Nacos首先需要保證自身服務的穩定性,在正常的運行環境下不會出現服務掛掉的情況。當然在一些依賴的系統出問題的時候(比如磁盤和DB),Nacos服務會受到影響,需要監控系統發現這些問題並能及時的介入處理。

作為高性能的服務發現和配置管理服務,Nacos也是存在自己的性能基線的,當瞬時的高峰流量超過自身的性能基線的時候,需要對高峰流量進行限流,以保證整體服務的健康運行而不影響到其他核心應用。

Tomcat 限流

Nacos基於spring boot使用內嵌的tomcat,tomcat線程分為acceptor線程和worker線程,acceptor線程負責從內核accept隊列中取出連接並交給worker線程,而worker線程則負責處理連接(讀取參數、執行處理、返回響應等)

  • acceptCount

當tomcat不能及時處理新的連接時,內核中新建的連接將會進入連接隊列排隊,acceptCount參數能夠設置tomcat accept連接隊列大小,當新的連接數超過acceptCount則拒絕連接,立即返回給client,不會讓client一直等待造成響應很慢或超時

  • maxConnections


接受了的連接需要由worker線程調度處理,當worker線程處理的連接數越來越多時,處理的速度會越來越慢造成client響應時間變長,需要根據系統和機器情況設置合理的maxConnections,當連接數到達maxConnections時,不再接受新的連接,讓新連接排隊等待,超出隊列長度則直接拒絕。

  • maxThreads


maxThreads參數設置tomcat的最大線程數,過高的線程數會讓系統運行的負載過高、響應變慢,過低的線程數讓系統的資源利用率太低,需要根據實際的運行情況(CPU、IO等)設置合理的最大線程數。

Nginx 限流

tomcat限流只能做到自身負載的調節,在實際生產環境中還遠遠不夠,需要依賴Nacos自身的限流來提高系統的限流能力。

Nacos的open API都是基於http協議,可以很方便地使用nginx來做限流,不需要自身再開發限流模塊來支持各種限流策略。nginx的基本使用以及nginx+lua模塊安裝網上資源很豐富,這裡就不再介紹。

Nacos每個接口執行的代價不盡相同,一般來說寫操作代價比讀操作大,與此同時還有高頻操作和低頻操作之分,SDK調用的接口一般來說是高頻接口,容易出現問題,所以在生產環境需要將這些接口區別對待,根據服務自身的實際情況採取合理的限流策略,以防錯用方打垮Nacos服務。下面介紹一下Nacos在生產環境的幾種限流場景

限制訪問速率

1、限制單個接口的請求QPS

limit_get_config對讀操作進行限流,正常使用Nacos獲取動態配置一般就啟動和運行時修改配置推送到client,獲取配置相對來說是低頻操作,如果頻繁獲取配置肯定是client有錯用或者應用不正常(比如數據平臺任務failover重試任務)

limit_req_zone $limit_key zone=limit_get_config:10m rate=10r/s;
server {
listen 8080;
server_name localhost;
location /nacos/v1/cs/configs {
if ($request_method = POST ) {
rewrite ^ /limit_publish_config_url last;
}
rewrite ^ /limit_get_config_url last;
}
location /limit_get_config_url {
set $limit_key "$remote_addr+$arg_dataid+$arg_group+$arg_tenant";
limit_req zone=limit_get_config burst=10 nodelay;
proxy_pass http://127.0.0.1:8848/nacos/v1/cs/configs;
}
}
  • limit_req_zone設置限流key和內存大小,以及請求速率
  • limit_key由[ip,dataId,group,tenant]四元組組成,可以防止client錯用頻繁訪問單個配置
  • burst設置漏桶算法的桶的大小
  • nodelay設置非延遲模式,如果桶滿了則會馬上返回給客戶端錯誤碼
  • proxy_pass指定後端Nacos的接口url

limit_publish_config對寫操作進行限流,可以有效防止熱點寫問題。對同一個數據的高頻寫會觸發mysql的行鎖,從而導致mysql的多線程任務因等待行鎖排隊,最終導致mysql所有操作都超時服務不可用。這裡通過nginx lua模塊獲取post請求的參數,設置limit_key

limit_req_zone $limit_key zone=limit_publish_config:10m rate=5r/s;
location /limit_publish_config_url {
set $dataId $arg_dataid;
set $group $arg_group;
set $tenant $arg_tenant;
set $limit_key "$remote_addr+$dataId+$group+$tenant";
lua_need_request_body on;
rewrite_by_lua '
ngx.req.read_body()
local post_args = ngx.req.get_post_args()
if post_args["dataId"] then
ngx.var.dataId = post_args["dataId"];
ngx.var.group = post_args["group"];
ngx.var.tenant = post_args["tenant"];
ngx.var.limit_key = ngx.var.remote_addr.."+"..ngx.var.dataId.."+"..ngx.var.group;
if ngx.var.tenant then
ngx.var.limit_key = ngx.var.limit_key.."+"..ngx.var.tenant;
end
end
';
limit_req zone=limit_publish_config burst=10 nodelay;
proxy_pass http://127.0.0.1:8848/nacos/v1/cs/configs;
}
  • lua_need_request_body on;用於讀取post請求的request body
  • rewrite_by_lua指令在http rewrite階段執行lua代碼

2、限制單機訪問QPS

perclient對單個client的所有請求限制低於500QPS,可以有效防止單臺client的重試攻擊

limit_req_zone $remote_addr zone=perclient:10m rate=500r/s;
server {
listen 8080;
server_name localhost;
limit_req zone=perclient burst=250 nodelay;
location / {
proxy_pass http://127.0.0.1:8848/nacos/v1/cs/configs;
}
}

3、限制 Nacos 服務 QPS

perserver限制整個Nacos服務的QPS,Nacos的服務部署在nginx之後,nginx可以保證到達Nacos的流量不會打垮Nacos

limit_req zone=perserver burst=1000 nodelay;

限制併發連接數

/nacos/v1/cs/configs/listener接口是Nacos的長連接通道,一般來說,一個client一個長連接就可以滿足生產需求。limit_conn_client限制client的連接數不超過10個,limit_conn_server限制Nacos單機(8核16G內存)支撐最多9000個長連接,最多可以同時服務9000個應用節點

limit_conn_zone $remote_addr zone=limit_conn_client:10m;
limit_conn_zone $server_name zone=limit_conn_server:10m;
server {

listen 8080;
server_name localhost;
location = /nacos/v1/cs/configs/listener {
limit_conn limit_conn_client 10;
limit_conn limit_conn_server 9000;
proxy_pass http://127.0.0.1:7001/diamond-server/config.co;
tcp_nodelay on;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

黑名單

1、IP黑名單

當生產環境發現有錯用的client影響到Nacos服務,可以使用nginx黑名單限制client的訪問

deny 30.5.125.70;

從被限制的IP訪問Nacos

curl -X GET "http://{IP}:8080/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test" -i

Nginx返回403狀態碼給client,禁止client訪問

HTTP/1.1 403 Forbidden
Server: nginx/1.13.5
Date: Fri, 15 Mar 2019 08:34:33 GMT
Content-Type: text/html
Content-Length: 169
Connection: keep-alive

<title>403 Forbidden/<title>

<center>

403 Forbidden

/<center>

<center>nginx/1.13.5/<center>


2、讀寫黑名單分離

有時候通過IP維度直接限制client訪問所有Nacos接口粒度過大,會導致應用服務不可用,可以將讀操作和寫操作分開,禁止client寫Nacos,依然允許其進行讀

# 1 limit read, 0 no limit
map "$remote_addr" $limit_read {
#10.2.24.252 1;
default 0;
}
# 1 limit write, 0 no limit
map "$remote_addr" $limit_write {
#10.2.24.252 1;
default 0;
}
location /some_url_to_write {
if ($limit_write = 1) {
return 403;
}
}
  • map指令匹配remote_addr變量,如果$remote_addr變量在ip黑名單裡面,則設置limit_read和limit_write參數為1,否則為0
  • 在寫接口中對limit_write做判斷,如果禁寫則返回403狀態碼

3、應用黑名單

IP黑名單功能是nginx提供的基礎能力,能夠限制某些IP的訪問,但是一般一個應用會有很多臺機器,當一個應用出問題的時候,會有很多IP訪問都有問題,通過IP的維度來限制訪問達不到預期,需要有應用的維度來限制

namespace(命名空間)是一個可以區分不同應用的維度,不同的應用一般會使用不同的namespace,這樣可以在namespace維度對服務的訪問進行限制

map "$arg_tenant" $limit_namespace {
af884cf8-1719-4e07-a1e1-3c4c105ab237 1;
#a6c745b7-fd92-4c1d-be99-6dc98abfe3dc 1;
default 0;
}
location /some_url {
if ($limit_namespace = 1) {
return 403;
}
}

通過匹配namespace是否在黑名單中來設置limit_namespace變量,然後在訪問的url中判斷limit_namespace的值,如果為1返回403狀態碼

ak維度:使用一個ak代表一個應用,不同的應用在啟動的時候設置不同的ak。client在發起請求的時候會帶上ak參數到server端,在nginx層對請求的參數進行解析,對特定的應用的ak進行訪問限制

map "$http_Spas_AccessKey" $limit_ak {
6839c164bb344cdc93107f08eda8a136 1;
default 0;

}
location /some_url {
if ($limit_ak = 1) {
return 403;
}
}

總結

本文簡單介紹了Nacos在實際生產環境中如何通過限流來提高自身服務的穩定性,除了自身設置tomcat參數,還可以通過高性能的nginx作為前端對流量進行過濾提高限流能力。文中難免會有個別錯誤或者遺漏,如果大家有更多的限流或者提高穩定性的辦法可以在Nacos官網提出來。


搜索微信號(ID:芋道源碼),可以獲得各種 Java 源碼解析。

並且,回覆【書籍】後,可以領取筆者推薦的各種 Java 從入門到架構的書籍。

阿里最新開源配置中心和註冊中心: Nacos 限流最佳實踐

來吧,騷年~


分享到:


相關文章: