Питання High Availability — як збільшувати продуктивність та працювати з високим навантаженням — в будь-якому продукті стоїть гостро. В цьому матеріалі розглянемо підхід, який призначений пришвидшити роботу PHP з брокером повідомлень, на прикладі стеку PHP + RabbitMQ + AMQProxy.
Термінологія
Спочатку пройдемося термінами.
AMQP (Advanced Message Queuing Protocol) — відкритий протокол для передачі повідомлень між компонентами системи.
Основна ідея полягає в тому, що окремі підсистеми (або незалежні застосунки) можуть обмінюватися довільним чином повідомленнями через AMQP-брокер, який здійснює маршрутизацію, можливо гарантує доставку, розподіл потоків даних, підписку на потрібні типи повідомлень.
RabbitMQ — це брокер повідомлень із відкритим вихідним кодом.
RabbitMQ реалізує і доповнює протокол AMQP. Він маршрутизує повідомлення за всіма базовими принципами протоколу AMQP, описаними в специфікації. Відправник передає повідомлення брокеру, а той доставляє його одержувачу.
В чому проблема швидкості публікації повідомлень
На своєму продукті, коли маємо великі навантаження, ми запускаємо PHP сервіси у Kubernetes. При таких умовах ми завжди використовуємо особливий підхід та спеціальні інструменти.
Памʼятаємо, що PHP-FPM щоразу створює мережеве з’єднання під час звернення до зовнішніх даних і не перевикористовує його. Це призводить до високого навантаження на мережеву підсистему серверів, затримок на створення нових з’єднань і на закриття використаних портів.
У протоколі AMQP, якщо ви відкриваєте з’єднання, клієнт та сервер мають обмінятися сімома пакетами TCP. Якщо ви потім хочете опублікувати повідомлення, вам потрібно відкрити канал, для якого потрібні ще два. Потім для публікації вам потрібен принаймні ще один. А потім, щоб елегантно закрити з’єднання, вам знадобляться ще чотири пакети.
Тобто загалом потрібно 15 пакетів TCP або 18, якщо ви використовуєте AMQPS (TLS). Для клієнтів, які з будь-якої причини не можуть підтримувати довгострокові з’єднання із сервером, це має значний вплив на затримку.
Розв’язання цієї проблеми розглянемо на прикладі AMQProxy.
Для чого потрібен та як використовувати AMQProxy?
AMQProxy — це проксі-сервіс AMQP з відкритим вихідним кодом, який може повторно використовувати з’єднання AMQP.
AMQProxy дозволяє клієнту (наприклад, PHP-клієнту), який зазвичай може використовувати лише короткочасні з’єднання, використовувати постійні з’єднання. Це зменшує споживання ресурсів мережі та черги повідомлень для ресурсів RabbitMQ.
Якщо запустити цей проксі-сервер в тому ж середовищі, де працює PHP-застосунок, то він зможе прибрати всю цю затримку на створення та закриття зʼєднання:
- Коли встановлено з’єднання з проксі-сервером, проксі-сервер відкриває з’єднання з сервером rabbit, використовуючи облікові дані надані клієнтом.
- Потім трафік AMQP пересилається між клієнтом і сервером. Але коли клієнт від’єднується, проксі-сервер перехоплює команду закриття каналу та натомість зберігає його відкритим на вихідному сервері (якщо це вважається безпечним).
- Наступного разу, коли клієнт підключається (з тими самими обліковими даними), з’єднання з вищим сервером використовується повторно, тому не потрібно створювати пакети TCP для відкриття та узгодження з’єднання AMQP або відкриття та очікування відкриття каналу.
Як краще розгорнути проксі?
Краще деплоїти проксі якнайближче до самого застосунку. Детальніше це показано на зображенні. На схемі можна побачити, що в нас проксі розгорнутий в якості сайдкару до кожної репліки застосунку:
Отже, така коротка інструкція, якщо ви також хочете мінімізувати затримку і навантаження на мережу в вашому продукті. Буду радий почитати в коментарях ваші варіанти роботи з високим навантаженням (High Load) та забезпеченням високої доступності (High Availability).
Цей матеріал – не редакційний, це – особиста думка його автора. Редакція може не поділяти цю думку.
Сообщить об опечатке
Текст, который будет отправлен нашим редакторам: