Rate Limit, Bulkhead

μž₯μ• κ°€ λ°œμƒν•˜κΈ° μ „, μ‹œμŠ€ν…œμ΄ 감당할 수 μžˆλŠ” μˆ˜μ€€μœΌλ‘œ λΆ€ν•˜λ₯Ό μ œμ–΄ν•˜μ—¬ μž₯μ• λ₯Ό μ˜ˆλ°©ν•˜λŠ” 두 κ°€μ§€ 핡심 기술이 μ‘΄μž¬ν•©λ‹ˆλ‹€. Rate Limit, Bulkhead은 ν˜ΈμΆœλŸ‰μ„ μ œν•œν•˜μ—¬ μ‹œμŠ€ν…œ μžμ›μ΄ κ³Όλ„ν•œ λΆ€ν•˜λ₯Ό λ°›μ§€ μ•Šλ„λ‘ λ³΄ν˜Έν•œλ‹€λŠ” 곡톡점이 μžˆμ§€λ§Œ, μ œν•œ λ°©μ‹μ—μ„œμ˜ 차이가 μ‘΄μž¬ν•©λ‹ˆλ‹€.

Rate Limit

Rate LimiterλŠ” 이름 κ·ΈλŒ€λ‘œ μ‹€ν–‰ 횟수λ₯Ό μ œν•œν•˜λŠ” κΈ°μˆ μž…λ‹ˆλ‹€.

μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ Rate Limit은 크게 두 곳에 μ μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

  • μš”μ²­μ΄ λ“€μ–΄μ˜€λŠ” κ³³ (Inbound)

    • κ°€μž₯ 많이 λ³Ό 수 μžˆλŠ” μΌ€μ΄μŠ€μž…λ‹ˆλ‹€.

    • νŠΉμ • μ‚¬μš©μžλ‚˜ API Keyλ₯Ό κΈ°μ€€μœΌλ‘œ μš”μ²­ 횟수λ₯Ό μ œν•œν•˜μ—¬, νŠΉμ • μ‚¬μš©μžκ°€ μ‹œμŠ€ν…œ λ¦¬μ†ŒμŠ€λ₯Ό λ…μ ν•˜κ±°λ‚˜ κ³Όλ„ν•œ λΉ„μš©μ„ μœ λ°œν•˜λŠ” 것을 λ°©μ§€ν•©λ‹ˆλ‹€.

  • μš”μ²­μ΄ λ‚˜κ°€λŠ” κ³³ (Outbound)

    • μš”μ²­μ„ λ°›λŠ” λŒ€μƒ μ„œλΉ„μŠ€λ‘œ κ³Όλ„ν•œ νŠΈλž˜ν”½μ΄ λ‚˜κ°€μ§€ μ•Šλ„λ‘ μ œν•œν•©λ‹ˆλ‹€.

    • κ΅¬μΆ•ν•œ μ„œλ²„κ°€ μ™ΈλΆ€ μ„œλΉ„μŠ€(타사 API λ“±)λ₯Ό ν˜ΈμΆœν•  λ•Œ μ μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

    • 타 μ„œλΉ„μŠ€μ˜ μ‹œμŠ€ν…œμ΄ 감당할 수 없을 만큼 κ³Όλ„ν•œ νŠΈλž˜ν”½μ„ 보내지 μ•Šλ„λ‘ λ³΄ν˜Έν•˜λŠ” 역할을 μˆ˜ν–‰ν•©λ‹ˆλ‹€.

