Azure Service Bus: неклассическое применение

    Azure Service Bus как Messaging System для «массовых» клиент-серверных приложений


    imageПриветствую вас, хабровчане!

    Перед тем, как расказать вам интересненького, позвольте для начала представиться. Мы — молодая компания, занимающаяся дистанционным обучением. В этом блоге мы будем делиться с вами нашими интересными находками, техническими хитростями и прочими вещами, которые, как мы считаем, должны быть достоянием сообщества.
    Дальше будет несколько слов о нас и, собственно, вынесенный в заглавие рассказ о неочевидном применении Azure Service Bus.

    Кто вы такие и что вы делаете?

    Когда-то совсем недавно образование касалось компьютера только на информатике, да и то не везде. С тех пор многое изменилось (у нас в стране – в меньшей степени, в Штатах, к примеру, – в большей): многие уже сейчас получают образование онлайн. Естественно, в новой области как грибы стали появляться програмные решения. И, как обычно это бывает, большая часть этих самописных систем предоставляла очень сильно ограниченый функционал. Такие системы используются до сих пор в разнообразных учебных заведениях. Потом в эту нишу стали подтягиваться крупные компании с серьезными решениями (например, Adobe), но вердикт учителей, которым приходится это использовать, звучит неутешительно. Им неудобно пользоваться существующими решениями.
    Наша компания на данном этапе разрабатывает одноименный продукт (PENXY), являющийся комплексной системой для онлайн обучения, причем как синхронного (похожего на вебинары), так и асинхронного (похожего на форумы, учебники, тестовые задания). Основной особенностью нашего подхода является то, что мы постоянно обсуждаем наши решения и идеи с преподавателями, стараясь максимизировать для них удобство использования системы. Ведь согласитесь, действительно качественное онлайн образование – это здорово!

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

    Хватит слов, давайте к делу!

    Наша система построена по клиент-серверной архитектуре с использованием облачных технологий. Соответственно, по ходу проектирования и разработки мы сталкивались с различными интересными проблемами и не менее интересными (а порой и довольно экстравагантными) решениями. Частью этих наблюдений мы бы хотели поделиться с хабром.

    Удивительным образом на хабре мало статей про Windows Azure (ну, за исключением общих обзоров и ежемесячных рассылок). Еще меньше затронута часть Azure под названием Service Bus. В общих чертах о том, что это такое, и зачем это нужно, можно прочитать в статьях Дэвида Чеппела. Например, на хабре, а именно тут и тут есть перевод обзорной статьи по Azure в 2 частях, в которой, в частности, описано применение Service Bus при построении корпоративных систем. Из нее может сложиться ощущение, что эта технология нужна лишь для того, чтобы связывать вместе части бизнес-решения, расположенные в облаке и на on-premise.

    Несмотря на то, что микрософтовский «независимый евангилист» Чеппел в своей статье рассматривает только указанное применение данной технологии, сейчас эта часть Azure имеет достаточно большой и удобный функционал Message Broker-a. С момента написания статьи произошло два изменения: Microsoft допилила функционал и сменила ценовую политику. Про функционал чуть позже, а сейчас ненадолго обратимся к ценам. Вообще, ценовая политика в отношении Service Bus, которую сначала проводила Майкрософт, очень сильно ограничивала область применения Service Bus: оплата производилась за каждое подключение к шине. В декабре ценовая политика была изменена, и теперь в Service Bus оплачивается каждая транзакция. Оплаты подключений нет, однако их количество ограничено. По сути, Service Bus теперь стоит столько же, сколько и Azure Storage. Более подробно о новом ценообразовании Service Bus можно прочитать на оффициальном сайте.

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

    Ура, картинки!



    Service Bus позиционируется как технология, позволяющая организовать взаимодействие между локальными приложениями и данными, находящимися за брандмауэром, приложениями в облаке, богатыми десктопными приложениями и приложениями на умных мобильных устройствах по всему миру.

    Основные свойства Service Bus:
    • Безопасно открывает доступ к внешним веб сервисам на базе WCF, которые закрыты брандмауэрами и NAT-роутерами, причем делает это без необходимости открывать какие-либо входящие порты или еще как либо перенастраивать брандмауэр или роутер.
    • Обеспечивает безопасные входящие соединения от устройств вне брандмауэра.
    • Предоставляет единое пространство имен, которое совершенно отвязано от географического положения. Это означает, что такой информации не содержится в имени сервиса.
    • Предоставляет механизмы публикации и поиска endpoint-ов в пространстве имен.
    • Предоставляет возможности пересылки сообщений. Поддерживается односторонний обмен сообщениями, обмен сообщениями по модели запрос/ответ и p2p взаимодействия.
    • Предоставляет функции брокера сообщений, в частности дает возможность асинхронного обмена сообщениями (отправитель и получатель сообщения не обязаны быть одновременно онлайн). Инфраструктура устроена таким образом, что сообщения надежно хранятся до тех пор, пока получатель не будет готов их принять.
    • Создает и обслуживает endpoint-ы сервисов, также допускает туннелирование между двумя endpoint-ами, позволяя двунаправленную передачу данных.


    Что мне было совершенно неочевидно, когда я начинал разбираться с Service Bus, так это то, насколько удобен Service Bus именно в роли брокера сообщений, причем в качестве источника сообщений могут быть как клиенты, находящиеся вне облака, так и роли в облаке. Давайте для примера рассмотрим чат и попробуем реализовать его на облаке.



    Все клиенты подключены к нашему серверу в облаке, один из клиентов отправляет сообщение, часть из клиентов получает сообщение (т.е. мы предполагаем разделение по комнатам). Но если бы все было так просто! Я сейчас не говорю даже про постоянные двунаправленные соединения, которые нужно поддерживать (чтобы клиентам не приходилось постоянно запрашивать у сервера, не пришло ли новых сообщений, хотя, конечно же, и такой подход тоже годится). Все дело в том, что для каждой роли в облаке создано несколько инстансов. С учетом того, что мы не контролируем то, к какому конкретно инстансу подключен каждый клиент, возникает необходимость передачи сообщений между инстансами в той или иной форме. Более того, с учетом того, что в одной комнате народу существенно больше, чем инстансов, автоматически получается, что на всех инстансах есть клиенты из данной комнаты. Т.е. получается, что каждый инстанс передает сообщения всем остальным инстансам. Это вполне естественный подход, более того, Майкрософт в своих лабах предлагает именно его. В результате получаем следующую картинку:



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



    Альтернативой является вообще использование Storage в качестве транзитной сущности между инстансами, но это не очень важно в рамках данной статьи. Вообще говоря, получилась достаточно сложная схема, которая предполагает использование Storage, несколько инстансов роли и не самое очевидное взаимодействие. Оказывается, нашу задачу в некоторых случаях можно решить существенно проще. Будем считать, что комнат у нас в чате менее 100 тысяч, в каждой комнате не более 100 человек, а комнаты заданы статично или редко меняются. Такие ограничения озвучены не случайно. Т.к. я планирую использовать в данном примере Service Bus и одно пространство имен, то и ограничения взяты соответственно.

    В новой схеме каждая комната в чате — это топик (специальная сущность, реализующая public subscribe подход) внутри Service Bus. Каждый клиент подключается напрямую к Service Bus, посылает сообщения в топик и получает сообщения по подписке. Выглядит это все примерно вот так:



    А что с безопасностью?

    Важно понимать, что если использовать простые очереди Service Bus или одну подписку на всех клиентов, то каждое сообщение в чате будет доставлено первому подсуетившемуся клиенту и все. Именно поэтому мы используем функционал топиков, а не очередей, и создаем по подписке на каждого клиента. К сожалению, этот подход тоже имеет свои минусы. Дело в том, что у Service Bus пока нет возможности получить security token, который позволил бы, к примеру, только отправлять и получать сообщения, но не позволил бы создавать и удалять топики. Т.е. если вы разрешаете клиенту работу с Service Bus, то он получает полный доступ со всеми вытекающими из этого рисками безопасности. Тем не менее, такое решение применяется и на практике, ведь при таком подходе вам не нужны никакие роли. В этом случае полномочия в том или ином виде либо хранятся на клиенте в зашифрованном виде, например в keychain в маках, либо их должен выдавать сервер в момент подключения клиента, естественно это предполагает безопасное соединение и работающую веброль. Вообще, даже если мы решим, что нам нужно обеспечить полную безопасность и будем использовать, к примеру, веброль для проксирования запросов к Service Bus (для того, чтобы спрятать от клиента этот токен), решение окажется все равно проще, ибо многие вопросы, например, управление комнатами, решаются при таком подходе существенно проще непосредственно возможностями Service Bus.
    Отдельно стоит отметить, что клиенту не обязательно быть .Net-based для того, чтобы взаимодействовать с ServiceBus. Вот, к примеру, ссылка на эту тему.

    На этом я хочу закончить этот небольшой обзор. Спасибо за внимание, буду благодарен замечаниям и предложениям по улучшению.

    Напоследок

    Ясно, что чтобы получить этот результат, вовсе не обязательно брать готовое решение, встроенное в Azure. Есть множество других способов добиться таких же (на первый взгляд) результатов. Вопрос как обычно заключается в специфике ваших задач и потребностей. Из возможных претендентов можно выделить:

    Low-lattency / High Throughput / in-RAM:
    • NoSQL хранилища/кэши с функционалом publish/subscribe — например redis (да-да, юниксовое хранилище вполне живет в Azure, правда со scaling-ом пока проблемы)
    • Реализации паттернов Complex Event Processing — например микрософтовский StreamInsight, умеющий не только перебрасывать данные но и производить подробную обработку сигналов в реал-тайме. (и таки да, это тоже скоро появиться в Azure)
    • ZeroMQ и прочие Messaging Queue Systems

    Guaranted Delivery / Redundant:
    • MSMQ
    • Всевозможные реализации паттерна Enterprise Service Bus (кроме рассмотренной азурной), работающие по принципу «отправил-забыл, не потеряется»

    Если хабру будет интересно, мы с удовольствием расскажем об опыте работы с подобными решениями и о тех подводных камнях, с которыми мы на данный момент уже успели познакомиться.
    PENXY
    22,88
    Компания
    Поделиться публикацией

    Комментарии 5

      0
      Отличный обзор, спасибо!

      >> Если, хабру будет интересно, мы с удовольствием расскажем об опыте работы с подобными решениями и о тех подводных камнях, с которыми мы на данный момент уже успели познакомиться.

      Было бы интересно узнать.
        0
        Без проблем. Мы сейчас общаемся с командой разработчиков StreamInsight. Это отличные ребята, частитчно из Microsoft Research — так что они вполне могут рассказать о подробностях устройства этой системы. Так что следующий пост напишем наверное об этом. Ну на хабре об этом почти ничего нет.
          0
          отлично, буду ждать
        0
        А что насчет Azure Tables Queue?
        Можно в кратце — в чем у них будут отличия с Service Bus?
          0
          По-порядку: Есть Azure Storage, который состоит из 3х сервисов: Tables (No-SQL таблицы), Queues («тупые» очереди) и BLOB (бинарные файлы).

          Если говорить про Azure Queue в сравнении с Azure ServiceBus Queue, то вот на msdn подробное сравнение: msdn.microsoft.com/en-us/library/windowsazure/hh767287(v=vs.103).aspx. Если кратко, то ServiceBus Queue умнее, гарантирует FIFO, но при этом имеет некоторые ограничения по размеру, количеству очередей и работает медленней, чем обычные Azure Queue.

          С другой стороны, просто очереди (даже умные от ServiceBus) такую простую задачу, как чат напрямую не решают, т.к. нет возможности простым способом доставить сообщение всем в комнате. Именно для этого использовался функционал топик-подписка плюс методы доставки, которые есть в ServiceBus, но нет в Azure Queue, да и вообще в Azure Storage.

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

        Самое читаемое