Mundarija (22)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Nega navbat (fon vazifa)
- 2.2. Navbat komponentlari (producer, broker, worker)
- 2.3. Vazifa hayotiy sikli
- 2.4. Celery asoslari
- 2.5. Retry va xato boshqarish
- 2.6. Rejalashtirilgan vazifalar (periodic)
- 2.7. Navbat amaliyoti
- 2.8. Navbat — vazifani vaqt va joydan ajratish
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Navbat: producer va worker
- Misol 2 — Vazifa hayotiy sikli (holatlar)
- Misol 3 — Retry (xatoda qayta urinish)
- Misol 4 — Worker miqyoslash (parallel)
- 5. To'g'ri va noto'g'ri tushunishlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8. Eng yaxshi amaliyotlar
- 9. Amaliy topshiriq
- Xulosa
29.4-dars: Navbatlar (Celery)
29-QISM — MIQYOS VA UNUMDORLIK · 4-dars
1. Kirish va motivatsiya
Ba'zi vazifalar uzoq davom etadi: email yuborish, rasm qayta ishlash, hisobot yaratish, video kodlash. Agar foydalanuvchi tugmani bosgach, bu vazifa darrov (so'rov ichida) bajarilsa — foydalanuvchi kutadi (10 soniya, 1 daqiqa — "sahifa qotib qoldi"). Yomon tajriba. Yaxshi yechim: vazifani fon rejimida bajarish — foydalanuvchiga darrov "qabul qilindi" deb javob berib, vazifani keyin (fonda) bajarish. Navbat (queue) buni ta'minlaydi: vazifa navbatga qo'yiladi, alohida ishchilar (worker) uni fonda bajaradi. Foydalanuvchi kutmaydi, tizim vazifani o'z vaqtida qayta ishlaydi.
Navbatlar (Celery) — uzoq vazifalarni fon rejimida asinxron bajarish: vazifa navbati (task queue — bajarilishi kerak vazifalar ro'yxati), producer (vazifa qo'yuvchi — veb dastur), broker (navbat saqlovchi — Redis, RabbitMQ — 27.10), worker (ishchi — vazifani oladi, bajaradi), natija (result backend — natija saqlash). Celery — Python'ning mashhur vazifa navbati. Foydalar: javob tez (foydalanuvchi kutmaydi), miqyoslash (ko'p worker — parallel), ishonchlilik (vazifa yo'qolmaydi — navbatda, qayta urinish). Bu hodisaga asoslangan (27.10 — Observer), async (14-qism) bilan bog'liq. Navbat — vazifani fonga ko'chirish. Fon vazifa — tez javob.
Real vaziyat. Bir tizimda foydalanuvchi ro'yxatdan o'tganda tasdiqlash emaili so'rov ichida yuborilardi — email server sekin bo'lganda foydalanuvchi 15 soniya kutardi (ba'zan xato). Celery qo'llanildi: ro'yxatdan o'tganda vazifa navbatga qo'yildi (send_email.delay(...)), so'rov darrov javob berdi ("ro'yxatdan o'tdingiz"), email fonda (worker) yuborildi. Foydalanuvchi kutmadi (darrov javob), email o'z vaqtida ketdi. Navbat — uzoq ishni fonga oldi.
Bu darsda navbatlar (Celery) ni o'rganamiz.
Bu darsda:
- Nega navbat (fon vazifa)
- Navbat komponentlari (producer, broker, worker)
- Vazifa hayotiy sikli
- Celery asoslari
- Retry va xato boshqarish
- Rejalashtirilgan vazifalar (periodic)
- Navbat amaliyoti
- Amaliy: navbat modeli
ℹ Celery Redis/RabbitMQ talab qiladi; misollar Python bilan navbat mantiqini modellashtiradi (deterministik).
2. Nazariya — chuqur tushuntirish
2.1. Nega navbat (fon vazifa)
Foydalanuvchini kutdirmaslik:
Navbatsiz: so'rov ichida uzoq vazifa → foydalanuvchi kutadi
tugma bos → email yuborish (15s) → javob (kutish!)
Navbat: vazifa navbatga → darrov javob → fonda bajarish
tugma bos → "qabul qilindi" (darrov) → email fondaNega navbat — uzoq vazifalarni (email, rasm, hisobot) fon rejimida bajarish: so'rov ichida bajarilsa — foydalanuvchi kutadi (yomon tajriba); navbat vazifani keyinga qoldiradi (darrov javob, fonda bajarish). Sabab: foydalanuvchi tez javob kutadi (28.10 — latency); uzoq vazifa so'rovni bloklaydi (kutish, timeout, resurs). Navbat vazifani ajratadi (so'rov — tez javob, vazifa — fonda). Foyda: tez javob, miqyoslash (ko'p worker), ishonchlilik (vazifa saqlanadi). Navbat — uzoq ishni fonga. Tez javob — yaxshi tajriba.
2.2. Navbat komponentlari (producer, broker, worker)
Uch asosiy qism:
Producer (veb dastur) → vazifani navbatga qo'yadi
↓
Broker (Redis/RabbitMQ) — navbatni saqlaydi
↓
Worker (ishchi) → vazifani oladi, bajaradi
↓
Result backend — natijani saqlaydi (ixtiyoriy) Navbat komponentlari: Producer (ishlab chiqaruvchi — vazifani navbatga qo'yadi: veb dastur — task.delay()); Broker (vositachi — navbatni saqlaydi: Redis, RabbitMQ — 27.10; vazifalar shu yerda kutadi); Worker (ishchi — navbatdan vazifani oladi va bajaradi: alohida jarayon, ko'p bo'lishi mumkin — parallel); Result backend (natijani saqlash — ixtiyoriy: vazifa natijasi kerak bo'lsa). Producer va worker ajratilgan (producer qo'yadi, worker bajaradi — bir-birini kutmaydi — 27.10 kabi). Bir vazifa — bir worker. Komponentlar — navbat tizimi. Ajratilgan — mustaqil.
2.3. Vazifa hayotiy sikli
Vazifa holatlari:
PENDING (navbatda kutmoqda) → STARTED (worker oldi)
→ SUCCESS (bajarildi) yoki FAILURE (xato)
→ RETRY (qayta urinish, agar xato)
producer vazifa ID oladi → holatni kuzatishi mumkin Vazifa hayotiy sikli: PENDING (navbatda — kutmoqda, worker hali olmagan), STARTED (worker oldi — bajarilmoqda), SUCCESS (muvaffaqiyatli bajarildi) yoki FAILURE (xato), RETRY (xatoda qayta urinish — 27.12). Producer vazifani qo'yganda ID oladi (AsyncResult) — holatni kuzatishi mumkin (.status, .get() natija). Sabab: vazifa asinxron (fonda) — holati vaqt bilan o'zgaradi (kutmoqda → bajarilmoqda → tayyor); producer natijani kutishi yoki kuzatishi mumkin. Hayotiy sikli — vazifa yo'li (navbat → bajarish → natija). Holat — vazifa qayerda.
2.4. Celery asoslari
from celery import Celery
app = Celery("myapp", broker="redis://localhost")
@app.task
def send_email(user_id, matn):
# uzoq vazifa (fonda bajariladi)
email_yubor(user_id, matn)
# producer (veb dastur):
send_email.delay(42, "Salom") # navbatga qo'yadi (darrov qaytadi)
# worker: celery -A myapp worker (alohida jarayon) Celery asoslari: Celery(broker=...) (ilova — broker manzili), @app.task (vazifani belgilash — dekorator, funksiyani vazifaga aylantiradi), .delay(args) (vazifani navbatga qo'yish — darrov qaytadi, worker keyin bajaradi), .apply_async (kengaytirilgan — kechiktirish, ustuvorlik bilan). Worker alohida ishga tushiriladi (celery worker — 28.1 konteyner). Producer .delay() chaqiradi (bloklamaydi), worker fonda bajaradi. Bu FastAPI (20-qism), Docker 28.1-bob bilan ishlatiladi (worker — alohida konteyner). Celery — Python vazifa navbati. .delay() — fonga qo'yish.
2.5. Retry va xato boshqarish
Xatoda qayta urinish:
@app.task(bind=True, max_retries=3)
def qayta_urinuvchi(self, data):
try:
tashqi_api_chaqir(data)
except ConnectionError as e:
# vaqtinchalik xato — qayta urinish (27.12)
raise self.retry(exc=e, countdown=60) # 60s keyin Retry va xato boshqarish — vazifa xato bersa (tashqi API yiqildi, tarmoq) — qayta urinish (27.12 kabi): self.retry (qayta navbatga — countdown kechikish, max_retries chegara). Sabab: fon vazifa nazoratsiz (odam kutmaydi) — xato bo'lsa avtomatik qayta urinish kerak (vaqtinchalik xato o'tib ketishi mumkin — 27.12); yoki xato log/ogohlantirish (28.12 Sentry). Idempotentlik (26.9 — qayta bajarish zararsiz) muhim (retry — ikki marta bajarilishi mumkin). Xato boshqarish — fon vazifa ishonchliligi. Retry — vaqtinchalik xatoga. Fon vazifa — mustahkam bo'lishi kerak.
2.6. Rejalashtirilgan vazifalar (periodic)
Davriy fon vazifalar:
# Celery Beat — rejalashtirilgan vazifalar (cron kabi — 26.9)
app.conf.beat_schedule = {
"har-kuni-hisobot": {
"task": "generate_report",
"schedule": crontab(hour=9, minute=0), # har kuni 09:00
},
} Rejalashtirilgan vazifalar (periodic tasks) — Celery Beat davriy vazifalarni navbatga qo'yadi (26.9 cron kabi, lekin Celery ichida): beat_schedule (jadval — crontab(hour=9) har kuni 09:00, yoki timedelta — har N daqiqa). Sabab: ba'zi fon vazifalar davriy (har kuni hisobot, har soatda tozalash, sinxronizatsiya) — Beat ularni vaqtida navbatga qo'yadi, worker bajaradi. Bu cron 26.9-bob ni Celery bilan birlashtiradi (cron — OS, Beat — Celery). Foyda: navbat afzalliklari (retry, monitoring) davriy vazifalarda. Beat — davriy vazifa rejalashtirgichi. Davriy fon — Beat bilan.
2.7. Navbat amaliyoti
Navbat amaliyotlari: uzoq/og'ir vazifani navbatga (email, rasm, hisobot — so'rovni bloklamaslik); tez javob (producer darrov qaytadi — 28.10 latency); idempotentlik (26.9 — retry zararsiz); retry (27.12 — vaqtinchalik xato); monitoring (28.10 — navbat uzunligi, worker holati — Flower vositasi); worker miqyoslash (ko'p worker — parallel, yukka qarab — 29.6); natijani keshlash (29.3 — agar kerak); navbat ustuvorligi (muhim vazifalar avval). Tuzoqlar: navbat to'lib ketishi (worker kam — vazifalar to'planadi), idempotent emas (retry — ikki marta), sinxron kutish (producer natijani kutsa — navbat foydasi yo'q). Yaxshi navbat — uzoq vazifaga, idempotent, monitoring bilan. Amaliyot — samarali navbat. Fon vazifa — to'g'ri ishlatish.
2.8. Navbat — vazifani vaqt va joydan ajratish
Navbat asosiy g'oyasi — vazifani vaqt va joydan ajratish: vazifa qachon so'ralgan (producer) va qachon/qayerda bajarilgan (worker) — ajratilgan (bir so'rov darrov javob, vazifa keyin/boshqa jarayonda). Bu hodisaga asoslangan arxitektura (27.10 — producer/consumer ajratilgan), async (14-qism — kutmasdan) tamoyillari. Navbat unumdorlik (tez javob — foydalanuvchi kutmaydi), miqyoslash (worker ko'paytirish — 29.6), ishonchlilik (vazifa saqlanadi, retry) beradi. Bu Celery (Python), Sidekiq (Ruby), Bull (Node) — barcha tilda navbat. "Uzoq ishni fonga" — unumdorlik prinsipi. Navbat — vazifani ajratish (so'rov tez, vazifa fonda). Ajratish — miqyoslanuvchan tizim.
3. Tez ma'lumotnoma
from celery import Celery
app = Celery("myapp", broker="redis://localhost", backend="redis://localhost")
# VAZIFA (task):
@app.task
def send_email(user_id, matn):
email_yubor(user_id, matn)
# PRODUCER (navbatga qo'yish):
natija = send_email.delay(42, "Salom") # darrov qaytadi
# holatni kuzatish:
natija.status # PENDING/STARTED/SUCCESS/FAILURE
natija.get() # natijani kutish (bloklaydi)
# WORKER (alohida jarayon):
# celery -A myapp worker --loglevel=info
# RETRY (xatoda qayta urinish):
@app.task(bind=True, max_retries=3)
def t(self, data):
try: ...
except Exception as e: raise self.retry(exc=e, countdown=60)
# PERIODIC (Celery Beat — cron kabi):
# beat_schedule = {"job": {"task": "...", "schedule": crontab(hour=9)}}
# KOMPONENTLAR: producer → broker (Redis) → worker → result
# HOLATLAR: PENDING → STARTED → SUCCESS/FAILURE/RETRYNavbatlar (Celery) xulosasi
Navbat — uzoq vazifani fonda (foydalanuvchi kutmaydi)
Producer (qo'yadi) → broker (Redis, saqlaydi) → worker (bajaradi)
Vazifa holatlari: PENDING → STARTED → SUCCESS/FAILURE/RETRY
Celery: @app.task, .delay() (fonga) · retry (xatoda)
Beat (periodic — cron kabi) · vazifani vaqt/joydan ajratish4. Batafsil misollar
Celery Redis/RabbitMQ talab qiladi; misollar Python bilan navbat mantiqini modellashtiradi.
Misol 1 — Navbat: producer va worker
"""Navbat: producer vazifa qo'yadi, worker bajaradi (ajratilgan)."""
from collections import deque
class Navbat:
def __init__(self) -> None:
self.vazifalar: deque = deque()
def qoy(self, vazifa: dict) -> str:
# producer — navbatga qo'yadi (darrov qaytadi)
vazifa["holat"] = "PENDING"
self.vazifalar.append(vazifa)
return f"vazifa {vazifa['id']} navbatga qo'yildi"
def ol(self) -> dict | None:
# worker — navbatdan oladi
return self.vazifalar.popleft() if self.vazifalar else None
def worker_bajar(vazifa: dict) -> dict:
vazifa["holat"] = "STARTED"
natija = f"email {vazifa['user']} ga yuborildi"
vazifa["holat"] = "SUCCESS"
vazifa["natija"] = natija
return vazifa
def main() -> None:
navbat = Navbat()
print("=== 1. Producer vazifalarni qo'yadi (tez) ===")
for i in range(1, 4):
print(f" {navbat.qoy({'id': i, 'user': f'user{i}'})}")
print("\n=== 2. Producer darrov davom etadi ===")
print(" so'rov javob berdi (vazifalar fonda kutadi)")
print(f" navbatda: {len(navbat.vazifalar)} vazifa")
print("\n=== 3. Worker vazifalarni bajaradi (fonda) ===")
while True:
vazifa = navbat.ol()
if vazifa is None:
break
natija = worker_bajar(vazifa)
print(f" vazifa {natija['id']}: {natija['holat']} — {natija['natija']}")
print("\n=== 4. Ajratilgan ===")
print(" producer qo'ydi (tez), worker bajardi (fonda)")
print(" ⭐ Navbat — producer/worker ajratilgan")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Producer vazifalarni qo'yadi (tez) ===
vazifa 1 navbatga qo'yildi
vazifa 2 navbatga qo'yildi
vazifa 3 navbatga qo'yildi
=== 2. Producer darrov davom etadi ===
so'rov javob berdi (vazifalar fonda kutadi)
navbatda: 3 vazifa
=== 3. Worker vazifalarni bajaradi (fonda) ===
vazifa 1: SUCCESS — email user1 ga yuborildi
vazifa 2: SUCCESS — email user2 ga yuborildi
vazifa 3: SUCCESS — email user3 ga yuborildi
=== 4. Ajratilgan ===
producer qo'ydi (tez), worker bajardi (fonda)
⭐ Navbat — producer/worker ajratilganNima ko'rsatdi: 2.1, 2.2-bo'limlar.
Misol 2 — Vazifa hayotiy sikli (holatlar)
"""Vazifa holatlari: PENDING → STARTED → SUCCESS/FAILURE."""
class Vazifa:
def __init__(self, vazifa_id: int) -> None:
self.id = vazifa_id
self.holat = "PENDING"
self.natija = None
def boshla(self) -> None:
self.holat = "STARTED"
def tugat(self, muvaffaqiyat: bool, natija: str = "") -> None:
if muvaffaqiyat:
self.holat = "SUCCESS"
self.natija = natija
else:
self.holat = "FAILURE"
def main() -> None:
print("=== 1. Vazifa yaratildi (PENDING) ===")
v = Vazifa(1)
print(f" vazifa {v.id}: {v.holat} (navbatda kutmoqda)")
print("\n=== 2. Worker oldi (STARTED) ===")
v.boshla()
print(f" vazifa {v.id}: {v.holat} (bajarilmoqda)")
print("\n=== 3. Bajarildi (SUCCESS) ===")
v.tugat(muvaffaqiyat=True, natija="email yuborildi")
print(f" vazifa {v.id}: {v.holat} — {v.natija}")
print("\n=== 4. Boshqa vazifa xato (FAILURE) ===")
v2 = Vazifa(2)
v2.boshla()
v2.tugat(muvaffaqiyat=False)
print(f" vazifa {v2.id}: {v2.holat}")
print(" producer holatni kuzatishi mumkin (.status)")
print(" ⭐ Vazifa — holatlar bo'ylab (hayotiy sikl)")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Vazifa yaratildi (PENDING) ===
vazifa 1: PENDING (navbatda kutmoqda)
=== 2. Worker oldi (STARTED) ===
vazifa 1: STARTED (bajarilmoqda)
=== 3. Bajarildi (SUCCESS) ===
vazifa 1: SUCCESS — email yuborildi
=== 4. Boshqa vazifa xato (FAILURE) ===
vazifa 2: FAILURE
producer holatni kuzatishi mumkin (.status)
⭐ Vazifa — holatlar bo'ylab (hayotiy sikl)Nima ko'rsatdi: 2.3-bo'lim.
Misol 3 — Retry (xatoda qayta urinish)
"""Retry: vazifa xatoda qayta urinadi (max_retries chegarasi bilan)."""
class RetryVazifa:
def __init__(self, muvaffaqiyat_urinish: int, max_retries: int = 3) -> None:
self.urinish = 0
self.muvaffaqiyat_urinish = muvaffaqiyat_urinish
self.max_retries = max_retries
def bajar(self) -> dict:
while self.urinish <= self.max_retries:
self.urinish += 1
if self.urinish >= self.muvaffaqiyat_urinish:
return {"holat": "SUCCESS", "urinishlar": self.urinish}
# xato — qayta urinish
if self.urinish > self.max_retries:
break
return {"holat": "FAILURE", "urinishlar": self.urinish}
def main() -> None:
print("=== 1. 3-urinishda muvaffaqiyat ===")
v = RetryVazifa(muvaffaqiyat_urinish=3)
natija = v.bajar()
print(f" holat: {natija['holat']}, urinishlar: {natija['urinishlar']}")
print("\n=== 2. Doim xato (chegaraga yetadi) ===")
v2 = RetryVazifa(muvaffaqiyat_urinish=10, max_retries=3)
natija = v2.bajar()
print(f" holat: {natija['holat']}, urinishlar: {natija['urinishlar']}")
print("\n=== 3. Nega retry ===")
print(" fon vazifa nazoratsiz (odam kutmaydi)")
print(" vaqtinchalik xato → qayta urinish 27.12-bob")
print("\n=== 4. Idempotentlik muhim ===")
print(" retry — ikki marta bajarilishi mumkin")
print(" idempotent (26.9 — qayta zararsiz)")
print(" ⭐ Retry — xatoda qayta urinish")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. 3-urinishda muvaffaqiyat ===
holat: SUCCESS, urinishlar: 3
=== 2. Doim xato (chegaraga yetadi) ===
holat: FAILURE, urinishlar: 4
=== 3. Nega retry ===
fon vazifa nazoratsiz (odam kutmaydi)
vaqtinchalik xato → qayta urinish 27.12-bob
=== 4. Idempotentlik muhim ===
retry — ikki marta bajarilishi mumkin
idempotent (26.9 — qayta zararsiz)
⭐ Retry — xatoda qayta urinishNima ko'rsatdi: 2.5-bo'lim.
Misol 4 — Worker miqyoslash (parallel)
"""Worker miqyoslash: ko'p worker vazifalarni parallel bajaradi (tez)."""
def taqsimla(vazifalar: int, workerlar: int) -> dict:
# vazifalarni workerlar orasida taqsimlash
har_worker = vazifalar // workerlar
qoldiq = vazifalar % workerlar
taqsimot = [har_worker + (1 if i < qoldiq else 0) for i in range(workerlar)]
# eng band worker (vaqt — eng ko'p vazifali)
eng_band = max(taqsimot)
return {"taqsimot": taqsimot, "eng_band": eng_band}
def main() -> None:
vazifalar = 12
print("=== 1. 1 worker (ketma-ket) ===")
r = taqsimla(vazifalar, 1)
print(f" taqsimot: {r['taqsimot']}")
print(f" eng band: {r['eng_band']} vazifa (hammasi bitta)")
print("\n=== 2. 4 worker (parallel) ===")
r = taqsimla(vazifalar, 4)
print(f" taqsimot: {r['taqsimot']}")
print(f" eng band: {r['eng_band']} vazifa (parallel)")
print("\n=== 3. Tezlashish ===")
bir = taqsimla(vazifalar, 1)["eng_band"]
tort = taqsimla(vazifalar, 4)["eng_band"]
print(f" 1 worker: {bir}, 4 worker: {tort}")
print(f" ~{bir // tort}x tez (parallel)")
print("\n=== 4. Miqyoslash ===")
print(" yuk oshsa — worker qo'shish (parallel)")
print(" navbat + ko'p worker (29.6 miqyoslash)")
print(" ⭐ Worker miqyoslash — parallel bajarish")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. 1 worker (ketma-ket) ===
taqsimot: [12]
eng band: 12 vazifa (hammasi bitta)
=== 2. 4 worker (parallel) ===
taqsimot: [3, 3, 3, 3]
eng band: 3 vazifa (parallel)
=== 3. Tezlashish ===
1 worker: 12, 4 worker: 3
~4x tez (parallel)
=== 4. Miqyoslash ===
yuk oshsa — worker qo'shish (parallel)
navbat + ko'p worker (29.6 miqyoslash)
⭐ Worker miqyoslash — parallel bajarishNima ko'rsatdi: 2.7-bo'lim.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "Uzoq vazifa so'rov ichida" | Navbatga (fonda) |
| "Producer natijani kutadi" | Ajratilgan (darrov qaytadi) |
| "Vazifa yo'qoladi" | Navbatda saqlanadi (retry) |
| "Retry keraksiz" | Xatoda qayta urinish |
| "Vazifa idempotent bo'lmasa mayli" | Idempotent (retry — ikki marta) |
| "Bir worker yetadi" | Ko'p worker (parallel, miqyos) |
| "Celery = Redis" | Celery — navbat, Redis — broker |
| "Navbat = kechikish" | Tez javob (vazifa fonda) |
6. Keng tarqalgan xatolar va yechimlari
1. Uzoq vazifa so'rov ichida
def route(): email_yubor() # foydalanuvchi kutadi # ⚠️
def route(): send_email.delay() # navbatga (fon) # ✅2. Producer natijani sinxron kutish
natija = task.delay(); natija.get() # bloklaydi # ⚠️
# darrov javob, natijani keyin kuzat (yoki keraksiz) # ✅3. Idempotent bo'lmagan vazifa
@app.task # to'lov (retry — ikki marta!) # ⚠️
# idempotent (idempotency key — 26.9) # ✅4. Retry yo'q (vaqtinchalik xato)
@app.task
def t(): tashqi_api() # xato → yo'qoladi # ⚠️
@app.task(max_retries=3) # retry 27.12-bob # ✅5. Worker monitoring yo'q
# navbat to'lyaptimi? worker ishlayaptimi? (noma'lum) # ⚠️
# Flower (navbat, worker monitoring — 28.10) # ✅6. Katta ma'lumot navbatga
task.delay(katta_fayl) # broker og'irlashadi # ⚠️
task.delay(fayl_id) # ID (worker o'zi oladi) # ✅7. Worker kam (navbat to'planadi)
# 1 worker, 1000 vazifa/min (to'planadi) # ⚠️
# worker miqyoslash (yukka qarab — 29.6) # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 27.10-dars (o'tilgan): Hodisaga asoslangan — producer/consumer
- 29.5-dars: Kafka/RabbitMQ — broker
- 14-qism (o'tilgan): Async — asinxron vazifa
- 26.9-dars (o'tilgan): Cron — periodic (Beat)
- 29.6-dars: Miqyoslash — worker
8. Eng yaxshi amaliyotlar
Uzoq/og'ir vazifani navbatga (so'rovni bloklamang).
Producer darrov javob (natijani kutmang).
Idempotent vazifa (retry — ikki marta).
Retry (vaqtinchalik xato — 27.12).
Monitoring (Flower — navbat, worker).
ID uzat (katta ma'lumot emas).
Worker miqyoslash (yukka qarab).
Periodic — Beat (cron kabi — 26.9).
9. Amaliy topshiriq
Vazifa 1: Bashorat qiling
1. # nega navbat (fon vazifa)?
2. # producer nima?
3. # broker nima?
4. # worker nima?
5. # .delay() nima?
6. # vazifa holatlari?
7. # PENDING nima?
8. # retry nima?
9. # nega idempotent?
10. # Celery Beat nima?
11. # worker miqyoslash?
12. # navbat nimani ajratadi?Javoblar
- Uzoq vazifani fonda (foydalanuvchi kutmaydi)
- Vazifa qo'yuvchi (veb dastur)
- Navbatni saqlovchi (Redis, RabbitMQ)
- Vazifani bajaruvchi (ishchi)
- Vazifani navbatga qo'yish (darrov qaytadi)
- PENDING, STARTED, SUCCESS, FAILURE, RETRY
- Navbatda kutmoqda (worker olmagan)
- Xatoda qayta urinish
- Retry ikki marta bajarishi mumkin
- Rejalashtirilgan vazifalar (cron kabi)
- Ko'p worker (parallel — yuk)
- Vazifani vaqt/joydan (so'rov vs bajarish)
Vazifa 2: Xatolarni tuzating
1. def route(): email_yubor() # kutadi
2. natija = task.delay(); natija.get()
3. @app.task; def tolov() # idempotent emas
4. @app.task; def t(): api() # retry yo'q
5. task.delay(katta_fayl)Javoblar
1. send_email.delay() (navbatga)
2. darrov javob (natijani kuzat/keraksiz)
3. idempotent (idempotency key)
4. @app.task(max_retries=3)
5. task.delay(fayl_id) (ID)Vazifa 3: Navbat
Modellang:
- Producer
- Broker
- Worker
- Ajratilgan
Vazifa 4: Holatlar
Modellang:
- PENDING
- STARTED
- SUCCESS
- FAILURE
Vazifa 5: Retry
Modellang:
- Urinish
- Xato
- Qayta
- Chegara
Vazifa 6: Miqyoslash
Modellang:
- Vazifalar
- 1 worker
- 4 worker
- Parallel
Vazifa 7: O'ylash
Navbat vazifani "vaqt va joydan ajratadi" (so'rov darrov javob beradi, vazifa keyin/boshqa jarayonda bajariladi). Nima uchun bu "sinxrondan asinxronga" o'tish foydalanuvchi tajribasi va tizim miqyoslanuvchanligi uchun ikkalasi uchun ham foydali, va nega u yangi murakkablik (vazifa yo'qolishi, holat kuzatuvi, idempotentlik) keltiradi — asinxronlikning narxi qanday?
Javob
Qisqa javob: "Sinxrondan asinxronga" o'tish foydalanuvchi tajribasi VA miqyoslanuvchanlik uchun foydali, chunki ular bir ildizdan: ajratish (decoupling). Foydalanuvchi tajribasi: sinxron — foydalanuvchi vazifa tugashini kutadi (uzoq vazifa — uzoq kutish, "qotgan sahifa"); asinxron — darrov javob ("qabul qilindi"), vazifa fonda — foydalanuvchi kutmaydi (yaxshi tajriba). Miqyoslanuvchanlik: sinxron — so'rov va bajarish bir jarayonda bog'langan (uzoq vazifa — jarayon band, kam so'rov qabul qiladi); asinxron — so'rov (tez, ko'p qabul qiladi) va bajarish (worker, alohida miqyoslanadi — 29.6) ajratilgan (yuk oshsa worker qo'shasan, veb serverni emas). Ya'ni bir yechim (ajratish) ikki muammoni yechadi: kutish (tajriba) va bog'lanish (miqyos). Lekin asinxronlik narx keltiradi: (1) murakkablik (ikki qism — producer/worker, broker; bir jarayon o'rniga taqsimlangan tizim — 27.9); (2) holat kuzatuvi (vazifa darrov tugamaydi — "tayyormi?" so'rash kerak, natija keyin); (3) vazifa yo'qolishi (broker yiqilsa? worker o'lsa? — ishonchlilik mexanizmlari — navbat saqlash, retry — 27.12); (4) idempotentlik (retry — vazifa ikki marta bajarilishi mumkin — 26.9); (5) debug qiyin (oqim ko'rinmas — 27.10 hodisaga asoslangan kabi — tarqoq log, correlation ID — 28.11). Bu "sinxron sodda, asinxron kuchli lekin murakkab" savdosi (tradeoff): sinxron — oson tushunish (ketma-ket, darrov natija), lekin bloklaydi; asinxron — moslashuvchan, miqyoslanadi, lekin taqsimlangan tizim murakkabligi 27.9-bob. Qoida: asinxron kerak bo'lganda (uzoq vazifa, miqyos) — har vazifaga emas (oddiy, tez vazifa sinxron — soddaroq). Muhandislik saboqlari: ajratish (decoupling) — bir yechim, ko'p foyda (tajriba + miqyos); asinxronlik kuchli, lekin narx bilan (murakkablik, ishonchlilik, idempotentlik); "sinxron vs asinxron" — savdo (soddalik vs moslashuvchanlik); kerak bo'lganda asinxron (majburlama emas).
1. Nega ikkalasi uchun foydali (ajratish)
Bir ildiz — decoupling. Tajriba: darrov javob (kutmaydi). Miqyos: so'rov va bajarish alohida miqyoslanadi.
2. Bir yechim, ikki muammo
| Muammo | Ajratish yechimi |
|---|---|
| Kutish (tajriba) | Darrov javob (vazifa fonda) |
| Bog'lanish (miqyos) | Worker alohida miqyoslanadi |
3. Asinxronlik narxi
- Murakkablik (producer/worker, broker)
- Holat kuzatuvi (tayyormi?)
- Vazifa yo'qolishi (ishonchlilik)
- Idempotentlik (retry — ikki marta)
- Debug qiyin (oqim ko'rinmas)
4. Savdo (tradeoff)
Sinxron — sodda, bloklaydi. Asinxron — moslashuvchan, murakkab. Kerak bo'lganda asinxron.
5. Muhandislik saboqlari
- Ajratish — bir yechim, ko'p foyda (tajriba + miqyos)
- Asinxronlik kuchli, lekin narx bilan
- Sinxron vs asinxron — savdo
- Kerak bo'lganda (majburlama emas)
6. Xulosa
- Ajratish — tajriba (kutmaydi) va miqyos (alohida)
- Bir yechim, ikki muammo
- Narx: murakkablik, ishonchlilik, idempotentlik
- Kerak bo'lganda asinxron
Nimani mustahkamlaydi: 2.1, 2.8-bo'limlar.
Xulosa
Bu darsda navbatlar (Celery) ni o'rgandik.
Eng muhim uch fikr:
Nega navbat va komponentlar. Navbat — uzoq vazifalarni (email, rasm, hisobot) fon rejimida bajarish: so'rov ichida bajarilsa foydalanuvchi kutadi (yomon tajriba), navbat vazifani keyinga qoldiradi (darrov javob, fonda). Komponentlar: Producer (vazifani navbatga qo'yadi —
.delay()), Broker (navbatni saqlaydi — Redis/RabbitMQ), Worker (vazifani oladi va bajaradi — alohida jarayon, ko'p bo'lishi mumkin), Result backend (natija — ixtiyoriy). Producer va worker ajratilgan (bir-birini kutmaydi — tez javob).Hayotiy sikl, Celery, retry. Vazifa hayotiy sikli: PENDING (navbatda kutmoqda), STARTED (worker oldi), SUCCESS/FAILURE, RETRY (xatoda qayta urinish); producer ID oladi (holatni kuzatadi). Celery:
Celery(broker=...),@app.task(vazifa),.delay()(navbatga — darrov qaytadi), worker alohida (celery worker). Retry — vazifa xato bersa qayta urinish (self.retry,max_retries— 27.12); fon vazifa nazoratsiz — idempotentlik (26.9 — retry ikki marta bajarishi mumkin) muhim.Periodic, amaliyot, ajratish. Rejalashtirilgan vazifalar — Celery Beat davriy vazifalarni navbatga qo'yadi (26.9 cron kabi, Celery ichida —
crontab(hour=9)). Amaliyot: uzoq vazifani navbatga, tez javob (producer darrov), idempotentlik, retry, monitoring (Flower), worker miqyoslash 29.6-bob, ID uzat (katta ma'lumot emas). Navbat vazifani vaqt va joydan ajratadi (so'rov darrov javob, vazifa keyin/boshqa jarayonda — hodisaga asoslangan 27.10, async 14-qism); unumdorlik (tez javob), miqyoslash (worker — 29.6), ishonchlilik (saqlash, retry) beradi. "Sinxrondan asinxronga" o'tish tajriba VA miqyos uchun foydali (ajratish — bir yechim), lekin narx bilan (murakkablik, holat kuzatuvi, vazifa yo'qolishi, idempotentlik — asinxronlik savdosi). Kerak bo'lganda (uzoq/og'ir vazifa).
Keyingi darsda navbatlar: Kafka / RabbitMQ ni o'rganamiz: xabar brokerlari chuqurroq — RabbitMQ (an'anaviy navbat) va Kafka (hodisa oqimi) farqi, xabar yetkazish kafolatlari va broker tanlovi.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!