Разработка и тестирование приложений с микросервисной архитектурой

Автор: Косов С.Г., Кальянов Л.В.

Журнал: Форум молодых ученых @forum-nauka

Статья в выпуске: 4 (32), 2019 года.

Бесплатный доступ

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

Программирование, микросервис, web-сервис, тестирование

Короткий адрес: https://sciup.org/140286253

IDR: 140286253

Текст научной статьи Разработка и тестирование приложений с микросервисной архитектурой

Архитектура определяет, как приложение будет работать внутри, а также как оно будет взаимодействовать с внешним миром. Так как десктопные приложения, вытесняемые аналогичными по функционалу и скорости работы web-сервисами, уходят на второй план, большинство приложений разрабатывается с использованием клиент-серверного подхода. В роли клиентов могут выступать мобильные приложения, сайты или десктопные клиенты. При этом, клиент обладает лишь функционалом получения данных от сервера, отправки данных на сервер и отображения этих данных в удобном для пользователя виде.

Такая архитектура приложения имеет много плюсов, например, приложение не привязано к конкретной платформе, серверную часть можно тестировать отдельно от клиентской, данные между устройствами можно синхронизировать в рамках одного аккаунта, клиентские устройства меньше нагружаются вычислениями, что позволяет сэкономить на их характеристиках, приобретя более слабое устройство, продлить срок работы от аккумулятора или выполнить больше других параллельных задач. К минусам клиент-серверной архитектуры можно отнести тот факт, что при отсутствии интернета получить доступ к данным, которые находятся на сервере не получится, но в современном мире проблема отсутствия доступа в интернет не актуальна.

Крайне часто разрабатываемое приложение не может работать само по себе и нуждается в интеграции со сторонними сервисами. Например, авторизация пользователя через социальные сети требует интеграции с api сервера авторизации, а для использования навигации, календарей и документов, необходима интеграция и с сервером авторизации, и с сервером конкретного приложения. Сервис, с которым необходима интеграция, может принадлежать как разработчику, так и совершенно другой компании, например, карты google или yandex.

Когда необходима интеграция с чужим сервисом разработчику необходимо лишь ознакомиться с документацией и публичным api. В этом случае нет возможности изменить api и придется, при необходимости, вносить изменения в свое приложение. Если необходима интеграция с сервисом, принадлежащим разработчику, архитектура такого приложения начинает приближаться к микросервисной.

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

Допустим разрабатывается приложение для электронной библиотеки, в нем должна быть возможность авторизоваться, выбрать и заказать доставку книги, подтвердить получение, сообщить о желании вернуть книгу, оплатить использование сервиса, а также сервис должен на основе статистических данных уметь предлагать книги, которые были бы интересны конкретному читателю. Здесь мы имеем довольно большее приложение, которые несомненно можно реализовать с использованием монолитной архитектуры, но его будет сложно масштабировать, обслуживать, а также его будет сложно полностью охватить одному разработчику. В этом приложение можно выделить 5 атомарных сервисов:

  • 1.    выбор и заказ книг,

  • 2.    авторизация и аккаунт,

  • 3.    мессенджер для коммуникаций с курьерами и менеджерами сервиса,

  • 4.    платежная система,

  • 5.    сбор и анализ статистики.

Помимо этих 5 сервисов желательно иметь еще несколько инфраструктурных сервисов, которые позволят упростить процесс коммуникации между сервисами, а также реализовать балансировку нагрузки:

  • 1.    сервис реализующий паттерн api Gateway,

  • 2.    сервис, который предоставляет конфигурацию для каждого сервиса,

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

В итоге мы получили 8 отдельных приложений, которые должны как-то между собой взаимодействовать. Но не все так плохо - с реализацией инфраструктурных сервисов помогут фреймворки (netflix не только снимает сериалы, но и разрабатывает множество библиотек для распределенных систем). Теперь осталось разобраться с пятью сервисами, отвечающими за бизнес-логику. Допустим каждый сервис пишет отдельная команда разработчиков.

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

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

Решить эту проблему можно с помощью второй реализации клиента к api другого сервиса. То есть, если у нас был класс, являющийся клиентом к сервису статистики, который отправлял запросы по сети в реальный сервис, необходимо реализовать его копию, которая будет возвращать заранее заготовленные данные.

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

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

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

Таким образом для разработки приложения на базе миросервисной архитектуры необходимо:

  • 1.    выделять api сервисов в библиотеки,

  • 2.    стаб версии сервисов заменить на стаб версии классов клиентов,

  • 3.    покрыть unit тестами бизнес логику каждого сервиса,

  • 4.    перед каждым релизом необходимо производить полноценное интеграционное тестирование с запуском реальных сервисов.

Следуя всем этим правилам можно упростить процесс разработки микросервисного приложения до уровня монолитного приложения, при этом не потеряв ни одного преимущества.

Список литературы Разработка и тестирование приложений с микросервисной архитектурой

  • Who's Sharing What - The State of Social Sharing in 2013 [Электронный ресурс]. - Режим доступа: http://www.webhostingbuzz.com/blog/2013/03/21/whos-sharing-what
  • TIOBE Index for April 2018 [Электронный ресурс]. - Режим доступа: https://www.tiobe.com/tiobe-index
  • Java Web Frameworks Index [Электронный ресурс]. - Режим доступа: https://zeroturnaround.com/webframeworksindex
  • GitHub, репозиторий проекта [Электронный ресурс]. - Режим доступа: https://github.com/Sergey34/spring-boot-starter-security-oauth-social
Статья научная