Skip to content

Latest commit

ย 

History

History
503 lines (336 loc) ยท 15.2 KB

File metadata and controls

503 lines (336 loc) ยท 15.2 KB

Task Dispatcher Study Guide

์ด ๋ฌธ์„œ๋Š” ์ด ์ €์žฅ์†Œ๋ฅผ ์ฒ˜์Œ ๋ณด๋Š” ์‚ฌ๋žŒ์ด ์ฝ”๋“œ ํ๋ฆ„, Redis ์‚ฌ์šฉ ๋ฐฉ์‹, Producer/Worker ๊ตฌ์กฐ๋ฅผ ๋น ๋ฅด๊ฒŒ ์ดํ•ดํ•˜๋„๋ก ๋•๊ธฐ ์œ„ํ•œ ํ•™์Šต์šฉ ๊ฐ€์ด๋“œ๋‹ค.

1. ์ด ํ”„๋กœ์ ํŠธ๊ฐ€ ํ•˜๋Š” ์ผ

์ด ํ”„๋กœ์ ํŠธ๋Š” ์•„์ฃผ ์ „ํ˜•์ ์ธ Producer -> Queue -> Worker ๊ตฌ์กฐ๋ฅผ ๊ตฌํ˜„ํ•œ ์˜ˆ์ œ๋‹ค.

๊ตฌ์„ฑ์€ ๋‹จ์ˆœํ•˜๋‹ค.

  • ํด๋ผ์ด์–ธํŠธ๊ฐ€ API์— ์ž‘์—…์„ ์š”์ฒญํ•œ๋‹ค.
  • API๋Š” ์ž‘์—… ๋‚ด์šฉ์„ Redis์— ์ €์žฅํ•˜๊ณ  ํ์— ๋„ฃ๋Š”๋‹ค.
  • Worker๊ฐ€ ํ์—์„œ ์ž‘์—…์„ ๊บผ๋‚ด ์ฒ˜๋ฆฌํ•œ๋‹ค.
  • ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋‹ค์‹œ Redis์— ๊ธฐ๋กํ•œ๋‹ค.
  • API๋Š” ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋‹ค๋ ธ๋‹ค๊ฐ€ ์ตœ์ข… ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

์ฆ‰, ๊ฒ‰์œผ๋กœ๋Š” HTTP API์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ, ๋‚ด๋ถ€์—์„œ๋Š” Redis๊ฐ€ ์ž‘์—… ์ค‘๊ฐœ์ž ์—ญํ• ์„ ํ•œ๋‹ค.

2. ํฐ ๊ทธ๋ฆผ

Client
  |
  | HTTP POST /jobs
  v
FastAPI app/api.py
  |
  | Redis์— job ์ €์žฅ + queue์— job_id push
  v
Redis
  |
  | worker๊ฐ€ BLPOP์œผ๋กœ ๋Œ€๊ธฐ
  v
Worker app/worker_demo.py
  |
  | ์ž‘์—… ์ฒ˜๋ฆฌ ํ›„ result/reply ์ €์žฅ
  v
Redis
  |
  | API๊ฐ€ reply๋ฅผ BLPOP์œผ๋กœ ๊ธฐ๋‹ค๋ฆผ
  v
FastAPI response

ํ•ต์‹ฌ ํฌ์ธํŠธ๋Š” ์ž‘์—… ๋ณธ๋ฌธ ์ „์ฒด๋ฅผ ํ์— ๋„ฃ์ง€ ์•Š๊ณ  job_id๋งŒ ํ์— ๋„ฃ๋Š”๋‹ค๋Š” ์ ์ด๋‹ค. ์‹ค์ œ payload๋Š” ๋ณ„๋„ key์— ์ €์žฅํ•œ๋‹ค.

3. ํŒŒ์ผ๋ณ„ ์—ญํ• 

  • app/config.py: Redis ์ ‘์† ์ •๋ณด, key ์ด๋ฆ„, TTL, ํƒ€์ž„์•„์›ƒ ์—ฌ์œ  ์‹œ๊ฐ„์„ ๋ชจ์•„๋‘” ์„ค์ • ํŒŒ์ผ
  • app/api.py: FastAPI ์„œ๋ฒ„. ์ž‘์—… ๋“ฑ๋ก, ์ƒํƒœ ์กฐํšŒ, ๊ฒฐ๊ณผ ์กฐํšŒ, health/stats ์ œ๊ณต
  • app/worker_demo.py: Redis ํ๋ฅผ ์†Œ๋น„ํ•˜๋Š” Worker ํ”„๋กœ์„ธ์Šค
  • app/producer_demo.py: ๋กœ์ปฌ์—์„œ ๋™์ž‘ ํ™•์ธํ•  ๋•Œ ์“ฐ๋Š” CLI Producer
  • docker-compose.yml: Redis, API, Worker, Locust๋ฅผ ํ•œ ๋ฒˆ์— ๋„์šฐ๋Š” ์‹คํ–‰ ๊ตฌ์„ฑ

4. Redis ํ‚ค ์„ค๊ณ„

