ЁЯЪз рдзрдбрд╛ 12 тАФ Backpressure & рд╕рдВрдкреВрд░реНрдг рдЪрд┐рддреНрд░: "рдирдВрддрд░ рдпрд╛" рд▓рд╡рдХрд░ рд╕рд╛рдВрдЧрд╛
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 12 ┬╖ рдорд╛рдЧреЗ: lesson-11-exactly-once ┬╖ рд╢реЗрд╡рдЯрдЪрд╛ рдзрдбрд╛ ЁЯОУ
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбреЗ 01тАУ11, рдЖрдгрд┐ backpressure: node рдХрд░реВ рд╢рдХрддреЗ рддреНрдпрд╛рдкреЗрдХреНрд╖рд╛ рдЬрд╛рд╕реНрдд рдХрд╛рдо рдЖрд▓реЗ рдХреА
unbounded рд░рд╛рдВрдЧ рддреНрдпрд╛ overload рдЪреЗ рд░реВрдкрд╛рдВрддрд░ рд╕рддрдд рд╡рд╛рдврдд рдЬрд╛рдгрд╛рд▒реНрдпрд╛ рдерд╛рдВрдмрдгреНрдпрд╛рдд рдХрд░рддреЗ; bounded рд░рд╛рдВрдЧ
"рдирдВрддрд░ рдпрд╛" (429 / 503 + Retry-After) рдЕрд╕реЗ рд╕рд╛рдВрдЧреВрди рд▓рд╡рдХрд░ рдирдХрд╛рд░ рджреЗрддреЗ рдЖрдгрд┐ рдерд╛рдВрдмрдгреЗ
рдХрдореА рдареЗрд╡рддреЗ. рд╢рд┐рд╡рд╛рдп load shedding, backoff рдЖрдгрд┐ jitter рд╕рд╣ retries, rate limiting рдЖрдгрд┐
circuit breaking тАФ рдЖрдгрд┐ рдХреЛрд░реНрд╕рдЪрд╛ рд╕рдВрдкреВрд░реНрдг рдирдХрд╛рд╢рд╛. dist/demo.py рдордзреАрд▓
backpressure() рдЖрдгрд┐ dist/sim.py рдордзреАрд▓ BoundedQueue.
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
рдкреНрд░рд╡реЗрд╢рд╛рдЪреНрдпрд╛ рджрд┐рд╡рд╢реА рдкреБрдгреЗ office рдордзреНрдпреЗ рджрд░ second рд▓рд╛ 120 рдкрд╛рд▓рдХ рдпреЗрддрд╛рдд. рдХрд╛рд░рдХреВрди рджрд░ second рд▓рд╛ 100 рдЬрдгрд╛рдВрдирд╛ рдорджрдд рдХрд░реВ рд╢рдХрддрд╛рдд. рдкреНрд░рддреНрдпреЗрдХ second рд▓рд╛ рдЖрдгрдЦреА 20 рдкрд╛рд▓рдХ рд░рд╛рдВрдЧреЗрдд рдЬреЛрдбрд▓реЗ рдЬрд╛рддрд╛рдд.
- рдХреЛрдгрддрд╛рд╣реА рдирд┐рдпрдо рдирд╛рд╣реА: рд░рд╛рдВрдЧ рд╡рд╛рдврддрдЪ рдЬрд╛рддреЗ. 5 seconds рдирдВрддрд░ рдирд╡реНрдпрд╛ рдкрд╛рд▓рдХрд╛рд▓рд╛ 1 second рдерд╛рдВрдмрд╛рд╡реЗ рд▓рд╛рдЧрддреЗ. 10 seconds рдирдВрддрд░ 2 seconds. рдПрдХрд╛ рдорд┐рдирд┐рдЯрд╛рдирдВрддрд░ рддреЗ рдХрд┐рддреАрддрд░реА рдЬрд╛рд╕реНрдд рд╣реЛрдИрд▓. рдорд╛рдЧрдЪреНрдпрд╛ рдкрд╛рд▓рдХрд╛рдВрдЪрд╛ рдзреАрд░ рд╕реБрдЯрддреЛ рдЖрдгрд┐ рддреЗ рдкреБрдиреНрд╣рд╛ рдпреЗрддрд╛рдд тАФ рддреНрдпрд╛рдореБрд│реЗ рд░рд╛рдВрдЧ рдЖрдгрдЦреАрдЪ рд▓рд╛рдВрдм рд╣реЛрддреЗ. ЁЯШй
- рдлрд╛рдЯрдХрд╛рд╡рд░ рдПрдХ рдирд┐рдпрдо: рджреАрдкрд┐рдХрд╛ рджрд╛рд░рд╛рдд рдЙрднреА рдЕрд╕рддреЗ. "рд░рд╛рдВрдЧреЗрдд 200 рдЬрдг рдмрд╕рддрд╛рдд. рд░рд╛рдВрдЧ рднрд░рд▓реА рдЕрд╕реЗрд▓, рддрд░ рдХреГрдкрдпрд╛ рдирдВрддрд░ рдпрд╛." ЁЯЪз рдХрд╛рд╣реА рдкрд╛рд▓рдХрд╛рдВрдирд╛ рд▓рдЧреЗрдЪ рдкрд░рдд рдкрд╛рдард╡рд▓реЗ рдЬрд╛рддреЗ. рдкрдг рдЖрдд рдЕрд╕рд▓реЗрд▓реЗ рд╕рдЧрд│реЗ рдЬрд╛рд╕реНрддреАрдд рдЬрд╛рд╕реНрдд рд╕реБрдорд╛рд░реЗ 1 second рдерд╛рдВрдмрддрд╛рдд, рдЖрдгрд┐ рдХрд╛рд░рдХреВрди рдХрд╛рдорд╛рд╢реА рдмрд░реЛрдмрд░реА рд░рд╛рдЦреВ рд╢рдХрддрд╛рдд.
рдХрд╛рд╣реА рд▓реЛрдХрд╛рдВрдирд╛ рдкрд░рдд рдкрд╛рдард╡рдгреЗ рдирд┐рд╖реНрдареБрд░ рд╡рд╛рдЯрддреЗ. рдкрдг рджреБрд╕рд░рд╛ рдкрд░реНрдпрд╛рдп рдореНрд╣рдгрдЬреЗ рд╕рдЧрд│реНрдпрд╛рдВрдирд╛рдЪ рдЦреВрдк рд╡реЗрд│ рдерд╛рдВрдмрд╛рд╡реЗ рд▓рд╛рдЧрддреЗ, рдЖрдгрд┐ office рд╕рдЧрд│реНрдпрд╛рдВрд╕рд╛рдареАрдЪ рдХрд╛рдо рдХрд░рдгреЗ рдерд╛рдВрдмрд╡рддреЗ.
рдЖрдгрд┐ рдкрд░рдд рдкрд╛рдард╡рд▓реЗрд▓реНрдпрд╛ рдкрд╛рд▓рдХрд╛рдВрд╕рд╛рдареА рдЖрдгрдЦреА рдПрдХ рдирд┐рдпрдо: рд╕рдЧрд│реЗ рдПрдХрд╛рдЪ рдХреНрд╖рдгреА рдкрд░рдд рдпреЗрдК рдирдХрд╛. рдереЛрдбреЗ рдерд╛рдВрдмрд╛, рдордЧ рдЖрдгрдЦреА рдереЛрдбреЗ рдЬрд╛рд╕реНрдд, рдЖрдгрд┐ рдереЛрдбрд╛рд╕рд╛ random рд╡реЗрд│ рдЬреЛрдбрд╛, рдореНрд╣рдгрдЬреЗ рдкреБрдврдЪреА рдЧрд░реНрджреА рд╡рд┐рдЦреБрд░рд▓реА рдЬрд╛рдИрд▓.
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart LR
in["ЁЯСк 120 requests/s arrive"] --> gate{"ЁЯЪз queue full?<br/>limit 200"}
gate -->|"yes"| shed["тЫФ 429 / 503 + Retry-After<br/>shed 100 in 10 s"]
gate -->|"no"| q["ЁЯУЛ bounded queue"]
q --> srv["ЁЯзСтАНЁЯТ╝ serve 100/s<br/>wait stays about 1.0 s"]
un["unbounded queue: wait 1.0 s after 5 s,<br/>2.0 s after 10 s, and still growing"]
ЁЯЧ║я╕П рд░реЗрдЦрд╛рдЯрд▓реЗрд▓реА рдЖрд╡реГрддреНрддреА + рдПрдХ lab: https://school-edh.pages.dev/distributed-systems/lesson-diagrams.html#l12
тЭУ рдХрд╛рдп
- Overload тАФ рдХрд╛рдо рд╣реЛрдК рд╢рдХрддреЗ рддреНрдпрд╛рдкреЗрдХреНрд╖рд╛ рд╡реЗрдЧрд╛рдиреЗ рдпреЗрддреЗ. рд░рд╛рдВрдЧ рджрд░ second рд▓рд╛ (arrival rate тИТ
service rate) рдЗрддрдХреА рд╡рд╛рдврддреЗ; 120 рдЖрдд рдЖрдгрд┐ 100 рдмрд╛рд╣реЗрд░ рдЕрд╕рддреАрд▓, рддрд░ overload рдЯрд┐рдХреЗрд▓ рддреЛрдкрд░реНрдпрдВрдд рджрд░ second рд▓рд╛
- Unbounded рд░рд╛рдВрдЧ тАФ рд╕рдЧрд│реЗ рд╕реНрд╡реАрдХрд╛рд░рддреЗ. рддреА рдХрдзреАрдЪ рдирдХрд╛рд░ рджреЗрдд рдирд╛рд╣реА, рддреНрдпрд╛рдореБрд│реЗ рдкреНрд░рддреНрдпреЗрдХ request рд╣рд│реВ рд╣реЛрддреЗ, memory рд╡рд╛рдврддреЗ, рдЖрдгрд┐ requests рдЕрдиреЗрдХрджрд╛ рдерд╛рдВрдмрд▓реНрдпрд╛рдирдВрддрд░ time out рд╣реЛрддрд╛рдд тАФ рдХреЛрдгрд╛рд╕рд╛рдареАрдЪ рдирд╕рд▓реЗрд▓реЗ рдХрд╛рдо. рдордЧ clients retry рдХрд░рддрд╛рдд, рдЖрдгрд┐ load рдЖрдгрдЦреА рд╡рд╛рдврддреЛ.
- Backpressure тАФ рд╡реНрдпрд╕реНрдд рднрд╛рдЧ рдЖрдкрд▓реНрдпрд╛ рдЖрдзреАрдЪреНрдпрд╛ рднрд╛рдЧрд╛рд▓рд╛ рд╣рд│реВ рд╡реНрд╣рд╛рдпрд▓рд╛ рдХрд┐рдВрд╡рд╛ рдкрд╛рдард╡рдгреЗ рдерд╛рдВрдмрд╡рд╛рдпрд▓рд╛ рд╕рд╛рдВрдЧрддреЛ: рднрд░рд▓реЗрд▓реА bounded рд░рд╛рдВрдЧ, рдирд╛рдХрд╛рд░рд▓реЗрд▓реА request, TCP flow control, рдЬреЗрд╡рдвреЗ рд╣рд╛рддрд╛рд│рддрд╛ рдпреЗрдИрд▓ рддреЗрд╡рдвреЗрдЪ рдУрдвреВрди рдШреЗрдгрд╛рд░рд╛ consumer (Kafka consumers pull рдХрд░рддрд╛рдд).
- Bounded рд░рд╛рдВрдЧ тАФ рдПрдХ рдХрдорд╛рд▓ рд▓рд╛рдВрдмреА; рддреНрдпрд╛рдкрд▓реАрдХрдбреЗ рдирд╡реЗ рдХрд╛рдо рд▓рдЧреЗрдЪ рдирд╛рдХрд╛рд░рд▓реЗ рдЬрд╛рддреЗ. рд╕реНрд╡реАрдХрд╛рд░рд▓реЗрд▓реНрдпрд╛ рдХрд╛рдорд╛рд╕рд╛рдареАрдЪреЗ рдерд╛рдВрдмрдгреЗ рд╕реБрдорд╛рд░реЗ limit ├╖ service rate рдкреЗрдХреНрд╖рд╛ рдХрдореА рд░рд╛рд╣рддреЗ.
- Load shedding тАФ рдмрд╛рдХреАрдЪреНрдпрд╛рдВрдЪреЗ рд╕рдВрд░рдХреНрд╖рдг рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдХрд╛рд╣реА рдХрд╛рдо рдЬрд╛рдгреВрдирдмреБрдЬреВрди рдирд╛рдХрд╛рд░рдгреЗ. рд╕рд░реНрд╡рд╛рдд рдХрдореА рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ рдЖрдзреА рдЯрд╛рдХрд╛ (payments рдЪреНрдпрд╛ рдЖрдзреА analytics), рдЖрдгрд┐ рд▓рд╡рдХрд░ рдЯрд╛рдХрд╛ тАФ рджрд╛рд░рд╛рддрдЪ, рдЕрд░реНрдзреЗ рдХрд╛рдо рдХреЗрд▓реНрдпрд╛рдирдВрддрд░ рдирд╡реНрд╣реЗ.
- 429 Too Many Requests / 503 Service Unavailable +
Retry-AfterтАФ "рдирдВрддрд░ рдпрд╛" рд╕рд╛рдВрдЧрдгреНрдпрд╛рдЪреЗ HTTP рдорд╛рд░реНрдЧ;Retry-AfterрдХреЗрд╡реНрд╣рд╛ рддреЗ рд╕рд╛рдВрдЧрддреЗ (seconds рдордзреНрдпреЗ, рдХрд┐рдВрд╡рд╛ рддрд╛рд░реАрдЦ). - Rate limiting тАФ рдкреНрд░рддреНрдпреЗрдХ client рдЪреНрдпрд╛ rate рд╡рд░ рдорд░реНрдпрд╛рджрд╛ (рдЕрдиреЗрдХрджрд╛ token bucket: tokens рд╕реНрдерд┐рд░ rate рдиреЗ рдкреБрдиреНрд╣рд╛ рднрд░рддрд╛рдд, рдкреНрд░рддреНрдпреЗрдХ request рдПрдХ рдЦрд░реНрдЪ рдХрд░рддреЗ, рдЫреЛрдЯрд╛ burst рд╕рд╛рдард╡рд▓реЗрд▓реЗ tokens рд╡рд╛рдкрд░реВ рд╢рдХрддреЛ).
- Exponential backoff рдЖрдгрд┐ jitter рд╕рд╣ retries тАФ рдкреНрд░рддреНрдпреЗрдХ failure рдирдВрддрд░ рдЬрд╛рд╕реНрдд рд╡реЗрд│ рдерд╛рдВрдмрд╛ (рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде 100 ms, 200 ms, 400 ms тАж рдПрдХрд╛ cap рдкрд░реНрдпрдВрдд), рдЖрдгрд┐ рддреНрдпрд╛ рд╕рдВрдЦреНрдпреЗрдкрд░реНрдпрдВрддрдЪрд╛ random рд╡реЗрд│ рдирд┐рд╡рдбрд╛ ("full jitter"), рдореНрд╣рдгрдЬреЗ рд╣рдЬрд╛рд░реЛ clients рдПрдХрд╛рдЪ рдХреНрд╖рдгреА retry рдХрд░рдгрд╛рд░ рдирд╛рд╣реАрдд. Retries рдЪреА рд╕рдВрдЦреНрдпрд╛ рдорд░реНрдпрд╛рджрд┐рдд рдареЗрд╡рд╛, рдХрд┐рдВрд╡рд╛ retry budget рдареЗрд╡рд╛ (рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, retries рдЬрд╛рд╕реНрддреАрдд рдЬрд╛рд╕реНрдд 10% requests).
- Circuit breaker тАФ рдПрдХрд╛ dependency рд▓рд╛ рдЕрдиреЗрдХ рд╡реЗрд│рд╛ рдЕрдкрдпрд╢ рдЖрд▓реНрдпрд╛рд╡рд░, рдХрд╛рд╣реА рдХрд╛рд│ рддрд┐рд▓рд╛ call рдХрд░рдгреЗ рдерд╛рдВрдмрд╡рд╛ рдЖрдгрд┐ рд▓рдЧреЗрдЪ fail рдХрд░рд╛; рдордЧ рдХрд╛рд╣реА test requests рдЬрд╛рдК рджреНрдпрд╛.
ЁЯдФ рдХрд╛
рдХрд╛рд░рдг рдпрд╛рдЖрдзреАрдЪрд╛ рдкреНрд░рддреНрдпреЗрдХ рдзрдбрд╛ рддрд╛рдгрд╛рдЦрд╛рд▓реА рдЬрд╛рд╕реНрддреАрдЪреЗ рдХрд╛рдо рдирд┐рд░реНрдорд╛рдг рдХрд░рддреЛ: timeouts рдирдВрддрд░рдЪреЗ retries (01, 11), failovers (05), repairs (06), elections (09). рдорд░реНрдпрд╛рджрд╛ рдирд╕рд▓реЗрд▓реА system рдЫреЛрдЯреНрдпрд╛ overload рдЪреЗ рдкреВрд░реНрдг overload рдордзреНрдпреЗ рд░реВрдкрд╛рдВрддрд░ рдХрд░рддреЗ тАФ рд░рд╛рдВрдЧ рд╡рд╛рдврддреЗ, рдкреНрд░рддреНрдпреЗрдХ request time out рд╣реЛрддреЗ, рдкреНрд░рддреНрдпреЗрдХ client retry рдХрд░рддреЛ, рдЖрдгрд┐ load рджреБрдкреНрдкрдЯ рд╣реЛрддреЛ. рд▓рд╡рдХрд░ "рдирдВрддрд░ рдпрд╛" рд╕рд╛рдВрдЧрдгреЗ рд╣реЗрдЪ рдмрд╛рдХреАрдЪреА system рдЪрд╛рд▓реВ рдареЗрд╡рддреЗ.
ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)
dist/sim.py рдордзреАрд▓ BoundedQueue(limit) рджрд░ second рд▓рд╛ рдПрдХ tick рдЪрд╛рд▓рд╡рддреЗ:
run(arrivals, served_per_tick) рд░рд┐рдХрд╛рдореНрдпрд╛ рдЬрд╛рдЧреЗрдкрд░реНрдпрдВрдд (limit - q;
limit=None рдореНрд╣рдгрдЬреЗ рдорд░реНрдпрд╛рджрд╛ рдирд╛рд╣реА) рдирд╡реНрдпрд╛ arrivals рдШреЗрддреЗ, рдЙрд░рд▓реЗрд▓реНрдпрд╛ shed рдордзреНрдпреЗ рдореЛрдЬрддреЗ, served_per_tick рдкрд░реНрдпрдВрдд serve рдХрд░рддреЗ,
рдЖрдгрд┐ рдерд╛рдВрдмрдгреЗ queue ├╖ served_per_tick seconds рдореНрд╣рдгреВрди рдиреЛрдВрджрд╡рддреЗ. dist/demo.py рдордзреАрд▓
backpressure() 100/s service рд╡рд┐рд░реБрджреНрдз 120 requests/s рдЪреЗ 10 seconds рдЪрд╛рд▓рд╡рддреЗ,
рдорд░реНрдпрд╛рджреЗрд╢рд┐рд╡рд╛рдп рдЖрдгрд┐ 200 рдЪреНрдпрд╛ рдорд░реНрдпрд╛рджреЗрд╕рд╣.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
python3 dist/demo.py backpressure
python3 - <<'EOF'
import sys; sys.path.insert(0, "dist"); from sim import BoundedQueue
for rate in (90, 120, 200):
for limit in (None, 200, 400):
q = BoundedQueue(limit); w = q.run([rate] * 10, served_per_tick=100)
print(f"{rate:>3}/s arrive ┬╖ limit {limit or 'none':>4} тЖТ wait after 10 s {w[-1]:>4.1f} s ┬╖ shed {q.shed:>4}")
EOF
python3 dist/demo.py
python3 dist/test_dist.py
тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ
backpressure рд╣реЗ print рдХрд░рддреЗ:
тФАтФА 120 requests/s arrive, 100/s can be served ┬╖ queue limit none тЖТ wait after 5 s 1.0 s, after 10 s 2.0 s ┬╖ shed 0
тФАтФА 120 requests/s arrive, 100/s can be served ┬╖ queue limit 200 тЖТ wait after 5 s 1.0 s, after 10 s 1.0 s ┬╖ shed 100
рддреБрдордЪрд╛ snippet рд╣реЗ print рдХрд░рддреЛ:
90/s arrive ┬╖ limit none тЖТ wait after 10 s 0.0 s ┬╖ shed 0
90/s arrive ┬╖ limit 200 тЖТ wait after 10 s 0.0 s ┬╖ shed 0
90/s arrive ┬╖ limit 400 тЖТ wait after 10 s 0.0 s ┬╖ shed 0
120/s arrive ┬╖ limit none тЖТ wait after 10 s 2.0 s ┬╖ shed 0
120/s arrive ┬╖ limit 200 тЖТ wait after 10 s 1.0 s ┬╖ shed 100
120/s arrive ┬╖ limit 400 тЖТ wait after 10 s 2.0 s ┬╖ shed 0
200/s arrive ┬╖ limit none тЖТ wait after 10 s 10.0 s ┬╖ shed 0
200/s arrive ┬╖ limit 200 тЖТ wait after 10 s 1.0 s ┬╖ shed 900
200/s arrive ┬╖ limit 400 тЖТ wait after 10 s 3.0 s ┬╖ shed 700
рдкреВрд░реНрдг demo тЬЕ done тАФ the branches agree рдиреЗ рд╕рдВрдкрддреЛ, рдЖрдгрд┐ tests 12/12 passed рдиреЗ.
ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ
рдХреНрд╖рдорддреЗрдЪреНрдпрд╛ рдЦрд╛рд▓реА (90/s) рдорд░реНрдпрд╛рджреЗрд▓рд╛ рдХрд╛рд╣реАрдЪ рдорд╣рддреНрддреНрд╡ рдирд╕рддреЗ. 200/s рд╡рд░ рдорд░реНрдпрд╛рджрд╛ рдирд╕рддрд╛рдирд╛ рдерд╛рдВрдмрдгреЗ 10 seconds рдордзреНрдпреЗ 10 seconds рдкрд░реНрдпрдВрдд рдкреЛрд╣реЛрдЪрд▓реЗ рдЖрдгрд┐ рдЕрдЬреВрдирд╣реА рд╡рд╛рдврдд рд╣реЛрддреЗ; 200 рдЪреНрдпрд╛ рдорд░реНрдпрд╛рджреЗрд╕рд╣ рддреЗ 1 second рд╡рд░рдЪ рд░рд╛рд╣рд┐рд▓реЗ, 900 requests рдЯрд╛рдХреВрди рджреЗрдгреНрдпрд╛рдЪреНрдпрд╛ рдХрд┐рдВрдорддреАрд╡рд░, рдЬреНрдпрд╛рдВрдирд╛ рдЭрдЯрдкрдЯ "рдирдВрддрд░ рдпрд╛" рдорд┐рд│рд╛рд▓реЗ. рдорд░реНрдпрд╛рджрд╛ рдореНрд╣рдгрдЬреЗ рдХрдорд╛рд▓ рдерд╛рдВрдмрдгреНрдпрд╛рдЪреА рдирд┐рд╡рдб: рдЗрдереЗ 400 рд╕реБрдорд╛рд░реЗ 3 seconds рдкрд░реНрдпрдВрдд рдерд╛рдВрдмреВ рджреЗрддреЗ. рддреА user (рдХрд┐рдВрд╡рд╛ caller рдЪрд╛ timeout) рдЦрд░реЛрдЦрд░ рдХрд┐рддреА рд╡реЗрд│ рдерд╛рдВрдмреЗрд▓ рддреНрдпрд╛рд╡рд░реВрди рдирд┐рд╡рдбрд╛.
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
- service рдЪреНрдпрд╛ рдЖрдд unbounded in-memory queues
- рд░рд╛рдВрдЧреЗрдЪреА рдорд░реНрдпрд╛рджрд╛ рдЗрддрдХреА рдореЛрдареА рдХреА рд╕реНрд╡реАрдХрд╛рд░рд▓реЗрд▓реНрдпрд╛ requests serve рд╣реЛрдгреНрдпрд╛рдЖрдзреАрдЪ time out рд╣реЛрддрд╛рдд
- backoff рдЖрдгрд┐ jitter рд╢рд┐рд╡рд╛рдп рд▓рдЧреЗрдЪ retry рдХрд░рдгреЗ тАФ "retry storm"
- рдкреНрд░рддреНрдпреЗрдХ рдерд░рд╛рд╡рд░ retries (client, gateway, service): рдПрдХрд╛ click рд╕рд╛рдареА 3 ├Ч 3 ├Ч 3 = 27 рдкреНрд░рдпрддреНрди
- overload рд╕рд╛рдареА 429/503 +
Retry-AfterрдРрд╡рдЬреА 500 рдкрд░рдд рдХрд░рдгреЗ, рддреНрдпрд╛рдореБрд│реЗ clients рдирд╛ "рд╡реНрдпрд╕реНрдд" рдЖрдгрд┐ "рдмрд┐рдШрдбрд▓реЗрд▓реЗ" рдпрд╛рдВрддрд▓рд╛ рдлрд░рдХ рдХрд│рдд рдирд╛рд╣реА - рдЪреБрдХреАрдЪреЗ рдХрд╛рдо рдЯрд╛рдХреВрди рджреЗрдгреЗ тАФ analytics рдЪрд╛рд▓реВ рдЕрд╕рддрд╛рдирд╛ payments рдирд╛рдХрд╛рд░рд▓реЗ рдЬрд╛рдгреЗ
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд
Edge рд╡рд░ rate limiting тАФ рдкреНрд░рддреНрдпреЗрдХ client address рд╕рд╛рдареА token-bucket рдкрджреНрдзрддреАрдЪреА рдорд░реНрдпрд╛рджрд╛ рдЕрд╕рд▓реЗрд▓реЗ NGINX, рдорд░реНрдпрд╛рджрд╛ рдУрд▓рд╛рдВрдбрд▓реНрдпрд╛рд╡рд░ 429 рдЙрддреНрддрд░ рджреЗрддреЗ. On a real account:
limit_req_zone $binary_remote_addr zone=per_ip:10m rate=10r/s;
server {
location /api/ {
limit_req zone=per_ip burst=20 nodelay;
limit_req_status 429;
proxy_pass http://timetable;
}
}
Load shed рдХрд░рдгрд╛рд░реА service рдХреЗрд╡реНрд╣рд╛ рдкрд░рдд рдпрд╛рдпрдЪреЗ рддреЗ рд╕рд╛рдВрдЧрддреЗ:
HTTP/1.1 503 Service Unavailable
Retry-After: 5
Envoy circuit breaking тАФ рдкреНрд░рддреНрдпреЗрдХ upstream cluster рд╕рд╛рдареА connections, рдерд╛рдВрдмрд▓реЗрд▓реНрдпрд╛ requests, active requests рдЖрдгрд┐ active retries рд╡рд░ рдорд░реНрдпрд╛рджрд╛; рдорд░реНрдпрд╛рджреЗрдкрд▓реАрдХрдбреЗ Envoy request рд░рд╛рдВрдЧреЗрдд рдареЗрд╡рдгреНрдпрд╛рдРрд╡рдЬреА рд▓рдЧреЗрдЪ fail рдХрд░рддреЗ (defaults 1024, 1024, 1024 рдЖрдгрд┐ 3 рдЖрд╣реЗрдд):
clusters:
- name: timetable
circuit_breakers:
thresholds:
- priority: DEFAULT
max_connections: 200
max_pending_requests: 100 # the bounded queue
max_requests: 400
max_retries: 3
Code рдордзреНрдпреЗ backoff рдЖрдгрд┐ full jitter рд╕рд╣ retries:
import random, time
def call_with_retries(call, attempts=4, base=0.1, cap=5.0):
for n in range(attempts):
try:
return call()
except TemporaryError:
if n == attempts - 1: raise
time.sleep(random.uniform(0, min(cap, base * 2 ** n))) # full jitter
AWS SDKs рд╣реЗ рддреБрдордЪреНрдпрд╛рд╕рд╛рдареА рдХрд░рддрд╛рдд (AWS_RETRY_MODE=standard рдХрд┐рдВрд╡рд╛ adaptive); Kubernetes рдЪрд╛
API server API Priority and Fairness рдиреЗ load shed рдХрд░рддреЛ рдЖрдгрд┐ рдПрдЦрд╛рджреНрдпрд╛
priority level рдЪреНрдпрд╛ queues рднрд░рд▓реНрдпрд╛ рдХреА 429 рдЙрддреНрддрд░ рджреЗрддреЛ.
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: рдкреНрд░рддреНрдпреЗрдХ service рд╕рд╛рдареА рддрд┐рдЪреНрдпрд╛ рд░рд╛рдВрдЧреЗрдЪреНрдпрд╛ рдорд░реНрдпрд╛рджрд╛, рднрд░рд▓реНрдпрд╛рд╡рд░ рддреА рдХрд╛рдп рдкрд░рдд рдХрд░рддреЗ, рдХреЛрдгрддреЗ рдХрд╛рдо рддреА рдЖрдзреА рдЯрд╛рдХреВрди рджреЗрддреЗ, рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ caller рдЪреА retry policy рд▓рд┐рд╣реВрди рдареЗрд╡рд╛. рдордЧ рдХреНрд╖рдорддреЗрдкреЗрдХреНрд╖рд╛ рдЬрд╛рд╕реНрдд load-test рдХрд░рд╛ рдЖрдгрд┐ 429/503 рдЪреА рд╕рдВрдЦреНрдпрд╛ рд╡рд╛рдврдд рдЕрд╕рддрд╛рдирд╛ p99 рдерд╛рдВрдмрдгреЗ рд╕рдкрд╛рдЯ рд░рд╛рд╣рддреЗ рдХрд╛ рддреЗ рддрдкрд╛рд╕рд╛.
ЁЯОУ рд╢рд╛рдЦрд╛рдВрдЪреЗ рдПрдХрдордд рдЭрд╛рд▓реЗ
рдирд┐рд░реЛрдкреЗ рд╣рд░рд╡рддрд╛рдд, рдЖрдгрд┐ рд╢рд╛рдВрддрддреЗрддреВрди рдЬрд╡рд│рдЬрд╡рд│ рдХрд╛рд╣реАрдЪ рдХрд│рдд рдирд╛рд╣реА тЖТ рдкреНрд░рддреНрдпреЗрдХ рд╢рд╛рдЦреЗрдЪреЗ рдШрдбреНрдпрд╛рд│ рдереЛрдбреЗрд╕реЗ рдЪреБрдХреАрдЪреЗ рдЕрд╕рддреЗ, рдореНрд╣рдгреВрди counters рдХрд╛рд░рдгрд╛рд▓рд╛ рдкрд░рд┐рдгрд╛рдорд╛рдЪреНрдпрд╛ рдЖрдзреА рдХреНрд░рдо рджреЗрддрд╛рдд тЖТ vector clocks рдЦрд░рд╛ conflict рдЖрдгрд┐ рдЙрд╢реАрд░ рдпрд╛рдВрддрд▓рд╛ рдлрд░рдХ рдУрд│рдЦрддрд╛рдд тЖТ heartbeats рдлрдХреНрдд рд╕рдВрд╢рдп рдШреЗрдК рд╢рдХрддрд╛рдд тЖТ рдиреЛрдВрджрд╡рд╣реАрдЪреНрдпрд╛ рдкреНрд░рддреАрдВрдирд╛ рдЬреЗ рдорд┐рд│рд╛рд▓реЗрдЪ рдирд╡реНрд╣рддреЗ рддреЗ рд╣рд░рд╡рддреЗ тЖТ quorums рд╕рд░реНрд╡рд╛рдд рдирд╡реАрди рд╢реЛрдзрдгреНрдпрд╛рд╕рд╛рдареА рдПрдХрдореЗрдХрд╛рдВрд╡рд░ рдпреЗрддрд╛рдд тЖТ рдкреНрд░рддреНрдпреЗрдХ рд╡рд╛рдЪрдгрд╛рд▒реНрдпрд╛рд▓рд╛ рдирд╛рд╡ рдЕрд╕рд▓реЗрд▓реЗ рд╡рдЪрди рдорд┐рд│рддреЗ тЖТ рддреБрдЯрд▓реЗрд▓рд╛ рд░рд╕реНрддрд╛ "рдирдХрд╛рд░ рджреНрдпрд╛ рдХрд┐рдВрд╡рд╛ рдЬреБрдиреЗ рдЙрддреНрддрд░ рджреНрдпрд╛" рд╣реА рдирд┐рд╡рдб рд▓рд╛рджрддреЛ тЖТ рдмрд╣реБрдордд рдкреНрд░рддреНрдпреЗрдХ term рдордзреНрдпреЗ рдПрдХ leader рдирд┐рд╡рдбрддреЗ тЖТ lease рд▓рд╛ fencing token рд▓рд╛рдЧрддреЛ тЖТ at-least-once рдЕрдзрд┐рдХ key рдореНрд╣рдгрдЬреЗ effectively once тЖТ рдЖрдгрд┐ bounded рд░рд╛рдВрдЧ рд▓рд╡рдХрд░ "рдирдВрддрд░ рдпрд╛" рд╕рд╛рдВрдЧрддреЗ. рддреБрдореНрд╣реА рдлрдХреНрдд distributed systems рд╢рд┐рдХрд▓рд╛ рдирд╛рд╣реАрдд тАФ рддреБрдореНрд╣реА рджреЛрди boxes рдордзрд▓рд╛ рдХреЛрдгрддрд╛рд╣реА рдмрд╛рдг рдкрд╛рд╣реВрди рдпреЛрдЧреНрдп рдкреНрд░рд╢реНрди рд╡рд┐рдЪрд╛рд░реВ рд╢рдХрддрд╛: рд╣реА рдЪрд┐рдареНрдареА рд╣рд░рд╡рд▓реА, рдЙрд╢рд┐рд░рд╛ рдЖрд▓реА, рдкреБрдиреНрд╣рд╛ рдЖрд▓реА, рдХрд┐рдВрд╡рд╛ рд░рд╕реНрддрд╛ рддреБрдЯрд▓рд╛ рддрд░ рдХрд╛рдп? ЁЯМРЁЯССЁЯОУ
тПня╕П рдкреБрдвреЗ
рдЗрддрд░ рд╢рд╛рд│рд╛. System Design рд╢рд╛рд│рд╛ рд╣реЗ рд╕рдЧрд│реЗ рдЦрд▒реНрдпрд╛ designs рдордзреНрдпреЗ рд╡рд╛рдкрд░рддреЗ; Scaling рд╢рд╛рд│рд╛ traffic рд╣рд╛рддрд╛рд│рддреЗ; Database рд╢рд╛рд│рд╛ рдиреЛрдВрджрд╡рд╣реАрдд рдЖрдгрдЦреА рдЦреЛрд▓рд╡рд░ рдЬрд╛рддреЗ; Kubernetes рд╢рд╛рд│рд╛ etcd рдЖрдгрд┐ leases рд╡рд░ рдЪрд╛рд▓рддреЗ; School portal рдордзреНрдпреЗ рдмрд╛рдХреА рд╕рдЧрд│реЗ рдЖрд╣реЗ.
git checkout main
python3 dist/demo.py # one last run, for fun