IlmHamroh
Python kursi/Miqyos va unumdorlik4/10-dars19 daqiqa
Mundarija (22)

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 fonda

Nega 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

python
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:

python
@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:

python
# 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

python
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/RETRY

Navbatlar (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 ajratish

4. Batafsil misollar

Celery Redis/RabbitMQ talab qiladi; misollar Python bilan navbat mantiqini modellashtiradi.

Misol 1 — Navbat: producer va worker

python
"""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:

text
=== 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 ajratilgan

Nima ko'rsatdi: 2.1, 2.2-bo'limlar.

Misol 2 — Vazifa hayotiy sikli (holatlar)

python
"""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:

text
=== 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)

python
"""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:

text
=== 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 urinish

Nima ko'rsatdi: 2.5-bo'lim.

Misol 4 — Worker miqyoslash (parallel)

python
"""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:

text
=== 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 bajarish

Nima 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

python
def route(): email_yubor()   # foydalanuvchi kutadi   # ⚠️
def route(): send_email.delay()   # navbatga (fon)     # ✅

2. Producer natijani sinxron kutish

python
natija = task.delay(); natija.get()   # bloklaydi     # ⚠️
# darrov javob, natijani keyin kuzat (yoki keraksiz)   # ✅

3. Idempotent bo'lmagan vazifa

python
@app.task  # to'lov (retry — ikki marta!)             # ⚠️
# idempotent (idempotency key — 26.9)                  # ✅

4. Retry yo'q (vaqtinchalik xato)

python
@app.task
def t(): tashqi_api()   # xato → yo'qoladi             # ⚠️
@app.task(max_retries=3)   # retry 27.12-bob              # ✅

5. Worker monitoring yo'q

python
# navbat to'lyaptimi? worker ishlayaptimi? (noma'lum)  # ⚠️
# Flower (navbat, worker monitoring — 28.10)            # ✅

6. Katta ma'lumot navbatga

python
task.delay(katta_fayl)   # broker og'irlashadi          # ⚠️
task.delay(fayl_id)   # ID (worker o'zi oladi)          # ✅

7. Worker kam (navbat to'planadi)

python
# 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

  1. Uzoq/og'ir vazifani navbatga (so'rovni bloklamang).

  2. Producer darrov javob (natijani kutmang).

  3. Idempotent vazifa (retry — ikki marta).

  4. Retry (vaqtinchalik xato — 27.12).

  5. Monitoring (Flower — navbat, worker).

  6. ID uzat (katta ma'lumot emas).

  7. Worker miqyoslash (yukka qarab).

  8. Periodic — Beat (cron kabi — 26.9).


9. Amaliy topshiriq

Vazifa 1: Bashorat qiling

python
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
  1. Uzoq vazifani fonda (foydalanuvchi kutmaydi)
  2. Vazifa qo'yuvchi (veb dastur)
  3. Navbatni saqlovchi (Redis, RabbitMQ)
  4. Vazifani bajaruvchi (ishchi)
  5. Vazifani navbatga qo'yish (darrov qaytadi)
  6. PENDING, STARTED, SUCCESS, FAILURE, RETRY
  7. Navbatda kutmoqda (worker olmagan)
  8. Xatoda qayta urinish
  9. Retry ikki marta bajarishi mumkin
  10. Rejalashtirilgan vazifalar (cron kabi)
  11. Ko'p worker (parallel — yuk)
  12. Vazifani vaqt/joydan (so'rov vs bajarish)

Vazifa 2: Xatolarni tuzating

python
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
python
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:

  1. Producer
  2. Broker
  3. Worker
  4. Ajratilgan

Vazifa 4: Holatlar

Modellang:

  1. PENDING
  2. STARTED
  3. SUCCESS
  4. FAILURE

Vazifa 5: Retry

Modellang:

  1. Urinish
  2. Xato
  3. Qayta
  4. Chegara

Vazifa 6: Miqyoslash

Modellang:

  1. Vazifalar
  2. 1 worker
  3. 4 worker
  4. 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

  1. Ajratish — bir yechim, ko'p foyda (tajriba + miqyos)
  2. Asinxronlik kuchli, lekin narx bilan
  3. Sinxron vs asinxron — savdo
  4. Kerak bo'lganda (majburlama emas)

6. Xulosa

  1. Ajratish — tajriba (kutmaydi) va miqyos (alohida)
  2. Bir yechim, ikki muammo
  3. Narx: murakkablik, ishonchlilik, idempotentlik
  4. Kerak bo'lganda asinxron

Nimani mustahkamlaydi: 2.1, 2.8-bo'limlar.


Xulosa

Bu darsda navbatlar (Celery) ni o'rgandik.

Eng muhim uch fikr:

  1. 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).

  2. 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.

  3. 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.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
29.4-dars: Navbatlar (Celery) — IlmHamroh