JavaRush /Курси /Модуль 4: FastAPI /Введення в обробку помилок при роботі з асинхронними зада...

Введення в обробку помилок при роботі з асинхронними задачами

Модуль 4: FastAPI
Рівень 15 , Лекція 0
Відкрита

Асинхронність — це, звісно, круто. Ви можете запускати код без блокування основної програми, виконувати задачі паралельно, розподіляти навантаження, посміхатися життю. Але в цієї магії є й зворотній бік — помилки можуть відбуватися де завгодно і коли завгодно. І, якщо їх вчасно не обробити, наслідки будуть... як у п’ятничний вечір перед дедлайном.

Тож давайте подивимося, що може піти не так і чому обробка помилок така критично важлива в асинхронних системах.


Характеристики асинхронних систем, які можуть викликати помилки

  1. Асинхронне виконання задач:
    • Задачі запускаються незалежно одна від одної. Якщо одна з них «впала», хто про це дізнається? Ніхто, якщо ви не передбачили обробку помилок.
  2. Взаємодія з зовнішніми ресурсами:
    • Мережеві запити, взаємодія з базою даних, звернення до зовнішніх API. Всі ці штуки можуть дати збій (наприклад, сервер раптом вирішив піти на обід).
  3. Довгоживучі процеси:
    • Швидкі задачі зазвичай встигають завершитися до того, як щось піде не так. Але якщо задача обробляє дані годинами... ризик помилки зростає.

Чому важливо обробляти помилки в асинхронних задачах

Без обробки помилок асинхронна система стає бомбою уповільненої дії. Ось лише три приклади:

  • Втрачені дані: Помилка може призвести до того, що важливі дані просто зникнуть (наприклад, платіжний запит відправлено, але не зареєстровано). Класно, правда?
  • Проблеми з продуктивністю: Задача може «зависнути», блокуючи інші процеси.
  • Неефективне використання ресурсів: Наприклад, задача продовжує відправляти запити в систему, яка «лежить», створюючи ще більше проблем.

Види помилок в асинхронних системах

Тепер давайте подивимося на основні види помилок, з якими стикаються асинхронні системи. Їх можна розбити на дві великі групи:

  1. Помилки виконання задач (Runtime Errors)

    Це ті помилки, які відбуваються прямо під час виконання задачі. Наприклад:

    • Проблеми в логіці коду (ну, хто ж не писав баги?).
    • Ділення на нуль (ми про це всі дізнаємося ще на першому курсі).
    • Неправильний формат даних або значення.

    Приклад:

    
    import asyncio
    
    async def divide_numbers(a, b):
        return a / b
    
    # Задача впаде, бо b дорівнює нулю
    asyncio.run(divide_numbers(10, 0))
    
  2. Проблеми зв'язку та недоступності ресурсів

    Це більш підступні помилки, бо вони часто залежать не від нас, а від зовнішніх факторів:

    • Мережеві збої (так, інтернет нестабільний).
    • Недоступність зовнішнього API (або його глюки).
    • Проблеми з підключенням до бази даних.

    Приклад:

    
    import aiohttp
    import asyncio
    
    async def fetch_data(url):
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as response:
                return await response.text()
    
    # "unknown_url" призведе до мережевої помилки (наприклад, DNS-помилки)
    asyncio.run(fetch_data("http://unknown_url"))
    

Приклади наслідків необроблених помилок

Помилки, залишені без уваги, можуть викликати справжню лавину проблем. Давайте розберемо найтиповіші сценарії.

Уявіть, що ваша задача повинна відправити дані в базу даних, але стався збій, і дані не збереглися. Якщо в вас немає механізму для повторної відправки, то ці дані втрачені для вашої системи назавжди.

Приклад коду без обробки помилок:


async def save_to_database(data):
    # Уявімо, що db.execute може викликати виключення
    await db.execute("INSERT INTO table (column) VALUES (:value)", {"value": data})

# Помилка може призвести до того, що дані не збережуться
asyncio.run(save_to_database("важливі дані"))

Що відбувається в реальності, якщо помилка не оброблена:

  • Ваші дані просто зникають без сліду.
  • Немає логів, немає можливості зрозуміти, що пішло не так.

Проблеми з продуктивністю

Без обробки помилок задачі можуть зависати або безкінечно намагатися виконати дію, яка заздалегідь приречена на провал (наприклад, підключитися до відключеного сервера). В результаті:

  • Ваші системи починають марно витрачати ресурси.
  • Продуктивність падає, користувачі невдоволені.

Приклад справжнього хаосу:

Ви відправляєте 1000 задач у чергу, кожна з яких звертається до бази даних, яка в цей момент перевантажена. Всі задачі починають безкінечно намагатися перезапуститися, черги накопичуються, сервери перегружаються... і в кінці кінців ви отримуєте повний колапс системи.


З чого почати обробку помилок?

Ми розібралися з видами помилок і їхніми наслідками. Чудово! Але що робити, щоб цього уникнути? На щастя, інструментарій для асинхронних систем досить багатий:

  1. Retry (повторні спроби виконання задач):
    • Задачі, які викликали помилку, можна спробувати запустити знову. Головне — переконатися, що система враховує обмеження (наприклад, максимальна кількість спроб).
  2. Dead Letter Queues (DLQ):
    • Якщо повідомлення не можна обробити, його можна відправити в спеціальний «сховок». Пізніше ми розберемо, як повторно обробити такі повідомлення.
  3. Таймаути:
    • Обмежте час виконання задач. Якщо задача не завершилася в строк — вона вважається невдалою.
  4. Логування:
    • Логи дозволяють бачити всі помилки і розуміти їхні причини. Це ключ до всього.
  5. Моніторинг:
    • Використовуйте інструменти для управління задачами та чергами. Наприклад, в Celery є вбудовані метрики.

У наступних лекціях ми детально розглянемо всі ці підходи, включно з роботою з retry, DLQ, логуванням і моніторингом. А зараз просто запам'ятайте: необроблені помилки в асинхронних системах — це не просто баг, а потенційна катастрофа.

Переходимо до вивчення RabbitMQ, Celery і їхніх інструментів обробки помилок!

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