[μ˜ˆμ‹œ: 둜그 μ‹œμŠ€ν…œ λ³΄ν˜Έν•˜κΈ°]

  • Rate LimiterλŠ” API 호좜뿐만 μ•„λ‹ˆλΌ μ—λŸ¬ 둜그 μ²˜λ¦¬μ—λ„ μœ μš©ν•©λ‹ˆλ‹€.

  • μ‹œμŠ€ν…œμ— μž₯μ• κ°€ ν„°μ§€λ©΄ μ—λŸ¬ λ‘œκ·Έκ°€ 폭발적으둜 λ°œμƒν•˜μ—¬ Slack 채널이 λ§ˆλΉ„λ˜κ±°λ‚˜ 둜그 μ„œλ²„(ELK λ“±)κ°€ 뻗어버릴 수 μžˆμŠ΅λ‹ˆλ‹€.

  • μ΄λ•Œ 둜그 전솑 λ‘œμ§μ— Rate Limit을 걸어두면, ν‰μ†Œμ—λŠ” 잘 보내닀가 μž₯μ•  μ‹œμ—λŠ” 둜그λ₯Ό μ°¨λ‹¨ν•˜κ±°λ‚˜ μš”μ•½ν•΄μ„œ λ³΄λƒ„μœΌλ‘œμ¨ 2μ°¨ ν”Όν•΄λ₯Ό 막을 수 μžˆμŠ΅λ‹ˆλ‹€.

resilience4j도 Rate Limit κΈ°λŠ₯을 μ œκ³΅ν•˜λŠ” 데, μ„œν‚·μ— λΉ„ν•΄μ„œ κΈ°λŠ₯이 쑰금 λ―Έμ•½ν•©λ‹ˆλ‹€.

Bulkhead

λ²Œν¬ν—€λ“œλŠ” β€˜κ²©λ²½β€™μ΄λΌλŠ” 의미인데, μ„ λ°• λ‚΄λΆ€λ₯Ό μ—¬λŸ¬ 격벽으둜 λ‚˜λˆ„μ–΄, ν•œ 곳에 ꡬ멍이 λ‚˜λ„ λ°° 전체가 μΉ¨λͺ°ν•˜μ§€ μ•Šκ²Œ ν•˜λŠ” κ²ƒμ—μ„œ μœ λž˜ν–ˆμŠ΅λ‹ˆλ‹€.

SWμ—μ„œλŠ” λ™μ‹œμ— μ§„μž…ν•  수 μžˆλŠ” 수λ₯Ό μ œν•œν•˜λŠ” λ°©μ‹μœΌλ‘œ κ΅¬ν˜„λ©λ‹ˆλ‹€. κ·Έλž˜μ„œ λ²Œν¬ν—€λ“œκ°€ 적용된 μ˜μ—­μ—λŠ” λ™μ‹œμ— μ§„μž…ν•  수 μžˆλŠ” μŠ€λ ˆλ“œμ˜ 수λ₯Ό μ œν•œν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λΉ„μŠ·ν•œ κ°œλ…μœΌλ‘œλŠ” synchronized ν‚€μ›Œλ“œλ‘œ 동기화λ₯Ό ν•˜λŠ” 것도 λ™μ‹œμ— ν•˜λ‚˜μ˜ νλ¦„λ§Œ 블둝에 μ§„μž…ν•˜λ„λ‘ μ œν•œν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. μ΄λŠ” 방식 μžμ²΄λŠ” κ°™μ§€λ§Œ λͺ©μ  μžμ²΄κ°€ λ‹€λ¦…λ‹ˆλ‹€.

λ²Œν¬ν—€λ“œλŠ” 동기화가 λͺ©μ μ΄ μ•„λ‹ˆλΌ, λ³΄ν˜Έν•˜λ €λŠ” λŒ€μƒμ˜ λ¦¬μ†ŒμŠ€κ°€ κ³Όλ„ν•˜κ²Œ μ‚¬μš©λ˜λŠ” 것을 λ§‰λŠ”κ²ƒμž…λ‹ˆλ‹€.

μŠ€λ ˆλ“œ ν’€, 컀λ„₯μ…˜ 풀이 λ²Œν¬ν—€λ“œμ™€ μ™„μ „νžˆ λ™μΌν•œ κ°œλ…μœΌλ‘œλ„ λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

  • λ„ˆλ¬΄ λ§Žμ€ μš”μ²­μ΄ λ™μ‹œμ— μ²˜λ¦¬λ˜μ§€ μ•Šλ„λ‘ μ œν•œν•˜λŠ” μ—­ν• 

  • λ„ˆλ¬΄ λ§Žμ€ μš”μ²­μ„ λ™μ‹œμ— μ²˜λ¦¬ν•˜λ©΄ μ»¨ν…μŠ€νŠΈ μŠ€μœ„μΉ­κ°™μ€ μ˜€λ²„ν—€λ“œ λ•Œλ¬Έμ— 였히렀 전체 μ„±λŠ₯이 μ €ν•˜λ  수 μžˆμ–΄μ„œ μ œν•œμ„ ν•˜λŠ” 것이닀.