app/config.py์—์„œ ์•„๋ž˜ key๋“ค์„ ์ •์˜ํ•œ๋‹ค.

  • demo:queue
  • demo:job:<job_id>
  • demo:status:<job_id>
  • demo:result:<job_id>
  • demo:reply:<job_id>

๊ฐ ์—ญํ• ์€ ์ด๋ ‡๋‹ค.

  • queue: ์ฒ˜๋ฆฌ ๋Œ€๊ธฐ์—ด
  • job: ์‹ค์ œ ์ž‘์—… payload ์ €์žฅ
  • status: ํ˜„์žฌ ์ƒํƒœ ์ถ”์ 
  • result: ์ตœ์ข… ๊ฒฐ๊ณผ ์ €์žฅ
  • reply: API๊ฐ€ ์ฆ‰์‹œ ์‘๋‹ต๋ฐ›๊ธฐ ์œ„ํ•œ 1ํšŒ์„ฑ ์‘๋‹ต ์ฑ„๋„

์ด ๊ตฌ์กฐ๊ฐ€ ์ข‹์€ ์ด์œ ๋Š” ์—ญํ• ์ด ๋ถ„๋ฆฌ๋ผ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

  • ํ๋Š” ์ˆœ์„œ ๋ณด์žฅ์— ์ง‘์ค‘
  • job key๋Š” payload ๋ณด๊ด€์— ์ง‘์ค‘
  • status key๋Š” ๋ชจ๋‹ˆํ„ฐ๋ง์— ์ง‘์ค‘
  • result/reply key๋Š” ์‘๋‹ต ์ „๋‹ฌ์— ์ง‘์ค‘

5. ์™œ job_id๋งŒ ํ์— ๋„ฃ์„๊นŒ

์ดˆ๋ณด์ž๊ฐ€ ์ œ์ผ ๋จผ์ € ๋ด์•ผ ํ•  ์„ค๊ณ„ ํฌ์ธํŠธ๋‹ค.

ํ์— ์ „์ฒด JSON payload๋ฅผ ๋„ฃ๋Š” ๋ฐฉ์‹๋„ ๊ฐ€๋Šฅํ•˜๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ด ํ”„๋กœ์ ํŠธ๋Š” ๊ทธ๋ ‡๊ฒŒ ํ•˜์ง€ ์•Š๋Š”๋‹ค.

๋Œ€์‹  ๋‹ค์Œ ์ˆœ์„œ๋ฅผ ์“ด๋‹ค.

  1. job_id ์ƒ์„ฑ
  2. demo:job:<job_id>์— payload ์ €์žฅ
  3. demo:queue์— job_id๋งŒ push

์ด ๋ฐฉ์‹์˜ ์žฅ์ :

  • payload์™€ queue๋ฅผ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค
  • ์ƒํƒœ ์กฐํšŒ ์‹œ job_id ๊ธฐ์ค€์œผ๋กœ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ๊ธฐ ์‰ฝ๋‹ค
  • ๊ฒฐ๊ณผ, ์ƒํƒœ, ์—๋Ÿฌ๋ฅผ ๊ฐ™์€ job_id ์ถ•์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค
  • ํ ๋ฉ”์‹œ์ง€๋ฅผ ๊ฐ€๋ณ๊ฒŒ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค

6. API๊ฐ€ ํ•˜๋Š” ์ผ

app/api.py์—์„œ ์ œ์ผ ์ค‘์š”ํ•œ ์—”๋“œํฌ์ธํŠธ๋Š” POST /jobs๋‹ค.

ํ๋ฆ„์€ ๊ฑฐ์˜ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  1. ์š”์ฒญ๊ฐ’์„ ๊ฒ€์ฆํ•œ๋‹ค.
  2. job_id๋ฅผ ๋งŒ๋“ ๋‹ค.
  3. payload๋ฅผ demo:job:<id>์— ์ €์žฅํ•œ๋‹ค.
  4. ์ƒํƒœ๋ฅผ waiting์œผ๋กœ ๊ธฐ๋กํ•œ๋‹ค.
  5. ํ์— job_id๋ฅผ ๋„ฃ๋Š”๋‹ค.
  6. demo:reply:<id>๋ฅผ BLPOP์œผ๋กœ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.
  7. Worker ๊ฒฐ๊ณผ๊ฐ€ ์˜ค๋ฉด ์„ฑ๊ณต/์‹คํŒจ ์‘๋‹ต์œผ๋กœ ๋ฐ”๊ฟ”์„œ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ์ ์€ API๊ฐ€ ๋น„๋™๊ธฐ ์ž‘์—…์„ ๋“ฑ๋ก๋งŒ ํ•˜๊ณ  ๋๋‚ด๋Š” ๊ตฌ์กฐ๊ฐ€ ์•„๋‹ˆ๋ผ๋Š” ์ ์ด๋‹ค. ์ด ํ”„๋กœ์ ํŠธ๋Š” ์ž‘์—… ๋“ฑ๋ก ํ›„ ๊ณง๋ฐ”๋กœ ๊ฒฐ๊ณผ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.

์ฆ‰:

  • ๋‚ด๋ถ€ ๊ตฌ์กฐ๋Š” ๋น„๋™๊ธฐ ๋ถ„์‚ฐ ์ฒ˜๋ฆฌ
  • ์™ธ๋ถ€ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์€ ๋™๊ธฐ ์‘๋‹ต

์ด ํŒจํ„ด์€ "์ž‘์—… ์ฒ˜๋ฆฌ๋Š” ์›Œ์ปค์—๊ฒŒ ๋งก๊ธฐ๊ณ  ์‹ถ์ง€๋งŒ, ํด๋ผ์ด์–ธํŠธ๋Š” ์ตœ์ข… ์„ฑ๊ณต/์‹คํŒจ๋ฅผ ๋ฐ”๋กœ ๋ฐ›๊ณ  ์‹ถ๋‹ค"๋Š” ์š”๊ตฌ์— ๋งž๋Š”๋‹ค.

7. BLPOP์ด ํ•ต์‹ฌ์ธ ์ด์œ 

์ด ์ €์žฅ์†Œ๋ฅผ ์ดํ•ดํ•˜๋ ค๋ฉด BLPOP์„ ์•Œ์•„์•ผ ํ•œ๋‹ค.

BLPOP์€ Redis List์—์„œ ๊ฐ’์„ ๊บผ๋‚ด๋˜, ๊ฐ’์ด ์—†์œผ๋ฉด ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋ช…๋ น์ด๋‹ค.

์ด ํ”„๋กœ์ ํŠธ๋Š” ๋‘ ๊ณณ์—์„œ BLPOP์„ ์“ด๋‹ค.

  • Worker: demo:queue๋ฅผ ๊ธฐ๋‹ค๋ฆผ
  • API: demo:reply:<job_id>๋ฅผ ๊ธฐ๋‹ค๋ฆผ

์ฆ‰ ์–‘์ชฝ ๋‹ค ํด๋งํ•˜์ง€ ์•Š๋Š”๋‹ค. Redis๊ฐ€ ๊ฐ’์ด ๋“ค์–ด์˜ฌ ๋•Œ๊นŒ์ง€ block ์ƒํƒœ๋กœ ๋Œ€๊ธฐํ•œ๋‹ค.

์žฅ์ :

  • ๋ถˆํ•„์š”ํ•œ while polling์ด ์ค„์–ด๋“ ๋‹ค
  • ๊ตฌํ˜„์ด ๋‹จ์ˆœํ•˜๋‹ค
  • ์‘๋‹ต ๋Œ€๊ธฐ ๋ชจ๋ธ์„ ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๋‹ค

8. Worker๊ฐ€ ํ•˜๋Š” ์ผ

app/worker_demo.py์˜ ํ•ต์‹ฌ์€ main()๊ณผ _process_job()์ด๋‹ค.

Worker ๋ฃจํ”„๋Š” ์•„๋ž˜์ฒ˜๋Ÿผ ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.

while True:
    job_id = BLPOP(queue)
    process(job_id)

์‹ค์ œ ์ฒ˜๋ฆฌ ์ˆœ์„œ๋Š” ์ด๋ ‡๋‹ค.

  1. ํ์—์„œ job_id๋ฅผ ๋ฐ›๋Š”๋‹ค.
  2. demo:job:<id>์—์„œ payload๋ฅผ ์ฝ๋Š”๋‹ค.
  3. ์ƒํƒœ๋ฅผ running์œผ๋กœ ๋ฐ”๊พผ๋‹ค.
  4. work_s๋งŒํผ sleep ํ•˜๋ฉฐ ์ž‘์—…์„ ํ‰๋‚ด ๋‚ธ๋‹ค.
  5. ์„ฑ๊ณต ๋˜๋Š” ์‹คํŒจ ๊ฒฐ๊ณผ๋ฅผ ๋งŒ๋“ ๋‹ค.
  6. result key์™€ reply key์— ๊ธฐ๋กํ•œ๋‹ค.
  7. ์ƒํƒœ๋ฅผ finish ๋˜๋Š” fail๋กœ ๋ฐ”๊พผ๋‹ค.

์ด ํ”„๋กœ์ ํŠธ์˜ Worker๋Š” ์‹ค์ œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๋Œ€์‹  sleep์œผ๋กœ ์ž‘์—… ์‹œ๊ฐ„์„ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ์•„ํ‚คํ…์ฒ˜๋ฅผ ๊ณต๋ถ€ํ•˜๊ธฐ์— ์ข‹๋‹ค. ๋ณต์žกํ•œ ๋„๋ฉ”์ธ ๋กœ์ง ์—†์ด ํ ํ๋ฆ„์—๋งŒ ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

9. ์ƒํƒœ ์ถ”์ ์ด ์™œ ํ•„์š”ํ•œ๊ฐ€

status key๊ฐ€ ์—†์œผ๋ฉด ์ž‘์—…์ด ์ง€๊ธˆ ์–ด๋””๊นŒ์ง€ ๊ฐ”๋Š”์ง€ ์•Œ ์ˆ˜ ์—†๋‹ค.

์ด ํ”„๋กœ์ ํŠธ๋Š” ์ƒํƒœ๋ฅผ ์ตœ์†Œํ•œ ๋‹ค์Œ ๊ฐ’์œผ๋กœ ๋‚˜๋ˆˆ๋‹ค.

  • waiting
  • running
  • finish
  • fail

