使用OpenResty進行限流的基本配置
- 1.安裝OpenResty
-
-
-
- 1. 添加倉庫執行指令
- 2. 執行安裝
- 3. 安裝成功後 會在預設的目錄如下:
-
-
- 2.安裝nginx
- 3.測試通路
- 4.廣告的載入和讀取
-
-
-
- 1.聲明nginx緩存
- 2.在/root/lua目錄下建立read_content.lua:
- 3.在nginx.conf中進行調用
-
-
- 5. 控制并發量
-
-
-
- 1. nginx的限流
-
- (1) 控制速率
-
- 處理突發流量
- (2) 控制并發量
-
-
以商城輪播廣告為例
采用多級緩存的方式來減少下遊系統的服務壓力。
先查詢openresty本地緩存 ,如果沒有,再查詢redis中的資料,如果沒有,再查詢mysql中的資料,但凡有資料 則傳回即可。
記錄使用OpenResty(Nginx+lua)進行限流最基礎的配置。
1.安裝OpenResty
1. 添加倉庫執行指令
yum install yum-utils
yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo
2. 執行安裝
yum install openresty
3. 安裝成功後 會在預設的目錄如下:
/usr/local/openresty
2.安裝nginx
預設已經安裝好了nginx,在目錄:/usr/local/openresty/nginx 下。
修改/usr/local/openresty/nginx/conf/nginx.conf,将配置檔案使用的根設定為root,目的就是将來要使用lua腳本的時候 ,直接可以加載在root下的lua腳本。
cd /usr/local/openresty/nginx/conf
vi nginx.conf
修改代碼如下:
3.測試通路
重新開機下centos虛拟機,然後通路測試Nginx
通路位址:http://192.168.211.132/
4.廣告的載入和讀取
實作思路:
先查詢openresty本地緩存 如果 沒有
再查詢redis中的資料,如果沒有
再查詢mysql中的資料,但凡有資料 則傳回即可。
1.聲明nginx緩存
lua_shared_dict dis_cache 128m;
2.在/root/lua目錄下建立read_content.lua:
ngx.header.content_type="application/json;charset=utf8"
local uri_args = ngx.req.get_uri_args();
local id = uri_args["id"];
--擷取本地緩存
local cache_ngx = ngx.shared.dis_cache;
--根據ID 擷取本地緩存資料
local contentCache = cache_ngx:get('content_cache_'..id);
if contentCache == "" or contentCache == nil then
local redis = require("resty.redis");
local red = redis:new()
red:set_timeout(2000)
red:connect("192.168.211.132", 6379)
local rescontent=red:get("content_"..id);
if ngx.null == rescontent then
local cjson = require("cjson");
local mysql = require("resty.mysql");
local db = mysql:new();
db:set_timeout(2000)
local props = {
host = "192.168.211.132",
port = 3306,
database = "changgou_content",
user = "root",
password = "123456"
}
local res = db:connect(props);
local select_sql = "select url,pic from tb_content where status ='1' and category_id="..id.." order by sort_order";
res = db:query(select_sql);
local responsejson = cjson.encode(res);
red:set("content_"..id,responsejson);
ngx.say(responsejson);
db:close()
else
cache_ngx:set('content_cache_'..id, rescontent, 10*60);
ngx.say(rescontent)
end
red:close()
else
ngx.say(contentCache)
end
3.在nginx.conf中進行調用
在/usr/local/openresty/nginx/conf/nginx.conf中配置如下:
location /read_content {
content_by_lua_file /root/lua/read_content.lua;
}
5. 控制并發量
1. nginx的限流
nginx提供兩種限流的方式:
- 一是控制速率
- 二是控制并發連接配接數
(1) 控制速率
- nginx的配置示意圖如下 修改/usr/local/openresty/nginx/conf/nginx.conf:
user root root;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#cache
lua_shared_dict dis_cache 128m;
#限流設定
limit_req_zone $binary_remote_addr zone=contentRateLimit:10m rate=2r/s;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
location /update_content {
content_by_lua_file /root/lua/update_content.lua;
}
location /read_content {
#使用限流配置
limit_req zone=contentRateLimit;
content_by_lua_file /root/lua/read_content.lua;
}
}
}
配置說明:
binary_remote_addr 是一種key,表示基于 remote_addr(用戶端IP) 來做限流,binary_ 的目的是壓縮記憶體占用量。
zone:定義共享記憶體區來存儲通路資訊, contentRateLimit:10m 表示一個大小為10M,名字為contentRateLimit的記憶體區域。1M能存儲16000 IP位址的通路資訊,10M可以存儲16W IP位址通路資訊。
rate 用于設定最大通路速率,rate=10r/s 表示每秒最多處理10個請求。Nginx 實際上以毫秒為粒度來跟蹤請求資訊,是以 10r/s 實際上是限制:每100毫秒處理一個請求。這意味着,自上一個請求處理完後,若後續100毫秒内又有請求到達,将拒絕處理該請求.我們這裡設定成2 友善測試。
處理突發流量
上面例子限制 2r/s,如果有時正常流量突然增大,超出的請求将被拒絕,無法處理突發流量,可以結合 burst 參數使用來解決該問題。
例如,如下配置表示:
上圖代碼如下:
server {
listen 80;
server_name localhost;
location /update_content {
content_by_lua_file /root/lua/update_content.lua;
}
location /read_content {
limit_req zone=contentRateLimit burst=4;
content_by_lua_file /root/lua/read_content.lua;
}
}
burst 譯為突發、爆發,表示在超過設定的處理速率後能額外處理的請求數,當 rate=10r/s 時,将1s拆成10份,即每100ms可處理1個請求。
此處,burst=4 ,若同時有4個請求到達,Nginx 會處理第一個請求,剩餘3個請求将放入隊列,然後每隔500ms從隊列中擷取一個請求進行處理。若請求數大于4,将拒絕處理多餘的請求,直接傳回503.
不過,單獨使用 burst 參數并不實用。假設 burst=50 ,rate依然為10r/s,排隊中的50個請求雖然每100ms會處理一個,但第50個請求卻需要等待 50 * 100ms即 5s,這麼長的處理時間自然難以接受。
是以,burst 往往結合 nodelay 一起使用。
例如:如下配置:
server {
listen 80;
server_name localhost;
location /update_content {
content_by_lua_file /root/lua/update_content.lua;
}
location /read_content {
limit_req zone=contentRateLimit burst=4 nodelay;
content_by_lua_file /root/lua/read_content.lua;
}
}
如上表示:
平均每秒允許不超過2個請求,突發不超過4個請求,并且處理突發4個請求的時候,沒有延遲,等到完成之後,按照正常的速率處理。
如上兩種配置結合就達到了速率穩定,但突然流量也能正常處理的效果。完整配置代碼如下:
user root root;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#cache
lua_shared_dict dis_cache 128m;
#限流設定
limit_req_zone $binary_remote_addr zone=contentRateLimit:10m rate=2r/s;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
location /update_content {
content_by_lua_file /root/lua/update_content.lua;
}
location /read_content {
limit_req zone=contentRateLimit burst=4 nodelay;
content_by_lua_file /root/lua/read_content.lua;
}
}
}
(2) 控制并發量
ngx_http_limit_conn_module 提供了限制連接配接數的能力。主要是利用limit_conn_zone和limit_conn兩個指令。
利用連接配接數限制 某一個使用者的ip連接配接的數量來控制流量。
注意:并非所有連接配接都被計算在内 隻有當伺服器正在處理請求并且已經讀取了整個請求頭時,才會計算有效連接配接。此處忽略測試。
配置文法:
Syntax: limit_conn zone number;
Default: —;
Context: http, server, location;
(1)配置限制固定連接配接數
如下,配置如下:
上圖配置如下:
http {
include mime.types;
default_type application/octet-stream;
#cache
lua_shared_dict dis_cache 128m;
#限流設定
limit_req_zone $binary_remote_addr zone=contentRateLimit:10m rate=2r/s;
#根據IP位址來限制,存儲記憶體大小10M
limit_conn_zone $binary_remote_addr zone=addr:1m;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
#所有以brand開始的請求,通路本地changgou-service-goods微服務
location /brand {
limit_conn addr 2;
proxy_pass http://192.168.211.1:18081;
}
location /update_content {
content_by_lua_file /root/lua/update_content.lua;
}
location /read_content {
limit_req zone=contentRateLimit burst=4 nodelay;
content_by_lua_file /root/lua/read_content.lua;
}
}
}
表示:
limit_conn_zone $binary_remote_addr zone=addr:10m; 表示限制根據使用者的IP位址來顯示,設定存儲位址為的記憶體大小10M
limit_conn addr 2; 表示 同一個位址隻允許連接配接2次。
限制每個用戶端IP與伺服器的連接配接數,同時限制與虛拟伺服器的連接配接總數。
如下配置:
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;
server {
listen 80;
server_name localhost;
charset utf-8;
location / {
limit_conn perip 10;#單個用戶端ip與伺服器的連接配接數.
limit_conn perserver 100; #限制與伺服器的總連接配接數
root html;
index index.html index.htm;
}
}