Модуль 13

Pub/Sub: обмін повідомленнями

Ось урок у стилі CS50, створений спеціально за твоїм запитом.


🎓 CS50-Style: Pub/Sub — Мистецтво "Не Знати Одне Одного"

Привіт усім! Це CS50 (умовно 😉), і сьогодні ми поговоримо про архітектуру, яка дозволяє будувати системи масштабу YouTube, Uber чи біржових терміналів.

Сьогоднішня тема: Pub/Sub (Publish/Subscribe) або Видавець/Підписник.


1. 🔥 Вступ: Проблема гучномовця

Уявіть, що ви організовуєте величезну вечірку. Ви — головний бармен. Коли коктейлі готові, вам потрібно повідомити про це офіціантів.

Сценарій А (Без Pub/Sub): Ви підходите до офіціанта Андрія і кажете: "Мохіто готовий". Потім шукаєте офіціантку Олену: "Мохіто готовий". Потім біжите до стажера Ігоря: "Мохіто готовий". Питання: А що буде, якщо Ігор звільниться? Або ви наймете ще 10 офіціантів? Вам доведеться бігати за кожним і витрачати свій час, замість того щоб робити коктейлі. Це — сильна зв’язність (tight coupling). Ви знаєте занадто багато про отримувачів.

Сценарій Б (З Pub/Sub): Ви ставите посеред кімнати дошку або берете мікрофон. Ви просто оголошуєте: "МОХІТО ГОТОВИЙ!" (Публікуєте подію). Вам байдуже, хто це почує. Вам байдуже, скільки там офіціантів — троє чи сотня. Ті, хто чекає на замовлення (Підписники), почують це і зреагують.

Чому без цього не обійтись? У сучасному світі сервіси не можуть "дзвонити" один одному напряму. Якщо сервіс "Оплати" чекатиме, поки сервіс "Доставки" візьме слухавку, вся ваша система "ляже" від першого ж збою мережі. Pub/Sub вирішує цю проблему, розриваючи прямий ланцюг.


2. 🧠 Теоретична база: Що там "під капотом"?

Давайте розберемо це на атоми. У нас є три головні дійові особи.

🔑 Ключові поняття:

  1. Publisher (Видавець): Той, хто створює повідомлення (ви з мікрофоном). Він нічого не знає про отримувачів.
  2. Subscriber (Підписник): Той, хто хоче отримувати повідомлення. Він підписується на певні теми.
  3. Broker (Брокер) / Topic (Тема): Це "посередник". Це та сама дошка оголошень або поштовий центр. Publisher кидає повідомлення в Брокера, а Брокер розсилає його всім, хто підписався.

Як це працює (логіка):

Уявіть собі Twitter (або X). * Коли Ілон Маск пише твіт — він Publisher. * Він не надсилає SMS кожному з мільйонів фоловерів особисто. Він відправляє твіт у систему (Broker). * Ви (Subscriber) підписані на тему "Ілон Маск". * Коли ви відкриваєте стрічку, Брокер показує вам повідомлення.

💡 Що треба зрозуміти інтуїтивно:

Головна магія тут — Decoupling (Розв'язка). Видавець і Підписник не знають IP-адрес один одного, вони можуть бути написані на різних мовах програмування і навіть вмикатися в різний час. Їх об'єднує лише Topic (Тема повідомлення).


3. 🧪 Приклади: Від радіо до E-commerce

Приклад 1: Радіостанція (Найпростіший)

  • Видавець: Радіовежа (надсилає хвилі).
  • Тема: Частота 101.5 FM.
  • Підписник: Ваша магнітола в машині.
  • Очікування: Якщо ви вимкнете магнітолу, радіовежа перестане працювати?
  • Реальність: Ні! Вежі байдуже. Вона продовжує "публікувати". Це — суть асинхронності.

Приклад 2: Інтернет-магазин (Реальний проєкт)

Уявіть, що користувач натиснув кнопку "Купити". Ця подія — order.created.

У класичній (поганій) архітектурі код виглядав би так:

def create_order(order):
    save_to_db(order)
    send_email(order)    # А якщо поштовий сервер завис?
    update_stock(order)  # А якщо складська база повільна?
    # Користувач чекає... чекає...

У архітектурі Pub/Sub:

def create_order(order):
    save_to_db(order)
    broker.publish('events/orders', {'event': 'order.created', 'id': 123})
    # Все! Ми миттєво відповідаємо користувачу "Дякуємо за замовлення!"

А десь "за кадром" цю подію слухають: 1. Email-сервіс: "О, нове замовлення! Шлю лист". 2. Склад-сервіс: "О, нове замовлення! Бронюю товар". 3. Аналітика-сервіс: "О, нове замовлення! Додаю в звіт для боса".

Результат: Ми додали сервіс аналітики, не змінюючи жодного рядка коду в системі замовлень!


4. 🛠 Практична частина

Припустимо, ми будуємо систему "Розумний Дім" (Smart Home). У нас є центральний Брокер.

Завдання 1: Налаштування (Повтори) Уявіть, що датчик руху (Publisher) публікує повідомлення в тему home/livingroom/motion. * Напишіть (псевдокодом або словами), що має зробити Лампа (Subscriber), підписана на цю тему. (Підказка: Отримати 'motion_detected' -> Увімкнути світло).

Завдання 2: Масштабування (Зміни умови) До нас прийшла кішка. Датчик спрацював. * Додайте нового Підписника: "Камера спостереження". * Що вона має зробити при отриманні того ж повідомлення home/livingroom/motion? * Чи зміниться робота Лампи від появи Камери?

Завдання 3: Виправ помилку Датчик температури публікує дані в тему home/kitchen/temp. Кондиціонер підписаний на тему home/kitchen/temperature. * Чому кондиціонер не вмикається? (Увага на назви тем).

Завдання 4: Міні-кейс Ви розробляєте Uber. Водій завершив поїздку. Подія: ride.completed. Придумайте 3 різні сервіси-підписники, які мають зреагувати на цю подію, і поясніть, що вони роблять. (Варіанти: Списання коштів, Рейтинг, Історія поїздок...)

Завдання 5: А що, якщо... Що станеться, якщо наш Брокер (посередник) вимкнеться? * Чи отримають підписники повідомлення? * Що станеться з повідомленнями, які відправив Видавець у цей момент? (Це питання надійності, подумайте про черги повідомлень).


5. 💡 Мислення як у розробника

Як думає новачок:

"Я просто викличу функцію іншого сервісу напряму через HTTP-запит. Так швидше і простіше."

Як думає Senior Developer:

"Сьогодні це простіше. Але завтра нам треба буде додати ще 5 сервісів, які потребують цих даних. Якщо я зроблю прямий виклик, я створю 'спагеті-код'. Краще я використаю Pub/Sub. Хай видавець просто кричить у темряву, а кому треба — почує."

Типові помилки: 1. Зайва складність: Для простого сайту-візитки Pub/Sub не потрібен. Не стріляйте з гармати по горобцях. 2. Формат даних: Якщо Видавець змінив формат повідомлення (наприклад, перейменував поле price на cost), усі Підписники зламаються. Потрібен контракт (узгодження формату).

Порада: Завжди думайте про систему як про набір незалежних цеглинок LEGO. Pub/Sub — це ті самі випуклості, що дозволяють з'єднувати будь-які деталі.


6. 🧩 Підсумок

Отже, що ми маємо в сухому залишку: 1. Pub/Sub дозволяє системам спілкуватися, не знаючи нічого одна про одну. 2. Це забезпечує масштабованість: можна додавати нових слухачів без зміни коду відправника. 3. Це робить систему стійкою: якщо один сервіс впав, інші продовжують працювати.

Тепер ви вмієте: Проєктувати системи, де компоненти "слабко пов'язані" (loosely coupled), і розумієте, як Facebook чи Instagram надсилають сповіщення мільярдам юзерів, не "вішаючи" свої сервери.

🔜 У наступній серії: Pub/Sub це круто, але що як повідомлення не можна губити? Що як Підписник був офлайн, коли прийшло повідомлення про зарплату? Ми поговоримо про Message Queues (Черги повідомлень) і таких монстрів як Kafka та RabbitMQ.

А поки що — це був CS50. Побачимось! 👋