Главная > Open Source, PHP, web2.0, веб-обзоры, Высокопроизводительная архитектура, Разное > Очереди сообщений — современный тренд в области веб-приложений.

Очереди сообщений — современный тренд в области веб-приложений.

24 августа 2010

Приветствую своих читателей. К сожалению, сейчас нет времени и возможности написать полноценный пост. Сейчас я погружаюсь все дальше и дальше в тему очередей сообщений, как раз пробуем распараллелить обработку сложных вычислений в одном  проекте, в другой - оптимизировать сбор и обработку данных из множества провайдеров. В процессе изысканий появилось множество мыслей на счет идеальной системы MQ для построения веб-приложений, но это тема отдельной интересной статьи. Сегодня же хочу поделиться рядом интересных презентаций, найденных на slideshare и посвященных этой теме.

The Art of Message Queues - для тех, кто хочет вообще понять, о чем речь, когда говорят про сообщения, очереди и брокеры. Хорошее введение в тему.
[slideshare id=4182369&doc=art-of-message-queues-100520171613-phpapp02]

Amqp Basic - хорошее введение в индустриальный стандарт, протокол AMQP. Однако мое мнение - он достаточно сложен (есть несколько редакций стандарта, разные сервера поддерживают свои стандарты, сама спецификация достаточно объемная).
[slideshare id=4023592&doc=amqpbasic-12733899503195-phpapp02]

High gear PHP with Gearman - использование сервера Gearmand в РНР приложениях. Gearman не совсем очередь сообщений, это скорее очередь работ (Job Server), и наверное сама близкая к вебу система. Кстати, мы ее используем для обработки RSS фидов.
[slideshare id=4099218&doc=gearmanphpday-100514132333-phpapp02]

RestMQ - HTTP/Redis based Message Queue - отличное решение на базе NoSQL бд Redis, готовая система для внедрения в любое приложение, жаль немного, что на Python.
[slideshare id=5026692&doc=restmq-100821153418-phpapp02]

Q4M - a high-performance message queue for MySQL - как при помощи специализированного движка превратить вашу MySQL базу данных в очередь сообщений. Добавим сюда Sphinx и получаем MySQL как комплексное решение, включающее в себя все, что необходимо для построения инфраструктуры веб-приложения.
[slideshare id=430087&doc=q4m-study-1211879346714168-8]

PgQ Generic high-performance queue for PostgreSQL - а это, если вы поклонник PostgreSQL.
[slideshare id=1863986&doc=skype55pgq-090814172722-phpapp01]

Using Message Queues in Day-to-Day Projects (Zend_Queue) - отличное решение, используем в одном проекте, к тому же, благодаря компании Geometria lab мы имеем адаптер и для Redis (хорошо бы протестировать производительность).
[slideshare id=3708288&doc=09zendqueue-100413064150-phpapp01]

Message Queues in Ruby - An Overview
[slideshare id=3521742&doc=messagequeues-100323060902-phpapp02]

Job Queue - web is more than request and response
[slideshare id=3829484&doc=abhinavlaljobqueue-100423070453-phpapp01]

Message Queues for Web Applications
[slideshare id=1567268&doc=messagequeues-090611064000-phpapp01]

