Всем тем, кто много слышал про микросервисы, но так и не решился сделать ни одного — посвящается.
По причинам создания и описанием всех “за” и “против” написано уже сотни статей — здесь же я расскажу про практическую сторону создания и использования.
image

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

Статья не акцентирует внимание на том, как писать микросервисы, у каждого свои методы, здесь я расскажу в общих чертах про этапы разработки и доставки сервиса на продакшн и тест.
Я разделил процесс создания на этапы. И вот первый из них:

1. Задача


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

2. Технологии


Задача есть, теперь определяемся с технологиями её решения. Хранилище данных медленное и не справится с большим потоком запросов. В таких случаях можно использовать elasticsearch — он отлично справляется с большими нагрузками и умеет шардироваться и реплицироваться из коробки. Положим в него данные отдельным скриптом для последующего поиска по ним.

Так как в нашей компании «Колеса Крыша Маркет» принято писать микросервисы на Go, и у меня есть опыт написания на Go, то принято решение писать на Go. В вашем случае это может быть что угодно — Nodejs, Java, PHP или любой другой, желательно, компилируемый язык. Так как стек технологий зависит и от архитектуры сервиса, то на этом этапе нужно подумать о ней, а также продумать логику работы. Здесь стоит собрать инфу со всех клиентов которые будут использовать наш микросервис, в частности с команды мобильной разработки, если таковая имеется.

3. Кодирование


После всех раздумий на счёт стека технологии и архитектуры, логики работы сервиса приступаем непосредственно к кодированию. Определяемся будем ли мы писать кодовую базу с нуля (не рекомендую) или заюзаем какой-то готовый фреймворк.

Много о реализации на Go
Было принято решение заюзать github.com/labstack/echo — показался мне наиболее легковесным и живым проектом. Далее, так как нам придётся ходить за данными в эластик, то нужно выбрать либу для работы с эластиком github.com/olivere/elastic. Для логирования возмём github.com/sirupsen/logrus. В качестве мониторинга можно взять github.com/rcrowley/go-metrics или что-нибудь попроще github.com/cactus/go-statsd-client.
Подключаем все зависимости в 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)


  1. x07
    29.06.2017 10:16
    +8

    Полезная статья!
    image


  1. Express777
    29.06.2017 10:58
    +5

    С этим полностью согласен

    После написания основной части кода приступаем к документации сервиса, ибо это самая важная часть — нет документации, нет сервиса.


    Ну и немного юмора
    image


  1. camilaomarova
    29.06.2017 11:00

    Спасибо за статью! :))


  1. mamont80
    29.06.2017 17:29

    У меня есть конкретный вопрос, который из статьи в статью обходится стороной или упоминается вскользь. Что используется в качестве транспорта для общения между сервисами? Ведь архитектура подразумевает наличие множество добавляемых инстансов? Единственно что слышал — RabbitMQ. Но он не очень-то подходит для этого. Есть ли мейнстримовые решения по интересней?


    1. akimserg
      29.06.2017 17:35

      Сервисы между собой общаются по http, никкакой специальной инфрастуктуры, пока, для этого не поднято. Пишем максимально автономные сервисы, чтобы было как можно меньше связей между ними.


      1. shishmakov
        29.06.2017 18:15

        Как меняете протокол взаимодействия? Версионность? Он один для всех?


        1. akimserg
          29.06.2017 18:33

          Версионность это боль, нет версионности — нет боли). Взаимодействуют по http стандартными POST и GET запросами. Есть в планах попробовать grpc.


          1. ewolf
            29.06.2017 21:11

            Что если потребуется поменять api, сделав его несовместимым, а при этом старый api уже используется 10 другими сервисами, и у команд, разрабатывающих их, обновление совместимости с вашим api не в приоритете задач??


            1. akimserg
              01.07.2017 16:41

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


      1. ewolf
        29.06.2017 21:07

        Мне кажется, что либо микро, либо автономные.