10 известных масштабируемых архитектурных шаблонов

23 ноября 2011 12 комментариев Иван Блинков
10 известных масштабируемых архитектурных шаблонов

«Масштабируемость» — одна из самых трудно достижимых характеристик при построении архитектуры современных программных продуктов. Что не удивительно, ведь не существует единого рецепта масштабируемости, который работал бы для всех возможных сценариев. Как же быть?

Тем не менее, список наиболее распространенных рецептов или «шаблонов», применяемых на практике, вполне реалистичен. Пост написан на основе списка из статьи Srinath, помимо простого перевода названий я постараюсь своими словами изложить «на пальцах» в чем заключается каждый подход и с чем его едят. В оригинале можно найти ссылки на большие многостраничные работы на английском по практически каждому из шаблонов.

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

  1. Балансировщики нагрузки + не имеющие ничего общего исполнители: в данной модели существует некий входящий поток запросов или заявок, которые поступают через балансировщик(и) нагрузки на один из ряда равноправных узлов-исполнителей, которые каким-то образом генерируют результат запроса и отправляют обратно через балансировщик нагрузки или напрямую. В роли балансировщика нагрузки может использоваться DNS round-robin, различные программные или аппаратные решения, а также их комбинации (иерархии).
  2. Балансировщики нагрузки + узлы без состояний + масштабируемое хранилище: для большинства веб-приложений необходимо сохранять некое состояние, и тогда по сравнению с предыдущей моделью вводят в действие систему хранения данных, также приспособленную для горизонтального масштабирования, зачастую ценой отказа от реляционных и прочих комплексных операций, что сводит её интерфейс к простому взять-положить.
  3. Принцип «равный-равному» (P2P): заключается в самостоятельном распределении данных и/или задач между равнозначными узлами на основе заранее определенного алгоритма; причем клиент зачастую сам является узлом системы (BitTorrent), либо обращается к произвольному узлу, который становится «агентом» для поиска и делегации конкретного запроса исполнителю (Cassandra).
  4. Распределенные очереди: эта модель основывается на выделении очередей, как отдельных сетевых сервисов; используются либо для передачи произвольных данных между компонентами системы, либо для создания очереди выполнения длительных операций (например конвертации фото/видео/аудио).
  5. Парадигма подписка/публикация: в системе определяется набор типов событий, одни компоненты системы создают эти события (публикуют сообщения), а другие — хотят узнавать когда произошло событие определенного типа (подписка на сообщения) и каким-то образом реагировать; реализуется обычно в виде отдельного сетевого сервиса, иногда совмещенного с распределенными очередями.
  6. «Молва» и прочие похожие на жизнь архитектуры: основная идея заключается в том, что компонентам системы не нужно знать об общей структуре всей сети; узлу достаточно лишь знать о нескольких «соседях», с которыми он будет напрямую взаимодействовать, а распространение информации внутри системы возможно по принципу «молвы», то есть цепного распространения через «соседей»; используется, например, для развертывания кода или упрощения конфигурации в больших кластерах.
  7. MapReduce и потоки данных: изначально MapReduce был предложен Google для обработки огромных массивов данных, с которыми они сталкиваются, алгоритм вкратце следующий:
    • Каждый узел в системе считывает с дисков свою часть данных и образует из них пары «ключ-значение»;
    • Эти пары преобразуются в новые промежуточные пары «ключ-значение» по определенному алгоритму (стадия Map);
    • Промежуточные пары сортируются и группируются по ключу и для каждого ключа вычисляется новое значение на основе группы промежуточных значений (стадия Reduce);
    • Результат стадии Reduce обычно и является желаемой информацией, полученной из массива данных, и обычно сохраняется в распределенную файловую систему, либо каким-то образом импортируется в другое хранилище.
    MapReduce по сути лишь распространенный частный случай обработки потоков данных, который способен решить большую часть аналитических задач. В общем случае процесс обработки потоков данных может иметь любое количество этапов, преобразований и сортировок данных, необходимых для получения результата.
  8. Дерево ответственности: заключается в разложение общей задачи на подзадачи и рекурсивной делегации их выполнения другим узлам системы, что в итоге и образует дерево; используется как часть некоторых других моделей.
  9. Обработка входящих потоков: скорее класс задач, чем шаблон, но тем не менее… есть некие внешние события (например сбои в клиентском ПО), обладающие какими-то характеристиками, информация о которых постоянно и непрерывно поступает в систему, которая должна в реальном времени обрабатывать события и получать на основе этих данных требуемую информацию. Реализуется посредством сети обрабатывающих узлов с общем хранилищем информации.
  10. Масштабируемое хранилище: их можно рассматривать как отдельный субъект, обладающий свойством масштабируемости; по типам можно выделить базы данных (зачастую не структурированных) и файловые системы.
  11. Разделение ответственности запросов на чтение и на запись (СQRS): звучит страшно, на деле еще страшнее, если по-простому, то… модель основывается на обмене сообщениями между равноправными компонентами, хранении, обработке данных в оперативной памяти, асинхронном масштабируемом хранилище данных для их сохранности и репликации компонент для надежности и отказоустойчивости.

