Компания
56,67
рейтинг
8 апреля 2013 в 15:16

Разработка → Архитектура высоконагруженной системы Диадок

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

Пару слов вкратце о системе: для чего она предназначена. Чтобы было сразу понятно, что это такое, представьте web-интерфейс для почты, но это не совсем почта, точнее, совсем не почта. Данная система предназначена для обмена документами. Основные документы – это счета-фактуры и накладные. При этом электронные документы являются юридически значимыми, имеют такую же силу, как и бумажные документы с печатями и подписями.

Обмен электронными документами в России только начинает развиваться, и в не столь далеком будущем, вероятно, все счета-фактуры будут передаваться в электронном виде. Ежегодно в России создается 12 миллиардов счетов-фактур. Это в среднем 380 документов в секунду, а при пиковой нагрузке – тысячи документов в секунду. Любой проект, который нацелен на предоставление услуг по обмену электронными документами, должен рассчитывать на такие объемы и создавать соответствующую архитектуру.

Поподробнее о Диадоке с точки зрения бизнеса и бухгалтерии можно узнать на сайте Диадока, а здесь далее пойдут технические подробности.

Платформа

ОС: Windows, Linux
Язык: C#, .Net 4.0
Очередь сообщений: RabbitMQ
Хранилища данных: Cassandra, MySQL, Berkeley DB, Kanso (собственная разработка)
Протоколы: Thrift, Protocol Buffers
Кэширование в памяти: Redis
MVC: ASP.NET MVC, Razor (только для админки)
Балансировка нагрузки: Nginx.

Архитектура

Система является сервис-ориентированной (SOA). Основной формат данных для взаимодействия – Protocol Buffers от компании Google, позволяющий эффективно обмениваться данными между сервисами. Протокол взаимодействия – HTTP. При этом для публикации сервисов используется не IIS, а собственная реализация HTTP-обработчика. IIS используется только для web-интерфейса системы.
В схеме развертывания содержится список exe-файлов, которые вообще есть в системе, и при выкладывании на рабочую площадку определяется, какие сервисы на каком сервере будут работать. Если какой-либо компоненте требуется подключиться к какому-либо сервису, то происходит случайный выбор из работающих реплик сервиса и выполняется подключение.

Cassandra

Cassandra используется в основном для ведения логов благодаря высокой скорости записи данных, но последнее время применяется и для других целей, например, если нужно хранить персистентно ключ-значение. Нельзя сказать, что это идеальное key-value хранилище, но мы с ним научились работать. Для взаимодействия с Cassandra используется упомянутый протокол Thrift. Thrift – это аналог Protocol Buffers, разработанный компанией Facebook, находящийся сейчас под опекой Apache Software Foundation.

Kanso

Собственная разработка отказоустойчивого и распределенного хранения данных. По функциональности чем-то напоминает файловую систему, но с жестким ограничением: записывать в файл можно только в конец. То, что уже записано, изменить нельзя. Такое ограничение увеличивает объем данных, но гарантирует, что никакие данные не пропадут.

MySQL

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

RabbitMQ

Этот сервис сообщений показал себя достаточно хорошо и используется для асинхронной обработки событий. Сообщения имеют ограниченный срок хранения и через несколько дней удаляются из очереди. Сюда мы, как и в http-сервисы, передаем структуры на основе Protocol Buffers.

Кэширование данных

Для кэширования данных и быстрого поиска информации используется Redis, а также целая группа сервисов на .net, которые при запуске читают данные из Kanso и записывают в свою локальную базу Berkeley DB.

Интеграция

Для публичного API также используется Protocol Buffers, но при этом есть возможность взаимодействовать через OLE Automation. Многие крупные компании сталкиваются с проблемами автоматизации интеграции, и разработчики Диадока помогают интегрировать проект с другими системами. Очень часто из внешних систем невозможно выгружать данные в XML или другом машиночитаемом формате, и мы вынуждены конвертировать данные из печатных форм (PDF) в наш формат.
Подробнее об интеграции см.:
https://diadoc.kontur.ru/sdk/IntegrationOptions.html
https://diadoc.kontur.ru/sdk/

Принципы разработки

  • Очень часто используется парное программирование.
  • Обязательный Code Review.
  • Двухнедельное планирование итераций.
  • Ежедневное совещание всей команды о текущем состоянии дел (Stand-up meeting).
  • Прозрачность информации о состоянии проекта как с точки зрения маркетинга, так и с точки зрения разработки.

Инструменты разработки

  • Visual Studio 2012
  • Resharper
  • TeamCity для Continuous Integration
  • YouTrack в качестве issue tracker

Статистика

Количество программистов: 24
Количество серверов: ~40
Среднее время доставки документа: 7 сек
Зарегистрированных организаций: ~160 000

Автор: @trurl123