์ด ๋•๋ถ„์— ๋‹ค์Œ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

  • API์—์„œ /jobs/{job_id}/status ์ œ๊ณต
  • ๋””๋ฒ„๊น…์ด ์‰ฌ์›€
  • Worker๊ฐ€ ๋ฉˆ์ท„๋Š”์ง€ ์ถ”์ • ๊ฐ€๋Šฅ
  • ์šด์˜ ์ค‘ ํ˜„์žฌ ๋ณ‘๋ชฉ์ด queue์ธ์ง€ worker ์ฒ˜๋ฆฌ์ธ์ง€ ๋ณด๊ธฐ ์‰ฌ์›€

10. ๊ฒฐ๊ณผ๋ฅผ ์™œ result์™€ reply๋กœ ๋‚˜๋ˆŒ๊นŒ

์ด๊ฒƒ๋„ ์ค‘์š”ํ•œ ์„ค๊ณ„ ํฌ์ธํŠธ๋‹ค.

๊ฒ‰๋ณด๊ธฐ์—๋Š” ๋‘˜ ๋‹ค ๊ฒฐ๊ณผ ์ €์žฅ์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ ๋ชฉ์ ์ด ๋‹ค๋ฅด๋‹ค.

  • result: ๋‚˜์ค‘์— ๋‹ค์‹œ ์กฐํšŒํ•˜๊ธฐ ์œ„ํ•œ ์ €์žฅ์†Œ
  • reply: ์ง€๊ธˆ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์š”์ฒญ์—๊ฒŒ ์ฆ‰์‹œ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•œ ์ฑ„๋„

์ฆ‰:

  • reply๋Š” ์‹ค์‹œ๊ฐ„ ์‘๋‹ต์šฉ
  • result๋Š” ์กฐํšŒ/๋ณด๊ด€์šฉ

๊ทธ๋ž˜์„œ API๋Š” ๋จผ์ € result๊ฐ€ ์ด๋ฏธ ์žˆ์œผ๋ฉด ์ฆ‰์‹œ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์—†์œผ๋ฉด reply๋ฅผ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.

11. ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์„ค๊ณ„

app/worker_demo.py์—์„œ ์ข‹์€ ๋ถ€๋ถ„์€ "์—๋Ÿฌ๊ฐ€ ๋‚˜๋„ API๋ฅผ ์˜์›ํžˆ ๊ธฐ๋‹ค๋ฆฌ๊ฒŒ ๋‘์ง€ ์•Š์œผ๋ ค๋Š” ์˜๋„"๊ฐ€ ๋ถ„๋ช…ํ•˜๋‹ค๋Š” ์ ์ด๋‹ค.

Worker ์ฒ˜๋ฆฌ ์ค‘ ์˜ˆ์™ธ๊ฐ€ ๋‚˜๋ฉด:

  • ์ƒํƒœ๋ฅผ fail๋กœ ๊ธฐ๋ก
  • ์‹คํŒจ ๊ฒฐ๊ณผ๋ฅผ result์— ์ €์žฅ
  • ์‹คํŒจ ๊ฒฐ๊ณผ๋ฅผ reply์—๋„ push

์ฆ‰, ์‹คํŒจํ•ด๋„ ๋ฐ˜๋“œ์‹œ ์‘๋‹ต ๊ฒฝ๋กœ๋ฅผ ๋‚จ๊ธด๋‹ค.

app/api.py๋„ ํƒ€์ž„์•„์›ƒ์„ ๋‘”๋‹ค.

  • timeout = work_s + JOB_TIMEOUT_GRACE_S

์˜๋ฏธ๋Š” ๊ฐ„๋‹จํ•˜๋‹ค.

  • ์ •์ƒ ์ž‘์—… ์‹œ๊ฐ„๋ณด๋‹ค ์กฐ๊ธˆ ๋” ๊ธฐ๋‹ค๋ฆฐ๋‹ค
  • ๊ทธ๋ž˜๋„ ์‘๋‹ต์ด ์—†์œผ๋ฉด worker crash ๋˜๋Š” hang์œผ๋กœ ๋ณด๊ณ  ์‹คํŒจ ์ฒ˜๋ฆฌํ•œ๋‹ค

์ด ์„ค๊ณ„ ๋•๋ถ„์— API ์š”์ฒญ์ด ๋ฌดํ•œ์ • ๋งค๋‹ฌ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค.

12. TTL์ด ์žˆ๋Š” ์ด์œ 

app/config.py์—๋Š” TTL์ด ์ •์˜๋ผ ์žˆ๋‹ค.

  • RESULT_TTL_S = 3600
  • REPLY_TTL_S = 600
  • STATUS_TTL_S = 3600

์™œ ํ•„์š”ํ• ๊นŒ.

  • ๊ฒฐ๊ณผ๊ฐ€ ์˜๊ตฌํžˆ ์Œ“์ด๋ฉด Redis ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๊ณ„์† ์ฆ๊ฐ€ํ•œ๋‹ค
  • reply key๋Š” ์ผํšŒ์„ฑ์ด๋ผ ์˜ค๋ž˜ ๋‚จ๊ธธ ์ด์œ ๊ฐ€ ์—†๋‹ค
  • status/result๋Š” ๋””๋ฒ„๊น…์„ ์œ„ํ•ด ์ผ์ • ์‹œ๊ฐ„๋งŒ ๋‚จ๊ธฐ๋ฉด ์ถฉ๋ถ„ํ•˜๋‹ค

