Начнем издалека. Допустим, у нас есть желание заиметь интернет-магазин. Предприниматель Вася заказал программисту Пете сделать ему сайт, где бы он мог торговать своими товарами. Петя, не долго думая, выбрал свой любимый LAMP (Linux/Apache/MySQL/PHP) и через месяц выдал архив с кодом и инструкцию по установке.
И это было очень хорошо. Пока магазин маленький и клиентов не очень много это самый лучший подход. Очень удобно устанавливать, обслуживать, обновлять. Не надо много программистов. Есть только один код на одном языке программирования, который делает все и требует простейшую инфраструктуру для запуска. Но магазин растет. Клиентов все больше. Начинаются проблемы с производительностью и отказоустойчивостью. Мы покупаем сервер покруче, но это вскоре перестает работать.
Первое, что приходит на ум в наши дни это заменить PHP, например, на Java, а MySQL, на какой-нибудь популярный NoSQL. Поставить много экземпляров приложения и закрыть это отказоустойчивой HTTP proxy. Теоретически, если все сделать правильно, это может помочь нам масштабироваться горизонтально. То есть мы нанимаем команду разработчиков и
переписываем приложение, "по модному":
SQL мы оставляем на схеме, так как NoSQL обычно решает проблемы с масштабированием упрощением функционала и поэтому эффективной операции JOIN не предоставляет. Это заставляет нас денормализовать данные. Но тогда нам очень сложно следить за правильностью данных, поэтому мы продолжаем хранить нормализованные данные в SQL, и вводим процедуру денормализации данных, в результате которой данные оптимизированные для чтения попадают в NoSQL базу данных и могут читаться быстрее.
На самом деле часто приложение у нас уже не одно, мы хотя бы разделяем часть, отвечающую за пользовательский интерфейс, и backend-приложение:
Это работает какое-то время, но как правило оказывается, что NoSQL это вовсе не серебряная пуля и он начинает не справляться. Для нашего примера причиной может быть то, что данные, которые мы обрабатываем, по своим характеристикам делятся на очень редко меняемые статические данные, где нам важно только быстро их отдавать (описание продукта, его фотографии), сравнительно редко меняемые данные (цена, скидки, промо-акции), очень часто меняемые данные (наличие на складе), которые важно быстро писать и читать, но при этом они не очень объемны. Поэтому один и то же NoSQL не может одинаково хорошо обрабатывать все типы запросов и на понадобится какое более специализированное решение для разного типа данных. Например для небольшого количества часто меняемых и запрашиваемых данных мы поставим отдельную NoSQL базу данных, которая будет все хранить в памяти. Я назову этот новый компонент "In-Memory Storage".
Как видим наше приложение растет, усложняется. Вместе с ним растет и наша команда разработчиков. Чтобы справиться с нарастающей сложностью приложений, мы делим наш код на несколько проектов, а разработчиков на несколько команд. И вот на этом интересном этапе есть несколько тонких моментов.
Момент первый, это то, как именно мы делим команды. Часто деление выглядит, как несколько групп разработчиков (по числу приложений), отдельная группа "архитекторов", которые диктуют, что и как писать, отдельная группа по тестированию (одна группа тестирует все приложения), отдельная группа, которая устанавливает и обслуживает приложение в "продакшен", отдельная группа, которая следит за документацией, диктует стандарты, редактирует тексты. Так вот в этом случае говорить о сервисах не приходится. Все продолжает быть сильно централизованным. Как правило все группы синхронизируются одним и тем же менеджментом, у них один цикл релизов и все очень централизовано.
Другой подход, который мне нравится больше, это независимые группы, каждая со своим архитектором, менеджментом, QA, циклом релизов, подходом к созданию документации, которые должны оказывать сервис другим командам. Они сами решают, как им устанавливать приложение, как оказывать поддержку и насколько полной должна быть документация по их приложению. Нужно ли создавать отдельные утилиты для поддержки приложения или для разработки с его помощью. Это дает гибкость проектам, и делает людей более мотивированными, поскольку они могут работать творчески не испытывая столь сильного давления со стороны. Это еще и более эффективно, так как эта команда будет более погружена в нужды своего сервиса и будет сильно сфокусирована в мыслях только на нем, вместо распыления усилий архитекторов на кучи приложений, которыми им приходится заниматься.
Момент второй, это то, как мы делим приложение на части. Его можно делить по схожим областям, например приложение "каталог товаров", приложение по обработке информации о пользователях, приложение по обработке специальных акций и т. п. Это довольно очевидно и многие так и делают. Но есть и второй путь. Делить приложения по типу обрабатываемых данных: приложение для хранения статических данных, приложение для хранения часто изменяемых данных, приложение для полнотекстовой индексации и т. п.
Почему второй путь очень важен, так это потому, что в одной и той же области могут быть данные разных типов и приложения поделенные по предметным областям легко превращаются в огромных монстров. Для их написания нужны специалисты разного профиля. Их становится сложнее поддерживать. Тогда как приложения по обработке данных с известными характеристиками написать проще и проще их обслуживать и поддерживать в дальнейшем. К тому же, если сервис получиться достаточно общим и эффективным, то можно начать его использовать так, как изначально не предполагалось.
Помня о вышесказанном, мы будем умными и создадим 3 независимые команды: для статических данных каталога товаров, для динамических данных по доступности товаров на складе и команду, которая будет пользоваться этими двумя сервисами, чтобы суммировать информацию полученную от них. На самом деле NoSQL и SQL можно считать тоже сервисами предоставляемыми другими командами и команд у нас будет больше ("готовый" NoSQL может обслуживать команда администраторов без программистов и это тоже будет сервисом для других команд или команда программистов может предоставлять сервис по автоматической установке и обслуживанию баз данных и тут мы уже начинаем говорить о облаках для разработчиков).
Обратите внимание, что на этой картинке уже не сам сервис занимается трансформацией статических данных о товарах из SQL в NoSQL, а команда которая его пишет, решила вынести это код в отдельное приложение для администраторов и это приложение тоже является частью их сервиса.
Теперь поглядим еще раз на нашу архитектуру и увидим, что у нас есть лишнее сетевое взаимодействие (от интеграционного приложения к приложениям по хранению данных одного типа и от тех к базам данных). Это совсем не обязательно, если понимать, что сервис не обязан быть отдельным приложением с сетевым API. Сервис может быть набором тулов, библиотек и документации. Библиотеки могут быть встроены в интеграционное приложение. Тогда мы получим следующую схему:
Настоящие приложения конечно гораздо сложнее. Они состоят из большего числа разных сервисов разных типов для обработки данных с совершенно различными свойствами.
Существует много готовых сервисов для обработки совершенно различных данных от временных статических данных, до обработки и хранения видео и изображений. Это и облачные сервисы от Amazon, и сервисы от Google (Google Cloud), и Heroku, и другие облачные провайдеры. Такие сервисы строят компании у себя, если не хотят пользоваться публичными по разным причинам.
Итоги:
- Большие и сложные приложения удобно разбивать на сервисы.
- Лучше, если сервис от начала до конца проектирует, реализует и обслуживает отдельная команда со своим менеджментом, бюджетом, разработчиками и т. д.
- Лучше делить сервисы по типу обрабатываемых данных и типичным операциям, а не по доменным областям, которые они должны обслуживать.
- Сервис это не обязательно отдельно стоящее приложение, а может быть набором утилит, приложений, библиотек и документации в любых сочетаниях.
- Хороший сервис обязательно включает в себя утилиты для обслуживания и документацию.
- Если есть возможность, то можно делать общие сервисы широкого профиля, которые будут использованы множеством других сервисов в будущем.
Комментариев нет:
Отправить комментарий