Rate limiter 's նախագծումը
1) Ինչու՞ rate limiting
Rate limiting-ը պաշտպանում է API-ի հասանելիությունը և տնտեսությունը 'կանգնեցնում է ֆլուդները, ռետերանների "փոթորիկները," credential stuffing "-ը, պաշտպանում է թանկ վիրահատությունները (դրամական գործարքները, արտադրությունը), հարթում է բեռը կախված համակարգերի վրա (BD/պրովայդերներ)։ Լավ դիզայնը տալիս է արդարություն (fairness), լատենտության կանխատեսելիությունը և պարզ SLO-ը։
Հիմնական նպատակները
Express RPS-ը և backend- ի պաշտպանությունը տեղափոխությունից։
Կառավարված «առաձգականությունը» (burst allowae)։
Հաճախորդների տարբերակումը (նախկին օգտագործողը/105-կազմակերպությունը/105-բանալին/105-IP/105-տարածաշրջանը)։
Ստոմոստային մոդել 'տարբեր «գներ» տարբեր վիրահատությունների համար։
2) Լիմիտների տեսակները
RPS-limits 'հարցումներ վայրկյանում/րոպեում։
Քվոտա 'ընդհանուր բյուջեն ժամանակահատվածում (օր/ամիս)։
Մրցակցություն 'միաժամանակ վիրահատություններ (www.kout, heavy job)։
Արագությունը/շերտը 'բայթ/վրկ (բեռնումը/բեռնումը)։
Կշռված սահմանները 'բարդության հարցման «արժեքը» (օրինակ, GraphQL complexity, batch չափսը)։
Հարմարվողական 'խստացվում են անոմալիաների դեպքում (կասկածելի ակտիվություն/սխալներ 401/403/5xx)։
3) Ալգորիթմներ և երբ դրանք կիրառվեն
3. 1 Fixed window counter
Պարզ է, որ հաշվիչը հաճախորդի վրա (օրինակ, 100 r/min)։
Պլյուսներ 'նվազագույն արժեքը։ Մինուսները '«տարածաշրջանի բերստերը» պատուհանի սահմաններում։
Երբ, ուղղանկյուն վահանակները, չնչին ճշգրտությունը, ցածր արժեքը։
3. 2 Sliding window (log / counter)
Լոգ 'պահպանում է վերջին հարցումների ժամանակը, ճշգրիտ, հիշողության ճանապարհները։
Counter 'երկու հարևան պատուհանների միջինը (rolling), ճշգրտության և գնի փոխզիջումը։
Երբ, հանրային API միջին ստանդարտի, անհրաժեշտ է լողալ առանց բարդ մաթեմատիկայի։
3. 3 Token bucket
Պարամետրեր 'արագություն' r '(հոսանքներ/վայրկյան) և հզորություն' b '(burst)։ Յուրաքանչյուր հարցում «այրում» է։
Պլյուսներ ՝ բնական burst allowae, պարզ կոմպոզիա։ Մինուսներ 'խիստ հավասարություն չկա։
Երբ, գրեթե միշտ RPS-ի համար, եթե անհրաժեշտ է «սալիկներ» 'b-ի սահմաններում։
3. 4 Leaky bucket (drip)
Հերթը, որից «դուրս է գալիս» ֆիքսված արագությամբ։
Պլյուսներ 'ուղիղ արձակուրդային հոսք։ Մինուսներ 'ավելի շատ ուշացումներ։
Երբ, արտաքին «փխրուն» պրովայդերների մոտ։
3. 5 GCRA (Generalized Cell Rate Algorithm)
Ժամադրության տեսական ժամանակի մոդելը (TAT)
«TAT _ next = max (TAT _ current, now) + 1/r», հարցումը ընդունվել է, եթե «now <= = TAT _ current + burst/r»։
Պլյուսներ ՝ խիստ, ճշգրիտ, քիչ հիշողություն (TAT-ի կողմից)։ Մինուսները 'ավելի բարդ հասկանալու համար։
Երբ անհրաժեշտ է խիստ վերահսկողություն և լող, բաշխված սահմանաչափեր։
3. 6 Մրցակցային սեմաֆորներ
Ակտիվ վիրահատությունների հաշվիչը; ե. - եթե «տոմսեր» կա; ելքը ազատումն է։
Երբ 'long-running վիրահատություն, հոսքեր, Socket, բեռնումը։
4) Ռուսական սահմանների մոդել
Բանալին = ատրիբուտների համադրություն
`client_id`/`api_key`/`user_id`/`org_id`
«IP/ASN/geo» (կոպիտ պաշտպանություն) (կոպիտ պաշտպանություն)
«endpoint/method» (տաք երթուղիներ)
'scope/plan/tier' (մոնետիզացիա)
«idempotency _ key» (write վիրահատություն)
Օգտագործեք հիերարխիա 'նախ խիստ ֆայլային բանալին, ապա տեղեկատվական-կազմակերպություն, ապա գլոբալ։
5) Հարցման քաշը (cost model)
Որոշեք "արժեքը" (q) "։
GraphQL 'բարդությունը 220 մ ³ խորության վրա։
REST 'պատասխանը/հարցումը, վիրահատության տեսակը (read = 1, write = 3, զեկույցը = 10)։
Batch: `cost = min(n, cap)`.
Limitirum-ը, ոչ թե «հարցումները» ՝ «budget-= cost (q)»։
6) Բաշխված ստանդարտ
6. 1 Lenta.ru
In-process: ultra-արագ, բայց ոչ ընդհանուր սահմանը (հարմար է տեղական «փափուկ» սահմանների համար)։
Redis: դե ֆակտո 2019։ INCR/EXPIRE, Lua-ջութակները (ատոմային), ZSET sliding-ի համար, TTL-ի բանալիները։
Envoy/NGINX/Kong/Traefik: ներկառուցված ֆիլտրեր; հարմար է պարագծի համար։
No Mesh: Տեղական սահմանները sidecar + գլոբալ համաժամացման վրա։
6. 2 Ատոմականություն և մրցավազք
Lua Redis-ում 'ստուգում և ստուգում մեկ գործողությամբ։
GCRA 'պահել մեկ TAT CAS/ջութակի հետ։
Ժամացույցի համաձայնությունը 'NTP, մոնոտոնային գաղտնիքներ։
Sharding: կոնսիստենտ հեշ բանալին; խուսափեք «տաք» շարիդներից։
6. 3 Երկրաչափություն
Տեղական լիմիտները տարածաշրջանի կլաստերի վրա + վերին գլոբալ (coarse)։
CRDT/կրկնօրինակումը զգույշ է (ուշացում, կրկնակի սպառում)։ Նախընտրելի է տարածաշրջանային սահմանները պահեստով։
7) Քաղաքականություն և գերակայություն
Ծրագրերը ՝ Free/Windows/Enterprise տարբեր «r», «b», քվոտաների հետ։
Առաջնահերթությունները '«թանկ» երթուղիները ստանում են ավելի քիչ սահմաններ կամ ավելի մեծ cost։
Ցուցակները ՝ allow-list ինտեգրման համար, deny ASN/2019/TOR։
Էսկալացիա 'կրկնվող ավելացումով, մենք իջեցնում ենք սահմանը, ներկայացնում ենք proof-of-work/challengi։
8) Եզրագծերի օրինակներ
8. 1 Envoy (HTTRATE limit corter, կեղծ)
yaml rate_limit:
domain: public-api descriptors:
- key: api_key rate_limit:
unit: second requests_per_unit: 50 burst: 100
- key: api_key value: payments. write rate_limit:
unit: second requests_per_unit: 5 burst: 10
8. 2 NGINX (lua + Redis, կեղծ)
nginx lua_shared_dict limits 10m;
location /api/ {
access_by_lua_block {
local key = ngx. var. arg_apikey.. ":".. ngx. var. request_method.. ":".. ngx. var. uri
-- token bucket in Redis (evalsha)
local allowed, retry_after = ratelimit_allow(key, 50, 100) -- r=50/s, b=100 if not allowed then ngx. header["Retry-After"] = retry_after return ngx. exit(429)
end
}
proxy_pass http://backend;
}
8. 3 Մրցակցային լիմիտներ (կեղծ)
pseudo on_request_start(key):
if redis. incr_with_ttl("sem:" + key, ttl=60) > MAX_CONCURRENCY:
redis. decr("sem:" + key); reject(429)
on_request_finish(key):
redis. decr("sem:" + key)
8. 4 GCRA (կեղծ)
pseudo params: r tokens/sec, burst b tat = redis. get(key) or now allowed_time = tat - (b / r)
if now < allowed_time: reject(429, retry_after = allowed_time - now)
tat_next = max(tat, now) + 1/r redis. set(key, tat_next, ttl = ceil(b/r) + safety)
9) Ինտեգրումը գետերի, թայմաուտների և circuit breaker հետ
Retry-budget: Սահմանափակեք գետերի մասնաբաժինը մինչև X տոկոսը հիմնական պայմանագրից։
Jitter: backoff-ում միշտ ավելացրեք ջիտթերը, նվազեցնում է սինխրոն աճը։
Circuit breaker: բարձր սխալմամբ («5xx», timeouts) կրճատեք սահմանները կամ տեղափոխեք երթուղիների մի մասը «read-only»։
Hedging: կոկիկ; հաշվի առեք, որպեսզի չվնասեք բյուջեի սպառումը։
10) Դիտողությունն ու կառավարումը
Метрики: `rps_allowed`, `rps_blocked`, `429_rate`, `retry_after_avg`, `burst_used`, `quota_remaining`, `active_concurrency`.
Պիտակները 'լիմիտի, տարածաշրջանի, էնդպոինթուի, պլանի միջոցով։
Լուծումների լոգները (semple) 'ձախողման պատճառը, ռուսական հաշվիչները, TTL բանալին։
Dashbords: ջերմային քարտեզներ բաների/endpointam, «տաք» հաճախորդներ։
Ալերտներ '429> 2-5 տոկոսը կրիտիկական երթուղիներում, հաճախակի «սպառումը» քվոտաների, շարիդների անհավասարակշռության վրա։
11) Փորձարկում և վալիդացիա
Պայմանագրային թեստեր քաղաքական (աղյուսակներ «եթե-որ բան»)։
Բեռները 'բուրստներ (x10-ից r), երկար սարահարթ, «կեղտոտ» պաթերտոններ (slow-POST, երկար միացություններ)։
Chaos-2019 'անհավասար հոսքեր, clock drift, Redis/mesh։
A/B: canary rollout limites, shadow լուծումներ (տրամաբանություն, բայց չենք արգելափակում) նախքան միացումը։
12) Edge-Cass-ը և նրբությունները
Clock skew: օգտագործեք «now ()» մեկ աղբյուրից (սերվերից), ոչ թե հաճախորդի վերնագրերից։
Idempotency-Key: write-ի համար նվազեցնում է amplifox ռելսերի ժամանակ։
Batch վիրահատություն 'սահմանափակում եք մարտիկի չափսերը և ընդհանուր cost-ը։
Long-poll/Windows Socket: Սահմանափակեք ալիքների/ստորագրությունների քանակով և երկարությամբ։
Cold start: «տաք» հաշվիչների/կանխավճարի սկիզբը; հակառակ դեպքում կեղծ 429-ի աճը։
Հաշվարկային թանկ հարցումները 'սահմանափակեք մինչև բիզնես տրամաբանության կատարումը։
TTL: TTL-ի սահմանները պետք է ծածկեն պատուհանը + (safety margin)։
13) Հակաբոտիկ էսկալացիա
Քայլերը 'նախազգուշացում 429 + Retry-After' www.challeng (գլխարկ/pazl) wwww.ru բլոկը։
Ազդանշաններ ՝ device-fingerprint, կուրսորի/թայմինգի վարքագիծը, TOR/2019/հանրակացարանները։
Քաղաքական գործիչները պետք է լինեն դետերմինացված և վերարտադրվեն ֆորուլֆիկայի համար։
14) Անվտանգություն և ընկերակցություն
Deny-by-2019-ը տեղադրված է կրիտիկական երթուղիների վրա (write/ֆինանսներ)։
Աուդիտ. Պահպանեք որոշումները կարգավորող գործընթացների և վերլուծությունների համար։
PII 'լիմիթների բանալիները չպետք է բացահայտեն անձնական տվյալները լոգարաններում։
15) Չեկ-թուղթ պատրաստակամության համար
- Սահմանվում են սահմանների բանալիները և cost-մոդելը։
- Ընտրվել է ալգորիթմ (token bucket/GCRA) և պահեստ (Redis/դարպաս)։
- Քաղաքական հաճախորդների համար + գլոբալ «ապահովիչներ»։
- Մրցակցային սահմանները երկար վիրահատությունների համար։
- Retry-budget, backoff ջիթերի հետ, circuit breaker ինտեգրումը։
- Dashbords/alerts, մոդելավորված լուծումների լույսեր։
- Canary-international և shadow ռեժիմը։
- Փոթորիկների թեստերը, երկար սարահարթը, Redis-ը, clock skew-ը։
- Հաճախորդների համար '429, «Retry-After», էքսպոնենցիալ backoff օրինակներ։
16) TL; DR
Օգտագործեք token bucket կամ GCRA Redis/դարպասի հետ, նախագծեք սահմանների բանալիները և հարցումների արժեքը, ավելացրեք մրցակցային սեմաֆորներ երկար վիրահատությունների համար, ինտեգրեք retry-budget և circuit breaker, դիտարկեք 429 և «burst-temples» canary/shadow և անպայման փորձարկեք փոթորիկները և ձախողումը։