RabbitMQ + CouchDB = Awesome
[slideshare id=2223826&doc=one-system-to-rule-them-all-091014153738-phpapp02]

  • Спасибо большое, очень интересная подборка! Про герман презентации были весьма интересны.

    Все эти варианты хороши для случая когда сервер сообщений находится в одной локальной сети. В таком случае коннект будет очень дешевой операцией, не тормозящей выполнение скрипта.
    Но что делать если нужно асинхронно передавать сообщения на удаленный сервер, к которому и коннектиться долго да и недосутпен он изредка бывает. Понятно что делать connect из кода, не разумно.
    Логика два варианта:
    1) Буфиризировать сообщения в памяти/ файлах/БД и отдельным демоном перекидывать их на удаленный сервер. Работать будет быстро, но придется поддерживать два разных API (локальное сохранение и работа с сервером сообщений)
    2) Что бы работать с универсальным API, на каждом физическом сервере поставить выбранный сервер сообщений (будь то герман или RabbitMQ) и опять же отдельным демоном собирать сообщения из локальных серверов и отправль их на удаленный.

    И в том и в другом случае придется писать какой то демон, который будет периодически передавать сообщения на удаленный сервер… конечно не проблема. Но пятой точкой чувствую, что ситуация очень типичная. Сложно поверить что для случай «каждый раз конектиться к серверу сообщений слишком долго», весьма типичен и сложно поверить что нет сложившегося патерна… но пока не нашел 🙂

  • И вопрос который тоже меня всегда мучил — обработка ошибок. Хорошо когда давно все отлажено и код воркера безгрешен. Но что делать с ситуациями когда данные одного конкретного таска вызывают ошибку? Причем когда мы говорим о PHP try / catch не поможет, воркер может просто вылетить.
    Как обрабатывать таск в таком случае?

    Игнорировать ошибку и игнорировать таск? Но в таком случае пока будет исправленна ошибка в коде — огроиное количество тасков может простой пропасть.

    Пробовать выполнять такс снова и снова? Тоже не вариант, часто бывает что только 5-10% приводят к ошибке и стопорить остальные 90% не разумно.

    В своей доморощенной реализации мы храним задания в базе и для каждого задания, уже на этапа получения инкрмируем счетчик. При получение новых тасков первыми идут с наименьшим количеством получений. То есть таск с проблемными данными всегда оказываются в конце очереди. Для меня это кажется вполне разумным решением, однако опять же удивляется что в устоявшихся решениях этот вопрос не очень освещают.
    Надо посмотреть тот же герман еще раз, но такое ощущение что если таск вызвал ошибку, то он просто пропадает. Или я ошибаюсь?

  • @developcenter
    Спасибо за комментарии, постараюсь ответить по порядку.

    Для таких случаев можно использовать или HTTP (REST или другие варианты), или же репликацию, возложив заботу о доставке через нестабильную среду на другой софт. Например, как вариант, репликация Redis-а как вариант синхронизации очередей сообщений которые должны быть переданы и уже локальный скрипт который загружает их на удаленном сервере.

    Например, Dropr как раз был создан для таких случаев.

  • @developcenter
    На счет ошибочных тасков — смотря от задачи. Можно игнорировать — тогда воркер берет задачу, она изымается из очереди и все. Либо, как в Zend_Queue, воркер берет задачу, она уходит в инвизиб и недоступна другим воркерам. Если задача успешно обработана, воркер удаляет ее из очереди. Если код падает, допустим, по сегфолту, задача по истечению таймаута снова доступна другим воркерам.

    В случае, если точно известно, что есть задачи с падениями, можно сделать несколько очередей. Воркер берет задачу, помещает ее сразу в другую очередь. Если упал, задача осталась в отдельной очереди и так можно отследить такие, которые вызывают падение, например, добавив счетчик в само сообщение.

    Замечу, кстати, что нельзя ставить знак равенства между очередями сообщений и очередями работ (Job Queue), это никак не одно и то же, и вот как раз Gearman это скорее Job queue сервер. Конечно, JQ всегда включает в себя MQ. По этой теме я еще напишу отдельную статью, видимо актуально.

    И в заключение, я тут пришел к мысли (в который раз), что меня не устраивают по разным причинам все (большинство) текущих решений из области MQ, и есть задумка написать свою реализацию — совместно со стандартном на протокол (JSON), а также интерфейсы доступа (TCP, websocket). Как считаете, такое необходимо? MQ специально для веб-приложений и легковесных распределенных систем

  • @aleks_raiden

    HTTP как раз сейчас и используем. Совершенно не радует, потому что этот велосипед нужно поддерживать. Хочется именно возложить это на сторонний софт.Идея с репликацией здравая, но в условиях когда серверов много и все они должны чтото передавать на главный кластер, не понятно как именно это реализовать. Для каждого удаленного сервера поднимать инстенс какого то софта и делать Master-Master репликацию? Думаю не вариант.

    Только что подумал, что было бы забавно организовать репликацию на основе файлов и rsync, но думаю что в реально жизни эффективность будет крайне низкая.

    А вот за Droper большое спасибо! Уже смотрел его мельком, но как то не рассматривал всерьез. А тут почитал их сайт и понял что у создателей очень похожая с нами ситуация. Видимо все равно придется пилить чтото свое и скорее всего Droper допилить будет проще всего.

  • Ну а почему все же прямое соединение не рассматриваете? если перебои связи — просто постоянный реконект пока не установиться. То есть что-то вроде веб-сокетов, теперь их почти во всех языках есть полно. Но тут выбор решения очень сильно зависит от особенностей проекта — у меня сейчас два проекта с кардинально разными требованиями например.

  • aleks_raiden :
    Ну а почему все же прямое соединение не рассматриваете?

    Смотря для чего. Если вы говорите а том что бы скрипт на сервере А напрямую конектился скажем к серверу Б где стоит RabbitMQ, то все это чудно работает пока оба сервера в приделах LAN. Если А и Б находятся в разных ДЦ, то время коннекта будет уже ощутимо. И что хуже, в наших реалиях, процент случаев когда Б будет не доступен, достаточно высок что бы это было проблемой. Следовательно, мы сразу приходим к варианту когда проще кешировать сообщения локально, и отдельным процессом передавать их на Б.

    И вот для этого отдельного процесса, являющегося связующим звеном между А и Б, конечно лучше использовать постоянный коннект. Но как я уже сказал, я всеми силами хочу избежать лишнего кода, если можно взять уже чтото готовое 🙂

    Что касается вашего второго сообщения, то с нетерпением жду статью о JQ != MQ.
    А вот что касается создания собственного сервера, то у меня несколько консервативная точка зрения на это. Мое имхо, что каждая написанная строчка кода, не только приносит пользу, но и требует ресурсов на создание, и что хуже, на поддержку. Поэтому надо просто смотреть, какое КПД будет у вашего решения, а точнее сколько пользы он принесет проектам. В нашем случае очереди это просто один из служебных кирпичиков и дешевле прогнуться под одно из существующих MQ решений, чем писать свое. Если у вас все сплошь и рядом на очередях, то может смысл и имеет.

    В одном соглашусь точно, из того что можно использовать на PHP, не одно из решений меня не радует. Но тут может лучше платформу поменять 🙂

Developers.org.ua