์ฆ‰, ์ด ํ”„๋กœ์ ํŠธ๋Š” "๋ฐ๋ชจ์ง€๋งŒ ์šด์˜ ๊ฐ๊ฐ์ด ์กฐ๊ธˆ ๋“ค์–ด๊ฐ„ ์„ค๊ณ„"๋ผ๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.

13. producer_demo.py๋Š” ์™œ ์žˆ๋‚˜

app/producer_demo.py๋Š” API ์—†์ด๋„ ํ๋ฆ„์„ ํ™•์ธํ•ด๋ณด๋Š” ๋กœ์ปฌ CLI ๋„๊ตฌ๋‹ค.

ํ•™์Šต ๊ด€์ ์—์„œ๋Š” ์˜คํžˆ๋ ค ์ด ํŒŒ์ผ์ด Redis ํ๋ฆ„์„ ์ง์ ‘ ๋ณด๊ธฐ ์ข‹๋‹ค.

๋ณผ๋งŒํ•œ ํฌ์ธํŠธ:

  • ์ž‘์—… enqueue
  • outstanding ๊ฐœ์ˆ˜ ์ถ”์ 
  • queue length ์กฐํšŒ
  • Redis ๋ฉ”๋ชจ๋ฆฌ ํ†ต๊ณ„ ์ถœ๋ ฅ
  • reply key ๋Œ€๊ธฐ ํ›„ ๊ฒฐ๊ณผ ์ถœ๋ ฅ

์ฆ‰, ๋ธŒ๋ผ์šฐ์ €๋‚˜ HTTP ์—†์ด๋„ "ํ ์‹œ์Šคํ…œ์ด ์‹ค์ œ๋กœ ์–ด๋–ป๊ฒŒ ํ๋ฅด๋Š”์ง€" ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

14. Compose ๊ตฌ์กฐ๋Š” ์™œ ์ด๋ ‡๊ฒŒ ๋˜์–ด ์žˆ๋‚˜

docker-compose.yml์„ ๋ณด๋ฉด ์„œ๋น„์Šค๋Š” 5๊ฐœ๋‹ค.

  • redis
  • api
  • worker-1
  • worker-2
  • locust

ํ•ต์‹ฌ ํ•™์Šต ํฌ์ธํŠธ:

  • worker๋ฅผ 2๊ฐœ ๋„์›Œ์„œ ์ˆ˜ํ‰ ํ™•์žฅ ๊ฐœ๋…์„ ๋ณด์—ฌ์คŒ
  • API์™€ Worker๊ฐ€ ๊ฐ™์€ ์ด๋ฏธ์ง€๋ฅผ ์“ฐ๊ณ  command๋งŒ ๋‹ค๋ฅด๊ฒŒ ์ค„ ์ˆ˜ ์žˆ์Œ
  • Redis healthcheck๊ฐ€ ํ†ต๊ณผ๋œ ๋’ค ๋‹ค๋ฅธ ์„œ๋น„์Šค๊ฐ€ ๋œจ๋„๋ก ํ•จ

์ด๊ฑด ์‹ค๋ฌด์—์„œ๋„ ์ž์ฃผ ๋ณด๋Š” ํŒจํ„ด์ด๋‹ค. ๊ฐ™์€ ์ฝ”๋“œ๋ฒ ์ด์Šค์—์„œ ์—ญํ• ๋งŒ ๋‹ค๋ฅด๊ฒŒ ๋ฐฐ์น˜ํ•œ๋‹ค.

15. ์ด ํ”„๋กœ์ ํŠธ๋ฅผ ์ฝ๋Š” ์ถ”์ฒœ ์ˆœ์„œ

์ฒ˜์Œ๋ถ€ํ„ฐ ๋ฌธ์„œ ์ „์ฒด๋ฅผ ๋‹ค ์ฝ๊ธฐ๋ณด๋‹ค ์•„๋ž˜ ์ˆœ์„œ๊ฐ€ ๋‚ซ๋‹ค.

  1. app/config.py์—์„œ key ๊ตฌ์กฐ๋ฅผ ๋จผ์ € ๋ณธ๋‹ค.
  2. app/worker_demo.py์—์„œ queue ์†Œ๋น„ ํ๋ฆ„์„ ๋ณธ๋‹ค.
  3. app/api.py์—์„œ ์š”์ฒญ์ด ์–ด๋–ป๊ฒŒ queue๋กœ ์—ฐ๊ฒฐ๋˜๋Š”์ง€ ๋ณธ๋‹ค.
  4. docker-compose.yml์—์„œ ์„œ๋น„์Šค ๊ตฌ์„ฑ์„ ๋ณธ๋‹ค.
  5. ๋งˆ์ง€๋ง‰์— app/producer_demo.py๋ฅผ ๋ณด๊ณ  ๋ณด์กฐ ๋„๊ตฌ ์—ญํ• ์„ ์ดํ•ดํ•œ๋‹ค.

