По причинам создания и описанием всех “за” и “против” написано уже сотни статей — здесь же я расскажу про практическую сторону создания и использования.
Итак, после долгих раздумий вы решились сделать сиё чудо, может, потому что у вас подвернулась на проекте задача, удачно подходящая под микросервисный подход или все вокруг уже написали по-несколько, а вы ещё ни одного.
Статья не акцентирует внимание на том, как писать микросервисы, у каждого свои методы, здесь я расскажу в общих чертах про этапы разработки и доставки сервиса на продакшн и тест.
Я разделил процесс создания на этапы. И вот первый из них:
1. Задача
Для начала определяемся какие задачи будет решать микросервис. Обычно — это доступ к какому-либо ресурсу на сервере (база данных, очереди или же файловая система) с небольшой логикой на самом сервисе.
Предположим, нам нужно реализовать отдачу данных для отображения на карте из медленного хранилища. Саму отрисовку будет делать, естественно, клиент микросервиса. Данные представляют координаты точек на карте с каким-то заголовком.
2. Технологии
Задача есть, теперь определяемся с технологиями её решения. Хранилище данных медленное и не справится с большим потоком запросов. В таких случаях можно использовать elasticsearch — он отлично справляется с большими нагрузками и умеет шардироваться и реплицироваться из коробки. Положим в него данные отдельным скриптом для последующего поиска по ним.
Так как в нашей компании «Колеса Крыша Маркет» принято писать микросервисы на Go, и у меня есть опыт написания на Go, то принято решение писать на Go. В вашем случае это может быть что угодно — Nodejs, Java, PHP или любой другой, желательно, компилируемый язык. Так как стек технологий зависит и от архитектуры сервиса, то на этом этапе нужно подумать о ней, а также продумать логику работы. Здесь стоит собрать инфу со всех клиентов которые будут использовать наш микросервис, в частности с команды мобильной разработки, если таковая имеется.
3. Кодирование
После всех раздумий на счёт стека технологии и архитектуры, логики работы сервиса приступаем непосредственно к кодированию. Определяемся будем ли мы писать кодовую базу с нуля (не рекомендую) или заюзаем какой-то готовый фреймворк.
Подключаем все зависимости в main.go, и в этом же файле описываем обработку всех публичных методов.
Помимо основных методов сервиса описываем специальный метод stats, который по http будет возвращать сервисную информацию: версию микросервиса, количество и коды обработанных запросов, а так же дату запуска — будет использоваться в сервисных целях и в частности для healthcheck. Для того чтобы можно было запускать микросервис в разных окружениях (разработки, тестирования, продакшена) нужно создать конфиги под каждое окружение.
4. Документация
После написания основной части кода приступаем к документации сервиса, ибо это самая важная часть — нет документации, нет сервиса. Описываем абсолютно все возможности микросервиса. Лучше всего для этих целей завести в корне проекта файл Readme для синхронной актуализации. Или можно применить swagger, если кто-то любит покрасивее.
В принципе, можно сказать, что на этом этапе разработка микросервиса закончена, так как код написан, документация написана и вы его протестировали (честно). Но на самом деле нет. Так как не решён самый важный, по моему скромному мнению, вопрос доставки сервиса на продакшн. И вот мы уже подошли к последнему этапу — доставка.
5. Доставка
Для этих целей мы воспользуемся CI менеджером и технологией Docker Swarm.
Про сборку буду рассказывать в терминах Bamboo (так как мы его у себя используем).
В цикле сборки участвует 2 связанных билд плана. Первый — компилируем бинарный файл из стянутого из репозитория исходного кода микросервиса. Компиляция проходит в специальном с нужной нам версией Go докер контейнере. На выходе первого плана у нас будет артефакт с готовым для запуска бинарником. Сразу после успешного завершения первого плана стартует зависимый (второй) план. Во втором плане — готовится докер образ с самим сервисом, его конфигами и параметрами деплоя из другого репозитория.
Для удобства настраиваем первый билд план так, чтобы при попадании изменений в ветку master, сборка запускалась автоматически.
Далее нужно создать и настроить Deployment Project для деплоя микросервиса. В этом проекте описываем два окружения — Test и Production.
Деплой осуществляется через свой костыльный питон-деплояторВ параметрах деплоя, в зависимости от окружения, указывается в какой кластер деплоить (у нас их на данный момент 4), количество реплик, лимиты процессора, памяти и т. д.
Сразу же после успешного деплоя каждой реплики будет произведена попытка его запуска и в случае неудачи деплой останавливается, чтобы не положить оставшиеся запущенные реплики.
Настраиваем триггер на окружение Test, чтобы при удачной сборки master ветки деплой на тест осуществлялся автоматически.
Вот и все, теперь, при изменении ветки master будет запускаться сборка бинарника, затем сборка образа, после чего в окружение Test будет происходить автоматический деплой, а для окружения Production будет активна специальная кнопка Deploy.
По личному опыту скажу, что основная проблема и сложность микросервисов — это доставка их на продакшн сервер, но если у вас есть люди, которые дружат с докером, то проблем становится в разы меньше. Раньше для деплоя мы использовали deb пакеты, что принуждало заниматься “ручной работой” при каждом обновлении сервиса и плюс к этому накладывалась деградация сервиса из-за того, что его приходилось перезапускать после установки нового пакета.
Мне удалось выделить 5 основных этапов для разработки микросервиса, надеюсь, это принесёт вам пользу и вдохнёт в вашу жизнь новую частичку творчества, которым занимаемся мы разработчики.
Комментарии (10)
Express777
29.06.2017 10:58+5С этим полностью согласен
После написания основной части кода приступаем к документации сервиса, ибо это самая важная часть — нет документации, нет сервиса.
Ну и немного юмора
mamont80
29.06.2017 17:29У меня есть конкретный вопрос, который из статьи в статью обходится стороной или упоминается вскользь. Что используется в качестве транспорта для общения между сервисами? Ведь архитектура подразумевает наличие множество добавляемых инстансов? Единственно что слышал — RabbitMQ. Но он не очень-то подходит для этого. Есть ли мейнстримовые решения по интересней?
akimserg
29.06.2017 17:35Сервисы между собой общаются по http, никкакой специальной инфрастуктуры, пока, для этого не поднято. Пишем максимально автономные сервисы, чтобы было как можно меньше связей между ними.
shishmakov
29.06.2017 18:15Как меняете протокол взаимодействия? Версионность? Он один для всех?
akimserg
29.06.2017 18:33Версионность это боль, нет версионности — нет боли). Взаимодействуют по http стандартными POST и GET запросами. Есть в планах попробовать grpc.
ewolf
29.06.2017 21:11Что если потребуется поменять api, сделав его несовместимым, а при этом старый api уже используется 10 другими сервисами, и у команд, разрабатывающих их, обновление совместимости с вашим api не в приоритете задач??
akimserg
01.07.2017 16:41Если какой-то метод в апи нужно сделать несовместимым, то можно оставть старый метод и создать новый. Новые клиенты будут пользоваться новым, старые старым.
x07
Полезная статья!