[λ™μž‘ 원리]

  • λ¦¬μ†ŒμŠ€ 격리:

    • 동기화(synchronized)와 λΉ„μŠ·ν•˜μ§€λ§Œ λͺ©μ μ΄ λ‹€λ¦…λ‹ˆλ‹€.

    • λ™κΈ°ν™”λŠ” 데이터 정합성이 λͺ©μ μ΄λΌλ©΄,

    • BulkheadλŠ” νŠΉμ • κΈ°λŠ₯이 전체 λ¦¬μ†ŒμŠ€(예: μŠ€λ ˆλ“œ/컀λ„₯μ…˜ ν’€ λ“±)λ₯Ό κ³ κ°ˆμ‹œν‚€λŠ” 것을 λ§‰λŠ” 것이 λͺ©μ μž…λ‹ˆλ‹€.

  • μ˜ˆμ‹œ:

    • 이미 μ‚¬μš©ν•˜κ³  μžˆλŠ” DBCP(Database Connection Pool)μ΄λ‚˜ ν†°μΊ£μ˜ μŠ€λ ˆλ“œ 풀이 ν•΄λ‹Ή νŒ¨ν„΄μ˜ μΌμ’…μž…λ‹ˆλ‹€.

  • 효과:

    • λ„ˆλ¬΄ λ§Žμ€ μš”μ²­μ„ λ™μ‹œμ— μ²˜λ¦¬ν•˜λ©΄ μ»¨ν…μŠ€νŠΈ μŠ€μœ„μΉ­ λΉ„μš© λ•Œλ¬Έμ— 였히렀 μ„±λŠ₯이 μ €ν•˜λ  수 μžˆμŠ΅λ‹ˆλ‹€.

    • BulkheadλŠ” 이λ₯Ό 적절히 μ œν•œν•˜μ—¬ 전체 μ‹œμŠ€ν…œμ˜ μ²˜λ¦¬λŸ‰μ„ μœ μ§€ν•©λ‹ˆλ‹€.

Resilience4j

Resilien4j κΈ°μ€€μ—μ„œ Rate Limit, Bulkhead λͺ¨λ‘ μ œν•œλ˜λŠ” μ˜μ—­μ€ 기본적으둜 λ©”μ„œλ“œ λ‹¨μœ„μž…λ‹ˆλ‹€.

  • Circuit: 높은 λΆ€ν•˜λ₯Ό λ°›λŠ” 경우(μ˜ˆμ™Έ, 느린 응닡) μΌμ‹œμ μœΌλ‘œ νŠΈλž˜ν”½ μ°¨λ‹¨ν•˜μ—¬ μ‹œμŠ€ν…œμ„ 회볡

  • Rate Limiter: 높은 λΆ€ν•˜λ₯Ό μ˜ˆλ°©ν•˜κΈ° μœ„ν•΄μ„œ μ‹œκ°„λ‹Ή μ‹€ν–‰ 횟수λ₯Ό μ œν•œ

  • Bulkhead: 높은 λΆ€ν•˜λ₯Ό μ˜ˆλ°©ν•˜κΈ° μœ„ν•΄, λ™μ‹œμ— μ²˜λ¦¬ν•  수 μžˆλŠ” μŠ€λ ˆλ“œ 수 μ œν•œ

λΆ„μ‚° ν™˜κ²½μ—μ„œ λ°œμƒν•  수 μžˆλŠ” 문제점과 λŒ€μ•ˆ

단일 μ„œλ²„μ—μ„œλŠ” λ©”λͺ¨λ¦¬ λ‚΄μ—μ„œ ν•΄κ²°ν•˜λ©΄ λ˜μ§€λ§Œ, μ„œλ²„κ°€ μ—¬λŸ¬ λŒ€μΈ λΆ„μ‚° ν™˜κ²½μ—μ„œλŠ” 고민이 ν•„μš”ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Rate Limiterλ‚˜ Bulkhead의 μƒνƒœλ₯Ό μ„œλ²„λΌλ¦¬ κ³΅μœ ν•˜λ €λ©΄ 보톡 Redis 같은 μ™ΈλΆ€ μ €μž₯μ†Œλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€. ν•˜μ§€λ§Œ κ·Έλƒ₯ μ‚¬μš©ν•˜κ²Œ λœλ‹€λ©΄ 이후에 큰 λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.