Комментарии (21)

  • +2
    Хоть и земляки, но не удержусь — за такое Api надо отрезать кое-что. У вас вроде даже IoC контейнер свой есть, а вот нормальный REST Api не осилили. Точнее у вас обычный RPC. Как у вас отличаются операции создания, изменения и частичного изменения?
    • 0
      Вообще-то, если посмотреть документацию diadoc.kontur.ru/sdk/, то можно убедиться, что применяются принципы REST. А то, что некоторые операции делаются в одной не считаю критичной проблемой.
      • +2
        /ParseAcceptanceCertificateSellerTitleXml — это совершенно не REST =) У вас обычный XML RPC. От REST там нет ровным счетом ничего.

        Вот хорошее видео по REST Api: www.youtube.com/watch?v=hdSrT4yjS1g.
        • 0
          Укажите, тогда какой принцип REST здесь нарушается? ru.wikipedia.org/wiki/REST
          • +3
            en.wikipedia.org/wiki/HATEOAS

            Из Википедии:

            Антиподом REST является подход, основанный на вызове удаленных процедур (Remote Procedure Call — RPC). Подход RPC позволяет использовать небольшое количество сетевых ресурсов с большим количеством методов и сложным протоколом. При подходе REST количество методов и сложность протокола строго ограничены, из-за чего количество отдельных ресурсов может быть большим.

            • 0
              В случае Диадока у нас как раз большое количество сетевых ресурсов, т.е. согласно REST.
              • +2
                ParseAcceptanceCertificateSellerTitleXml — не ресурс (документ), а операция.
                • –1
                  diadoc.kontur.ru/sdk/ParseAcceptanceCertificateSellerTitleXml.html
                  Это ресурс, который соответствует понятию REST, у него есть URL. См. en.wikipedia.org/wiki/Web_resource
                  • +2
                    Он был бы REST, если бы:
                    1. У вас был ресурс AcceptanceCertificateSellerTitle. (Без Xml!). Допустим коллекция этих ресурсов по URL: www.diadoc.ru/api/v1/AcceptanceCertificateSellerTitles
                    2. У этого ресурса можно было бы сделать POST для создания нового тайтла и в ответ получить Created и ссылку где он находится вида: www.diadoc.ru/api/v1/AcceptanceCertificateSellerTitles/{mytitle}

                    То, что вам приехал XML вы должны были взять например из ContentType.
                    • –1
                      Где это написано в спецификации REST?
                      • +2
                        Вы специально пропускаете ссылку про HATEOAS. У вас операция, не ресурс. В чем разница между /GetUserName и /users/vasyapupkin/name?

                        PS Спасибо за минуса.
                        • –1
                          Я минусы не ставил, видимо, кто-то другой постарался. На самом деле, формат URL у ресурсов может быть разным и не обязательно таким, как вам хочется.
                          • +4
                            Как раз формат очень важен. Именно за счет формата можно всегда однозначно написать /users/vasyapupkin/groups если ресурс user может содержать ресурсы типа groups.

                            С вероятностью процентов 90% у вас используются ASP.NET MVC контроллеры для этой задачи. Они не очень хорошо предназначены для этого и на них проще как раз делать обычный RPC(такой подход например используется в TFS 2012).
                            Если вы возьмете WebApi, то по дефолту там у контроллеру увидите не Parse, Update и тд, а GET, POST, PUT, DELETE. Это типы действий которые вы можете произвести над ресурсом. Причем PUT например должен быть идемпотентным.

                            В видео, которое я приводил выше, очень хорошо рассказано про то, как создать грамотный REST Api.
                            Вот ссылка на их описание Api: www.stormpath.com/docs/rest/api
                          • +1
                            Просто оставлю это здесь — en.wikipedia.org/wiki/Representational_state_transfer#RESTful_web_APIs
                            • –1
                              Все-таки нужно понимать разницу между «Tipicaly used» и «Mandatory»
                        • –4
                          И насчет HATEOAS тоже у программиста может быть выбор — использовать это или нет. Да, Диадок не похож на Твиттер, но это не значит, что нужно их ругать.
                          • +4
                            Тогда это обычный XML RPC over HTTP. И называть его REST не корректно.
  • +3
    Как-то вроде и всё рассказали, но в то же время слишком кратко и сухо. Например хотелось бы больше про использование кассандры. Мы вот тоже используем кассандру в продакшене. Хочется послушать про возникшие проблемы и способы их решения.
    • +1
      Наверное, это тем для отдельной статьи
  • +10
    Честно говоря ожидал больше подробностей, чем просто список используемых на проекте технологий. Все-таки под словом «архитектура» подразумевается нечто большее.
  • 0
    Спасибо что поделились.

    Любой рассказ о высокой нагрузке должен сопровождаться тем, какую нагрузку УЖЕ выдерживает система на тестах ли или живых пользователях. На что вы рассчитываете в теории совершенно не важно. Потому что под реальной нагрузкой, так или иначе ложились, пожалуй, все крупные проекты, хотя они тоже что-то там оценивали и планировали.

    Картина dataflow из вышего описания выглядит несколько лоскутной.

    И у меня небольшой вопрос, какие у вас максимальные размеры документа? Как внутри системы гоните блобы, через буферы или отдельно?

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

Самое читаемое Разработка