Хотелось бы обсудить в комментариях какие из перечисленных моделей Вы чаще всего используете на практике и почему? В чем видите перспективы, преимущества и недостатки каждого? Может быть вспомните еще шаблоны, которые не попали в список?

P.S.: Я недавно участвовал в сессии вопросов-ответов про высоконагруженные и не очень интернет проекты, возможно Вам будет интересно почитать.
  • Vadim Kantorov

    CQRS не очень удачно переведено. Там ведь смысл в том, что запросы на чтение (query) и запросы на запись (command) обрабатываются по-разному и с использованием разных моделей данных. Как-нибудь бы это подчеркнуть :)

    Например, «Сегрегация ответственности запросов _на чтение и на запись_»

    • http://www.insight-it.ru Ivan Blinkov

      Спасибо за поправку :)

  • Gleb Radchenko

    Спасибо, интересная подборка. Буду давать студентам на курсе распределенных вычислительных систем, вы не против?

    • http://www.insight-it.ru Ivan Blinkov

      Не против, конечно)

    • http://www.insight-it.ru Ivan Blinkov

      Кстати в каком ВУЗе преподаете, если не секрет?

      • Gleb Radchenko

        ЮУрГУ НИУ (Челябинск). Мы на факультете Вычислительной математики и информатики занимаемся распределенными вычислительными системами... На хорошем уровне :)  

    • http://joomlasecret.ru/ роман

      присоединяюсь к благодарности! сам разработчик и много чего почерпнул отсюда.  Заложил теорию на будущие проекты

  • http://twitter.com/man4j Vladimir Petrukhin

    Спасибо за пост. Начало неплохое. Если ещё потрудиться, то статья может перерасти в мини-справочник по высоконагруженным шаблонам. 

    К каждому пункту можно добавить ещё и популярные программные решения. Например если что-то связано с очередями — то RabbitMQ, HornetQ, ActiveMQ. Если с деревом отвественности — то это я так понимаю что-то типа организации иерархии процессов в эрланге. 

    Интересно, куда отнести грид решения? Наверное те решения, которые сочетают в себе DataGrid + ComputeGrid — это к пункту 3 (типа GridGain, Hazelcast, Infinispan, Coherence). А те гриды, которые только DataGrid — это к пункту 10 (gemfire, cacheonix). Хотя GridGain например подходит под все пункты, кроме 11 )))

    • http://www.insight-it.ru Ivan Blinkov

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

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

  • Pingback: Рубрика «Полезное чтиво». Выпуск 12 « XP Injection

  • Pingback: Статьи, не попавшие в ленту новостей (выпуск 155) | AllUNIX.ru — Всероссийский портал о UNIX-системах

  • Pingback: Статьи, не попавшие в ленту новостей (выпуск 155)