OpenResty 가 흐름 제한 을 실현 하 는 몇 가지 방식
api
게 이 트 웨 이 를 닫 을 때 간단 한 흐름 제한 을 한 적 이 있다. 예 를 들 어 정적 차단 과 동적 차단 등 이다.정적 차단 은 특정한 인터페이스 가 일정 시간 창 에 있 는 요청 수 를 제한 하 는 것 이다.사용 자 는 시스템 에서 그들의 인터페이스 에 초당 최대 호출 량 을 설정 할 수 있 습 니 다. 만약 에 이 제한 을 초과 하면 서비스 이 인 터 페 이 스 를 거부 합 니 다. 동적 차단 도 정적 차단 을 바탕 으로 개선 할 수 있 습 니 다. 우 리 는 현재 시스템 의 응답 시간 에 따라 제한 흐름 의 한도 값 을 동적 으로 조정 할 수 있 습 니 다. 만약 에 응답 이 빠 르 면 한도 값 을 크게 조정 하고 더 많은 요 구 를 할 수 있 습 니 다.반대로 흐름 제한 한도 값 을 자동 으로 낮 추고 소량의 요청 만 통과 시킨다.사실 이것 은 매우 간단 한 흐름 제한 방식 이다.하지만 이 장면 들 은 우리 가 개발 할 때 자주 만 나 기 때문에 여기 서 사용 합 니 다.
OpenResty
대략 흔히 볼 수 있 는 제한 방식 을 실현 하 다.(이곳 에 서 는 OpenResty1.13.6.1
버 전의 자체 테이프 lua-resty-limit-traffic
모듈 을 사용 하여 실현 하기에 더욱 편리 합 니 다)인터페이스 총 병발 수 제한
장면:
ip
동시 접속 수 제한1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
ua_shared_dict my_limit_conn_store 100m;
...
location /hello {
access_by_lua_block {
local limit_conn = require "resty.limit.conn"
-- ip 1
-- burst 0, , 503,
-- , burst ( )
-- ( ) ,
local lim, err = limit_conn.new("my_limit_conn_store", 1, 0, 0.5)
if not lim then
ngx.log(ngx.ERR, "failed to instantiate a resty.limit.conn object: ", err)
return ngx.exit(500)
end
local key = ngx.var.binary_remote_addr
-- commit true shared dict key ,
-- false
local delay, err = lim:incoming(key, true)
if not delay then
if err == "rejected" then
return ngx.exit(503)
end
ngx.log(ngx.ERR, "failed to limit req: ", err)
return ngx.exit(500)
end
-- shared dict , ctx ,
-- ,
if lim:is_committed() then
local ctx = ngx.ctx
ctx.limit_conn = lim
ctx.limit_conn_key = key
ctx.limit_conn_delay = delay
end
local conn = err
-- delay ,
-- , 100 , 200 , 500 , 200
-- 100 , 200 , 200 ,0-100 0.5 ,
-- 101-200 0.5*2=1 (0.5 )
if delay >= 0.001 then
ngx.sleep(delay)
end
}
log_by_lua_block {
local ctx = ngx.ctx
local lim = ctx.limit_conn
if lim then
local key = ctx.limit_conn_key
-- , shared dict ,
-- , limit_conn.new ,
--
local conn, err = lim:leaving(key, 0.5)
if not conn then
ngx.log(ngx.ERR,
"failed to record the connection leaving ",
"request: ", err)
return
end
end
}
proxy_pass http://10.100.157.198:6112;
proxy_set_header Host $host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 60;
proxy_read_timeout 600;
proxy_send_timeout 600;
설명: 사실 이곳 은 설정 되 어 있 지 않 습 니 다.
burst
의 값 은 단순 한 제한 최대 병발 수 입 니 다. 설정 하면 burst
의 값 과 지연 처 리 를 했 습 니 다. 사실은 병발 수 에 누 통 알고리즘 을 사 용 했 지만 지연 처 리 를 하지 않 으 면 사용 하 는 토 큰 통 알고리즘 입 니 다. 아래 요청 수 에 누 통 토 큰 통 을 사용 하 는 부분 을 참고 하여 병발 수의 누 통 토 큰 통 은 이와 비슷 합 니 다.인터페이스 시간 창 요청 수 제한
필드: 제한
ip
분당 120 회 만 호출 가능 /hello
인터페이스 (시간 대 시작 시 120 개의 요청 을 한꺼번에 놓 칠 수 있 음)1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
lua_shared_dict my_limit_count_store 100m;
...
init_by_lua_block {
require "resty.core"
}
....
location /hello {
access_by_lua_block {
local limit_count = require "resty.limit.count"
-- rate: 10/min
local lim, err = limit_count.new("my_limit_count_store", 120, 60)
if not lim then
ngx.log(ngx.ERR, "failed to instantiate a resty.limit.count object: ", err)
return ngx.exit(500)
end
local key = ngx.var.binary_remote_addr
local delay, err = lim:incoming(key, true)
-- , ( 0, )
if not delay then
if err == "rejected" then
return ngx.exit(503)
end
ngx.log(ngx.ERR, "failed to limit count: ", err)
return ngx.exit(500)
end
}
proxy_pass http://10.100.157.198:6112;
proxy_set_header Host $host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 60;
proxy_read_timeout 600;
proxy_send_timeout 600;
}
부 드 러 운 제한 인터페이스 요청 수
필드: 제한
ip
분당 120 회 만 호출 가능 /hello
인터페이스 (매 끄 러 운 처리 요청, 즉 1 초 에 2 개의 요청 을 놓 치 는 것)1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
lua_shared_dict my_limit_req_store 100m;
....
location /hello {
access_by_lua_block {
local limit_req = require "resty.limit.req"
-- rate=2/s, 0,( )
-- resty.limit.req ,
local lim, err = limit_req.new("my_limit_req_store", 2, 0)
if not lim then
ngx.log(ngx.ERR, "failed to instantiate a resty.limit.req object: ", err)
return ngx.exit(500)
end
local key = ngx.var.binary_remote_addr
local delay, err = lim:incoming(key, true)
if not delay then
if err == "rejected" then
return ngx.exit(503)
end
ngx.log(ngx.ERR, "failed to limit req: ", err)
return ngx.exit(500)
end
}
proxy_pass http://10.100.157.198:6112;
proxy_set_header Host $host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 60;
proxy_read_timeout 600;
proxy_send_timeout 600;
}
누 출 통 알고리즘 제한 흐름
필드: 제한
ip
분당 120 회 만 호출 가능 /hello
인터페이스 (부 드 러 운 처리 요청, 즉 1 초 에 2 개의 요청 을 놓 치 는 것), 부분 을 초과 하여 통 에 들 어가 기다 리 고 (통 용량 은 60), 통 이 가득 차 면 흐름 제한 을 한다.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
lua_shared_dict my_limit_req_store 100m;
....
location /hello {
access_by_lua_block {
local limit_req = require "resty.limit.req"
-- rate=2/s, 0,( )
-- resty.limit.req ,
local lim, err = limit_req.new("my_limit_req_store", 2, 60)
if not lim then
ngx.log(ngx.ERR, "failed to instantiate a resty.limit.req object: ", err)
return ngx.exit(500)
end
local key = ngx.var.binary_remote_addr
local delay, err = lim:incoming(key, true)
if not delay then
if err == "rejected" then
return ngx.exit(503)
end
ngx.log(ngx.ERR, "failed to limit req: ", err)
return ngx.exit(500)
end
-- , delay ,
-- , ,
--
if delay >= 0.001 then
ngx.sleep(delay)
end
}
proxy_pass http://10.100.157.198:6112;
proxy_set_header Host $host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 60;
proxy_read_timeout 600;
proxy_send_timeout 600;
}
토 큰 통 알고리즘 흐름 제한
토 큰 통 은 사실 누 출 통 의 역 조작 을 볼 수 있 습 니 다. 우리 가 요청 속 도 를 초과 하여 통 에 들 어 가 는 요 구 를 어떻게 처리 하 는 지 볼 수 있 습 니 다. 만약 에 우리 가 이 부분 을 대기 행렬 에 넣 었 다 면 사실은 누 출 통 알고리즘 을 사 용 했 습 니 다. 그러나 우리 가 이 부분의 돌발 요 구 를 직접 처리 할 수 있다 면 사실은 토 큰 통 알고리즘 을 사용 한 것 입 니 다.
필드: 제한
ip
분당 120 회 만 호출 가능 /hello
인터페이스 (부 드 러 운 처리 요청, 즉 1 초 에 2 개의 요청 을 놓 치지 만 일정한 돌발 유량 (돌발 유량, 즉 통 의 용량 (통 의 용량 은 60) 을 허용 하고 통 의 용량 을 초과 하면 직접 거절 합 니 다.여 기 는 통 에서 요청 한 지연 처리 코드 를 백 엔 드 서비스 로 바로 보 내 면 됩 니 다. 이렇게 하면 토 큰 통 을 사용 합 니 다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
lua_shared_dict my_limit_req_store 100m;
....
location /hello {
access_by_lua_block {
local limit_req = require "resty.limit.req"
local lim, err = limit_req.new("my_limit_req_store", 2, 0)
if not lim then
ngx.log(ngx.ERR, "failed to instantiate a resty.limit.req object: ", err)
return ngx.exit(500)
end
local key = ngx.var.binary_remote_addr
local delay, err = lim:incoming(key, true)
if not delay then
if err == "rejected" then
return ngx.exit(503)
end
ngx.log(ngx.ERR, "failed to limit req: ", err)
return ngx.exit(500)
end
-- , delay ,
-- , ,
--
if delay >= 0.001 then
-- ngx.sleep(delay)
end
}
proxy_pass http://10.100.157.198:6112;
proxy_set_header Host $host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 60;
proxy_read_timeout 600;
proxy_send_timeout 600;
}
설명: 사실
nginx
의 ngx_http_limit_req_module
이 모듈 의 delay
과 nodelay
는 여기 서 통 에 지연 처 리 를 요청 하 는 것 과 유사 한 두 가지 방안 이다. 즉, 각각 대응 하 는 누 출 통 과 토 큰 통 두 가지 알고리즘 이다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Openresty 및 Google BigQuery를 사용한 마이크로서비스 사용량 로깅Descartes Labs에서는 플랫폼 구축에 마이크로서비스 아키텍처를 사용해 왔습니다. Descartes Labs의 마이크로서비스 로깅, 특히 사용 로깅의 주요 요구 사항은 전체 위성 이미지 모음에 대한 API 액...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.