Доклад об очередях сообщений / задач, прочитанный на конференции YAPC::Russia 2015, в котором описываются методы построения очередей и принципы протокола AMQP
2. Генерация уменьшенных картинок
● Клиент загружает изображения и уведомляет клиент об
успехе
● Сервер генерирует уменьшенные копии и раскладывает их
в нужные папки
● Заходящие пользователи видят предпросмотр для картинок
3. «Бонусы» при покупке сервисов
● К домену прилагается N «стандартных» почтовых ящиков
– клиент создает их сам при необходимости
● При покупке хостинга квота на ящик увеличивается
● Нужно обойти все созданные ранее ящики и увеличить им квоту
– это долго
– не относится напрямую к покупке хостинга
● Чтобы дать клиенту воспользовать хостингом как можно быстрее:
– создаем только хостинг и уведомляем об успехе
– задачу по изменению квоты почтовых ящиков передаем другому процессу
4. Очередь задач (сообщений)
● Передача сообщения от одного процесса другому
(возможно, находящемуся на другом сервере)
● Задачи обычно хранятся недолго
● Процедуры «положить» и «взять» задачу из очереди
должны выполняться быстро
● Простота расширения и конфигурации
● Надежность систем передачи и хранения
6. Свободные решения
● Queue::DBI — бэкенды, поддерживаемые DBI
● Minion — поддержка разных бэкендов (SQL, MongoDB,
файлы, write your own!)
● Resque, Queue::Q — Redis backend
● ZeroMQ — собственный бэкенд и протокол
● RabbitMQ (и десятки других) — протокол AMQP
7. AMQP
● Разработка начата в 2003г. John O'Hara из JPMorgan Chase Bank
● Цель: создать свободную реализацию протокола обмена сообщениями,
который можно использовать в критически важных банковских задачах
● Определяет как формат передачи данных, так и поведение клиентского и
серверного ПО
● Имеет множество реализаций на разных языках:
– OpenAMQ
– RabbitMQ
– Apache Qpid
– Red Hat Enterprise MRG
8.
9. Сообщения
● Содержат некоторые данные
– заголовок, содержащий набор свойств сообщения
– тело — содержимое сообщения, бинарные данные
● Могут храниться постоянно или временно
– постоянные хранятся на диске и восстанавливаются после
рестарта системы
● Могут иметь разный приоритет
– поэтому очередь сообщений называют «слабой очередью»
10. Поставщики и потребители сообщений
● Поставщик отправляет сообщения в обменник
– может ждать или не ждать подтверждения получения
●
Потребитель может:
– просто «слушать» определенную очередь
– создавать или уничтожать очереди
– определять правила заполнения очередей
– выбирать разные обменники, полностью меняя маршрутизацию сообщений
внутри системы
– указывать, сколько сообщений он может обработать (QoS)
– подтверждать обработку сообщения или отказывать в его обработке
11. Очередь сообщений (Message Queue)
● Именованный FIFO буфер, хранящий сообщения по запросу
приложения-потребителя
● Хранит сообщения в памяти или на диске и доставляет их к
одному или нескольким потребителям
– одно сообщение из очереди может получить только один потребитель
● Свойства:
– частные или общие
– постоянные, временные, автоматически удаляемые
– созданные клиентом или сервером
12. Обменник (Exchange)
● Получает сообщения от поставщика (producer)
● Направляет их в очередь(и) или в другой обменник в
соответствии с заданными критериями и параметрами сообщений:
– заголовки сообщения
● routing_key
– содержимое
● Может отправить одно сообщение в несколько очередей
● Как и очередь, может быть постоянным, временным,
автоматически удаляемым
13. Direct exchange
● Очередь «привязывается» к обменнику по ключу K
● Поставщик отправляет сообщение с ключом R
● Сообщение передается в очередь если K == R
● По умолчанию, все сообщения привязаны к безымянному
обменнику, использующему имя очереди как routing_key
14.
15. Fanout exchange
● Очередь привязывается к обменнику без аргументов
● Поставщик отправляет сообщение в обменник
● Сообщение передается в очередь сообщений безо всяких
условий (то есть сообщение передается во все очереди,
привязанные к обменнику)
16.
17. Topic exchange
● Очередь привязывается к обменнику с шаблоном
маршрутизации P
– шаблон: 0 или более слов ([A-Za-z0-9]+), разделенных точками
– * матчится с целым словом
– # - 0 или более слов
● Поставщик отправляет сообщение с ключом R
● Сообщение передается в очередь, если R соответствует P
18. Headers exchange
● При привязке очереди к обменнику передается таблица
аргументов с заголовками, которые должно иметь
сообщение для попадания в эту очередь (и опционально их
значения). routing_key не используется.
● Поставщик отправляет сообщение с заголовками,
содержащими таблицу имен и значений.
● Если заголовки сообщения совпадают с требуемыми, оно
попадает в очередь.
20. Logging system
● Отправитель шлет сообщения, где routing_key имеет вид:
<facility>.<severity>
● Получатели принимают только нужные им сообщения (от
нужных приложений либо с нужной «важностью») и
выполняют некоторые действия, например:
– отображают на экране
– сохраняют на диск
– шлют по e-mail
21. # producer.pl
use Net::RabbitFoot;
my $connection = Net::RabbitFoot new load_xml_spec→ → →
>connect(%connect_arg);
my $channel = $connection>open_channel();
$channel>declare_exchange(exchange => 'topic_logs',
type => 'topic');
# Routing key: <facility>.<severity>
my $routing_key = shift || 'anonymous.info';
my $message = shift || 'Hello, World!';
$channel>publish(
exchange => 'topic_logs',
routing_key => $routing_key,
body => $message,
);
say "Send $routing_key:$message";
$connection>close;
24. ● ./consumer.pl *.error
● system.error: System error
occured
● player.error: Player could
not play
● ./consumer.pl player.info
● player.info: Player is
playing Counter-Strike
● ./consumer.pl '#'
● system.error: System error occured
● player.error: Player could not play
● player.info: Player is playing
Counter-Strike
Использование
● ./producer.pl system.error "System error occured"
● ./producer.pl player.error "Player could not play
● ./producer.pl player.info "Player is playing Counter-Strike"
25. Деплой
● Самое трудное — убедить всех, что это нужно
● Непривычно, что все приходится создавать программно
– не забывать писать тесты для архитектуры