์ด ์ˆœ์„œ๊ฐ€ ์ข‹์€ ์ด์œ ๋Š” ์‹œ์Šคํ…œ์˜ ์ค‘์‹ฌ์ด UI๊ฐ€ ์•„๋‹ˆ๋ผ queue flow์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

16. ๊ณต๋ถ€ํ•  ๋•Œ ์ง์ ‘ ํ™•์ธํ•ด๋ณผ ์งˆ๋ฌธ

์•„๋ž˜ ์งˆ๋ฌธ์— ๋‹ตํ•ด๋ณด๋ฉด ๊ตฌ์กฐ๊ฐ€ ๋นจ๋ฆฌ ์žกํžŒ๋‹ค.

  • ์™œ queue์—๋Š” payload๊ฐ€ ์•„๋‹ˆ๋ผ job_id๋งŒ ๋„ฃ์—ˆ์„๊นŒ?
  • ์™œ result์™€ reply๋ฅผ ๋‘˜ ๋‹ค ๋งŒ๋“ค์—ˆ์„๊นŒ?
  • Worker๊ฐ€ ์ฃฝ์œผ๋ฉด API๋Š” ์–ด๋–ป๊ฒŒ ์‹คํŒจ๋ฅผ ํŒ๋‹จํ• ๊นŒ?
  • Worker ์ˆ˜๋ฅผ 1๊ฐœ์—์„œ 2๊ฐœ๋กœ ๋Š˜๋ฆฌ๋ฉด ์–ด๋–ค ์ ์ด ๋‹ฌ๋ผ์งˆ๊นŒ?
  • BLPOP ๋Œ€์‹  polling์œผ๋กœ ๊ตฌํ˜„ํ•˜๋ฉด ์–ด๋–ค ๋น„ํšจ์œจ์ด ์ƒ๊ธธ๊นŒ?
  • TTL์ด ์—†๋‹ค๋ฉด Redis์—๋Š” ์–ด๋–ค ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ๊นŒ?

17. ์ง์ ‘ ์‹คํ—˜ํ•ด๋ณผ ๊ฒƒ

ํ•™์Šต์€ ์ฝ”๋“œ๋ฅผ ์ฝ๋Š” ๊ฒƒ๋ณด๋‹ค ์กฐ๊ธˆ ๋งŒ์ ธ๋ณด๋Š” ์ชฝ์ด ๋น ๋ฅด๋‹ค.

์ถ”์ฒœ ์‹คํ—˜:

  1. Worker๋ฅผ 1๊ฐœ๋งŒ ๋„์šฐ๊ณ  ์—ฌ๋Ÿฌ ์š”์ฒญ์„ ๋ณด๋‚ด๋ณธ๋‹ค.
  2. Worker๋ฅผ 2๊ฐœ ๋„์šฐ๊ณ  ๊ฐ™์€ ์š”์ฒญ์„ ๋ณด๋‚ด๋ณธ๋‹ค.
  3. work_s=1, work_s=5, fail=true๋ฅผ ์„ž์–ด์„œ ์š”์ฒญํ•ด๋ณธ๋‹ค.
  4. ์ž‘์—… ์ค‘ Worker ํ”„๋กœ์„ธ์Šค๋ฅผ ์ฃฝ์˜€์„ ๋•Œ API ์‘๋‹ต์ด ์–ด๋–ป๊ฒŒ ๋ฐ”๋€Œ๋Š”์ง€ ๋ณธ๋‹ค.
  5. Redis key๋ฅผ ์ง์ ‘ ์กฐํšŒํ•ด๋ณด๋ฉฐ queue, job, status, result, reply์˜ ์ฐจ์ด๋ฅผ ๋ณธ๋‹ค.

18. ํ•œ ์ค„ ์š”์•ฝ

์ด ์ €์žฅ์†Œ๋Š” "Redis๋ฅผ ์ค‘๊ฐ„์— ๋‘” ์ž‘์—… ๋ถ„๋ฐฐ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ํ˜•ํƒœ๋กœ ๋ณด์—ฌ์ฃผ๋Š” ํ•™์Šต์šฉ ์˜ˆ์ œ"๋‹ค.

ํ•ต์‹ฌ๋งŒ ๋‚จ๊ธฐ๋ฉด ์ด ๋ฌธ์žฅ์ด๋‹ค.

API๋Š” ์ž‘์—…์„ ๋„ฃ๊ณ  ๊ธฐ๋‹ค๋ฆฌ๊ณ , Worker๋Š” ์ž‘์—…์„ ๊บผ๋‚ด ์ฒ˜๋ฆฌํ•˜๊ณ , Redis๋Š” ๋‘˜ ์‚ฌ์ด์˜ ์ƒํƒœ์™€ ๊ฒฐ๊ณผ๋ฅผ ์—ฐ๊ฒฐํ•œ๋‹ค.

19. ์ฒ˜์Œ ์„ค์น˜ํ•˜๊ณ  ์…‹์—…ํ•˜๋Š” ๋ฐฉ๋ฒ•

์ด ํ”„๋กœ์ ํŠธ๋ฅผ ์ฒ˜์Œ ์‹คํ–‰ํ•  ๋•Œ๋Š” Podman์˜ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ํ•œ ๋ฒˆ์— ๋ณด๋ ค ํ•˜์ง€ ์•Š๋Š” ํŽธ์ด ๋‚ซ๋‹ค.

์ถ”์ฒœ ์ˆœ์„œ๋Š” ์ด๋ ‡๋‹ค.

  1. ๋จผ์ € docker compose๋กœ ๊ตฌ์กฐ๋ฅผ ์ดํ•ดํ•œ๋‹ค.
  2. ๊ทธ๋‹ค์Œ podman compose๋กœ ๊ฐ™์€ ์Šคํƒ์„ ์‹คํ–‰ํ•ด๋ณธ๋‹ค.
  3. ๋งˆ์ง€๋ง‰์œผ๋กœ Quadlet + systemd๋ฅผ ๋ณธ๋‹ค.

์ด ์ˆœ์„œ๊ฐ€ ์ข‹์€ ์ด์œ ๋Š” ์•„ํ‚คํ…์ฒ˜ ํ•™์Šต๊ณผ Podman ์šด์˜ ๊ธฐ๋Šฅ ํ•™์Šต์„ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

20. ๊ฐ€์žฅ ์‰ฌ์šด ์‹œ์ž‘: Docker Compose

๋ฌธ์„œ์ƒ ์ด ํ”„๋กœ์ ํŠธ๋Š” docker-compose.yml์„ ๊ธฐ์ค€์œผ๋กœ ๋ฐ”๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

20.1 ์ค€๋น„

  • Git ์„ค์น˜
  • Docker Desktop ๋˜๋Š” Docker Engine ์„ค์น˜

20.2 ์ €์žฅ์†Œ ๋ฐ›๊ธฐ

git clone <your-repo-url>
cd task-dispatcher-demo
git switch develop

20.3 ์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰

docker compose up -d --build

20.4 ์ƒํƒœ ํ™•์ธ

docker compose ps
curl http://localhost:8000/health
curl http://localhost:8000/stats

20.5 ์ž‘์—… ์š”์ฒญ ํ…Œ์ŠคํŠธ

curl -X POST http://localhost:8000/jobs \
  -H "Content-Type: application/json" \
  -d '{"work_s": 3, "fail": false}'

20.6 ๋กœ๊ทธ ๋ณด๊ธฐ

docker compose logs -f api
docker compose logs -f worker-1
docker compose logs -f worker-2

20.7 ์ข…๋ฃŒ

docker compose down

์ฒ˜์Œ์—๋Š” ์ด ๋‹จ๊ณ„๋งŒ ํ•ด๋„ ์ถฉ๋ถ„ํ•˜๋‹ค. ์ด๊ฑธ๋กœ API -> Redis -> Worker -> ์‘๋‹ต ํ๋ฆ„์„ ๋ชจ๋‘ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

ํ…Œ์ŠคํŠธ ํ›„ ํ•œ ๋ฒˆ์— ์ •๋ฆฌํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์•„๋ž˜ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

bash scripts/teardown_all.sh

21. Podman์œผ๋กœ ์‹คํ–‰ํ•˜๊ธฐ

๋ฌธ์„œ ๊ธฐ์ค€์œผ๋กœ๋Š” podman compose๋„ ๋ฐ”๋กœ ์ง€์›ํ•œ๋‹ค.

21.1 ์ค€๋น„

  • Podman ์„ค์น˜

21.2 ์‹คํ–‰

podman compose up -d --build

21.3 ํ™•์ธ

podman compose ps
curl http://localhost:8000/health
curl http://localhost:8000/stats

21.4 ์ข…๋ฃŒ

podman compose down

ํ•™์Šต ๋ชฉ์ ์ด๋ผ๋ฉด docker compose์™€ podman compose์˜ ์ฐจ์ด๋ฅผ ํฌ๊ฒŒ ์˜์‹ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค. ๋‘˜ ๋‹ค ํ˜„์žฌ ์ €์žฅ์†Œ ๊ตฌ์กฐ๋ฅผ ์ดํ•ดํ•˜๋Š” ๋ฐ๋Š” ์ถฉ๋ถ„ํ•˜๋‹ค.

Podman Compose๋กœ ๋„์šด ๋’ค์—๋„ ๋™์ผํ•˜๊ฒŒ ์•„๋ž˜ ์Šคํฌ๋ฆฝํŠธ๋กœ ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

bash scripts/teardown_all.sh

22. ๋ฌธ์„œ๊ฐ€ ๊ถŒ์žฅํ•˜๋Š” Podman ์‹ฌํ™” ๋ฐฉ์‹: Podman Machine + Quadlet

README.md์—์„œ๋Š” Podman์˜ ์šด์˜ํ˜• ๊ด€๋ฆฌ ๋ฐฉ์‹์œผ๋กœ Quadlet + systemd๋ฅผ ์•ˆ๋‚ดํ•œ๋‹ค.

ํ•ต์‹ฌ์€ Docker ์ปจํ…Œ์ด๋„ˆ ์•ˆ์— Podman์„ ๋„ฃ๋Š” ๋ฐฉ์‹์ด ์•„๋‹ˆ๋ผ, Podman Machine ์•ˆ์œผ๋กœ ๋“ค์–ด๊ฐ€์„œ systemd๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ์‹์ด๋ผ๋Š” ์ ์ด๋‹ค.

22.1 Podman Machine ์ ‘์†

podman machine init
podman machine start
podman machine ssh

์ดํ›„ ๋ช…๋ น์€ podman machine ssh ์•ˆ์—์„œ ์‹คํ–‰ํ•œ๋‹ค.

22.2 systemd ๋””๋ ‰ํ† ๋ฆฌ ์ค€๋น„

mkdir -p ~/.config/containers/systemd/

22.3 Quadlet ๋„คํŠธ์›Œํฌ ๋ฐ ์„œ๋น„์Šค ํŒŒ์ผ ์ƒ์„ฑ

๋ฌธ์„œ์— ์žˆ๋Š” ์•„๋ž˜ ํŒŒ์ผ๋“ค์„ ๋งŒ๋“ ๋‹ค.

  • dispatcher.network
  • dispatcher-redis.container
  • dispatcher-api.container
  • dispatcher-worker-1.container
  • dispatcher-worker-2.container
  • dispatcher-locust.container

์ด ํŒŒ์ผ ๋‚ด์šฉ์€ README.md์— ๊ทธ๋Œ€๋กœ ๋‚˜์™€ ์žˆ๋‹ค.

22.4 systemd ๋ฐ˜์˜ ๋ฐ ์‹œ์ž‘

systemctl --user daemon-reload
systemctl --user start dispatcher-redis.service
systemctl --user start dispatcher-api.service
systemctl --user start dispatcher-worker-1.service
systemctl --user start dispatcher-worker-2.service
systemctl --user start dispatcher-locust.service

22.5 ๋กœ๊ทธ์•„์›ƒ ํ›„์—๋„ ์œ ์ง€ํ•˜๋ ค๋ฉด

loginctl enable-linger $(whoami)

์ด ๋‹จ๊ณ„๋Š” "๊ทธ๋ƒฅ ์‹คํ–‰ํ•ด๋ณด๊ธฐ"๋ณด๋‹ค "Podman์—์„œ ์ž๋™ ์žฌ์‹œ์ž‘๊ณผ systemd ๊ด€๋ฆฌ๊นŒ์ง€ ํ™•์ธํ•ด๋ณด๊ธฐ"์— ๊ฐ€๊น๋‹ค.

Quadlet๋กœ ์˜ฌ๋ฆฐ ์„œ๋น„์Šค๊นŒ์ง€ ์ •๋ฆฌํ•˜๋ ค๋ฉด ์•„๋ž˜ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๋œ๋‹ค.

bash scripts/teardown_all.sh

23. ๋ฌด์—‡๋ถ€ํ„ฐ ํ•˜๋ฉด ์ข‹๋‚˜

์ฒ˜์Œ ๊ณต๋ถ€ํ•  ๋•Œ ์ถ”์ฒœ ๊ฒฝ๋กœ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  1. docker compose up -d --build
  2. curl /health, curl /jobs, curl /stats
  3. logs -f api, logs -f worker-1, logs -f worker-2
  4. Worker๋ฅผ ์ผ๋ถ€๋Ÿฌ ์ค‘์ง€ํ•˜๊ฑฐ๋‚˜ ์š”์ฒญ์„ ์—ฌ๋Ÿฌ ๊ฐœ ๋ณด๋‚ด๋ณด๋ฉฐ ํ ๋™์ž‘ ํ™•์ธ
  5. ์ต์ˆ™ํ•ด์ง€๋ฉด podman compose
  6. ๋งˆ์ง€๋ง‰์— podman machine + quadlet

24. ์ค‘์š”ํ•œ ์ฃผ์˜์ 

README.md์—์„œ๋„ ๋ถ„๋ช…ํžˆ ๋งํ•˜๋“ฏ์ด ๋‹ค์Œ์€ ํ”ผํ•˜๋Š” ํŽธ์ด ์ข‹๋‹ค.

  • Compose์™€ Quadlet์„ ๋™์‹œ์— ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ
  • ๊ฐ™์€ ํฌํŠธ์™€ ๊ฐ™์€ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฆ„์„ ์ค‘๋ณต์œผ๋กœ ๋„์šฐ์ง€ ์•Š๊ธฐ
  • ์ฒ˜์Œ๋ถ€ํ„ฐ Podman ์šด์˜ ๊ธฐ๋Šฅ๊ณผ ์•„ํ‚คํ…์ฒ˜ ํ•™์Šต์„ ํ•œ ๋ฒˆ์— ํ•˜๋ ค๊ณ  ํ•˜์ง€ ์•Š๊ธฐ

์ฒ˜์Œ์—” docker compose๋กœ ๊ตฌ์กฐ๋ฅผ ์ดํ•ดํ•˜๊ณ , ๊ทธ ๋‹ค์Œ์— Podman ์ชฝ์œผ๋กœ ๋„˜์–ด๊ฐ€๋Š” ๊ฒŒ ๊ฐ€์žฅ ๋œ ๊ผฌ์ธ๋‹ค.