[문제 상황: μƒνƒœ 관리λ₯Ό ν•˜λŠ” Redisκ°€ 죽으면?]

μ΄λ•Œ 선택할 수 μžˆλŠ” 3κ°€μ§€ λ°©μ•ˆμ΄ μžˆμŠ΅λ‹ˆλ‹€.

μ •ν•΄μ§„ 것은 μ—†μœΌλ©° λΉ„μ¦ˆλ‹ˆμŠ€ ν˜Ήμ€ μ„œλΉ„μŠ€ κ·œμΉ™μ— 맞좰 μ μ ˆν•˜κ²Œ 선택해야 ν•©λ‹ˆλ‹€.

  1. Fail Open (λͺ¨λ‘ ν—ˆμš©)

    • Redisκ°€ 죽으면 μ œν•œμ„ ν’€κ³  λͺ¨λ“  μš”μ²­μ„ λ°›μŠ΅λ‹ˆλ‹€.

    • μ‹œμŠ€ν…œμ˜ κ°€μš©μ„±μ΄ μ€‘μš”ν•œ 경우 선택할 수 μžˆμ§€λ§Œ, μ‹œμŠ€ν…œ κ³ΌλΆ€ν•˜ μœ„ν—˜λ„ μ‘΄μž¬ν•©λ‹ˆλ‹€.

  2. Fail Closed (λͺ¨λ‘ 차단)

    • Redisκ°€ 죽으면 λͺ¨λ“  μš”μ²­μ„ κ±°λΆ€ν•©λ‹ˆλ‹€.

    • μ‹œμŠ€ν…œμ„ λ³΄ν˜Έν•˜λŠ” 것에 μ§‘μ€‘ν•˜μ§€λ§Œ, μ„œλΉ„μŠ€ 쀑단이 λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.

  3. Local Fallback (μΈμŠ€ν„΄μŠ€λ³„λ‘œ μ„€μ •)

    • Redisκ°€ 죽으면, 각 μ„œλ²„μ˜ 둜컬 λ©”λͺ¨λ¦¬λ₯Ό κΈ°μ€€μœΌλ‘œ μ œν•œν•©λ‹ˆλ‹€.

    • κ°€μž₯ ν˜„λͺ…ν•œ λŒ€μ•ˆμ΄λΌκ³  μƒκ°λ˜μ§€λ§Œ, μ‚¬μš©μž μž…μž₯μ—μ„œ 일관성 μ—†λŠ” κ²½ν—˜μ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Summary

Rate Limiter와 BulkheadλŠ” μ‹œμŠ€ν…œμ΄ 감당할 수 μžˆλŠ” λ°λ“œλΌμΈμ„ μ„€μ •ν•˜λŠ” 것과 κ°™μŠ΅λ‹ˆλ‹€.

  • Rate Limiter둜 μš”μ²­ λΉˆλ„λ₯Ό μ œμ–΄ν•˜κ³ 

  • Bulkhead둜 μžμ›μ„ κ²©λ¦¬ν•˜κ³ 

  • λ¬Έμ œκ°€ λ°œμƒν•˜λ©΄ μ„œν‚·μœΌλ‘œ 연결을 차단할 수 μžˆμŠ΅λ‹ˆλ‹€.

μ„Έ κ°€μ§€ 방식이 μ‘°ν™”λ‘­κ²Œ μ μš©λ˜μ—ˆμ„ λ•Œ, κ°‘μž‘μŠ€λŸ¬μš΄ νŠΈλž˜ν”½μ—μ„œλ„ κ²¬κ³ ν•œ μ‹œμŠ€ν…œμ„ ꡬ좕할 수 μžˆμ„ κ²ƒμž…λ‹ˆλ‹€.

Last updated