Опыт ВсеИнструменты.ру: как тестировать микросервисы и нужны ли они вашему бизнесу

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

Сегодня у ВсеИнструменты.ру около сотни микросервисов и будет примерно в два раза больше после «распила» из текущих монолитов.

Преимущества микросервисов — изолированность кода и масштабируемость. В отличие от монолитов, масштабировать микросервисы быстрее и гораздо дешевле.

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

Почему не надо начинать с логистики

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

Тем не менее мы выбрали стек технологий и создали группу микросервисов логистики. И интегрировали со всеми монолитами / сервисами где эта логика была необходима: системы отчетности, ERP-систему, мобильное приложение, сайт.

Выбранный стек технологий менялся несколько раз прямо на ходу. Первый микросервис мы запускали на РНР (тогда же стало понятно, что он вообще не подходит для этой задачи). От него нельзя добиться нужной нам скорости ответа сервиса, через год сервисы, написанные на PHP, мы переписали на Go.

Стек технологий ВсеИнструменты.ру

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

PostgreSQL, MySQL, MariaDB, Dgraph. Для поддержки баз данных. Dgraph мы используем для хранения логистических цепочек.

NewRelic / Prometheus + Grafana / EFK. Для мониторинга приложений.

PHP. Используется в монолитах.

RabbitMQ. Для очередей.

Vue.js. Для фронтенда.

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

Как строить тестирование микросервисов

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

Сначала нужно определиться со стратегией и выбрать виды тестирования.

Виды тестирования

Модульное тестирование (или юнит-тестирование). Самый простой вид быстрого тестирования, направленный на один компонент за один раз.

Интеграционное тестирование. Программные модули тестируют как группу после объединения для выявления багов взаимодействия.

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

Тестирование производительности. Для определения скорости работы вычислительной системы или ее части. Проверяет non function requirements (требования, не относящиеся к функциональности). Мы измеряем нагрузку для определения основных показателей ЦПУ и памяти сервиса. Используется и для тестирования каналов связи.

После выбора стратегии нужно обсудить активности тестировщиков; решить, как генерировать тестовые сценарии; рассчитать требуемые ресурсы.

Сам процесс тестирования аналогичен тестированию процессов на монолитах. Сначала нужно протестировать требования, выставленные к микросервису, убедиться, что не будет нужно переделывать процессы. Чем раньше мы найдем баги, тем дешевле будет “чинить”.

Важно также определить уровни тестирования с разработчиками: одну логику можно покрыть юнит-тестами, для другой нужен более высокий уровень — функциональные или API-тесты (в контексте автоматизирования тестирования).

Получившееся техническое задание позволяет оценить необходимое на тестирование время. Оно зависит от опыта тестировщика и объемов задач. Затем можно приступать к тестированию.

Программные средства для тестирования

PostMan и Swagger. Rest-клиенты протокола общения для ручного тестирования.

JavaScript. Для автоматизации тестирования.

GitLab CI. Автоматический запуск тестирования.

Allure. Фреймворк Яндекса для просмотра красивых отчетов.

Jaeger. Чтобы подружить между собой несколько микросервисов и проверить их полную интеграцию. Показывает точку входа клиента на сайт и всю цепочку его передвижений до конечного сервиса. Тестировщик может оперативно отследить проблемы на этом пути.

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

Стоит подумать и об автоматизации тестирования. Например, без нее весь наш сайт после изменения функционала один тестировщик будет проверять вручную порядка 7 рабочих дней. Наши процессы существенно быстрее, потому что автоматизация есть и прогон тестов по сайту занимает 25 минут.

Уроки наших ошибок

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

С другой стороны, начав с самого сложного процесса, значительно завязанного на клиентах, мы получили мощную экспертизу и теперь уверенно движемся вперед. Мы переосмыслили все ключевые бизнес-процессы компании, запустили несколько складов, в которых микросервисы отлично себя показали. Сейчас, например, при изменении логистических процессов, мы заходим в админку, меняем логику и все изменения автоматически «разъезжаются» по системам. На монолите на аналогичную операцию потребовался бы квартал и команда из 10 человек.

Что важно учесть при тестировании микросервисов

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

Тестовые данные. Это больная история микросервисов. Их нужно сгенерировать в достаточном количестве, что иногда трудозатратно. К тому же, нужно одновременно генерировать новые и поддерживать старые данные.

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

Учитывать цепочки. Особенность тестирования микросервисов в том, что их нужно проверять в цепочке. Это усложняет процесс. Для успешного тестирования нужно знать все контракты, которые прописывают общение между микросервисами.

Здравый смысл. Микросервисы нужны не всем компаниям. Есть и категорические противники микросервисов вроде компании Badoo. Они решили, что раздробились слишком сильно и не сгруппировали новые службы. Поэтому в разработке и тестировании микросервисов важно искать баланс между пользой для бизнеса и затрачиваемыми ресурсами.

0
24 комментария
Написать комментарий...
Александр Курицын

Было бы интересно прочитать отдельный материал про ПО для тестирования, потому что от знакомых слышал много негатива в адрес Swagger

Ответить
Развернуть ветку
ВсеИнструменты
Автор

Звучит как идея для следующего материала

Ответить
Развернуть ветку
Артем Арте

1. ЯП
2. тестовый фреймворк для юнит тестов
3. правильная архитектура, когда тестовый фреймворк собирается на основе DAL+Domain библиотек и генерирует тестовые данные. Иначе самописная либа для создания тестовых данных.
Создаёте свои тесты и не нужен никакой сваггер.

что-то ещё - трата времени и денег клиента.

Ответить
Развернуть ветку
Милана Леонова

Много закупались на ВИ.ру, когда делали ремонт. Удобный сервис, но никогда не думала, что он такой технологичный😱 Рассказывайте о своих разработчиках почаще, они у вас очень крутые👍😍

Ответить
Развернуть ветку
ВсеИнструменты
Автор

Благодарим! Это действительно так, они лучшие)

Ответить
Развернуть ветку
C Shark

Все классно, выводы порадовали, действительно было странно начинать внедрение с логистики, но ок. Я скорее обычный юзер, объясните, почему ВИ.РУ не работает на Python? Отличный язык для написания каких-нибудь автоматизаторов, “душить питона”, как говорит один мой знакомый джуниор, прекрасно.

Ответить
Развернуть ветку
ВсеИнструменты
Автор

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

Ответить
Развернуть ветку
Александр Коваль

Суть статьи - мы распилили монолит, было тяжело, PHP -  медленный. Остальное просто водица.

Ответить
Развернуть ветку
Чича Ничаев

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

Ответить
Развернуть ветку
Мегаплан
 Автотестирование. Его нужно внедрить и постоянно совершенствовать.

А совершенству, как известно, предела нет) 

Ответить
Развернуть ветку

Комментарий удален модератором

Развернуть ветку
Kristina Serdyukova

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

Ответить
Развернуть ветку
Andrey Sakharov

Забавно. Было 2-3 системы. В одну вносили изменения, во вторую забывали. В результате пользователи и менеджеры видели разную дату доставки.
Теперь же у вас 100 микросервисов и все видят дату одинаково. Видимо поддержка большого количества микросервисов тренирует память.

Ответить
Развернуть ветку
Александр Коваль

Если запроектировать в Entity services. То нет проблем с консистентностью, но есть проблемы с единой точкой отказа.

Ответить
Развернуть ветку
Батин Воротила

А сервисы между собой общаются по http или через rabbitmq? Или еще как-то? И все одинаково или - какие-то http, какие-то через очередь?
И как работают распределенные транзакции? В плане согласованности данных - если что-то где-то упало, откатываете обратно на каждом сервисе? Недавно узнал про CAP теорему, и теперь оно не дает мне покоя..
В последнее время столько всего про микросервисы начитался, что создается впечатление, что минусов больше, чем плюсов. Или просто опыта мало. Сейчас есть возможность разгрести весь написанный трэш. И хочется сделать чуть лучше, а не как всегда.

Ответить
Развернуть ветку
ВсеИнструменты
Автор

Для синхронного взаимодействия используется http (в основном JSON:RPC или GraphQL), для асинхронного - Kafka. Один и тот же сервис может использовать как синхронное, так и асинхронное взаимодействие.

С транзакциями действительно всё сложнее после монолитов. Распределенных транзакций, как таковых, у нас сейчас не существует, по той причине, что в используемых сервисах нет данных, для которых это было бы критично. Распределенные транзакции - это всегда некоторый оверхед, как с точки зрения разработки, так и с точки зрения производительности.
Для поддержания консистентности данных используется механизм сверок - они выполняются на приемлемом для нас промежутке времени, сверяя данные между системами и синхронизируя их по необходимости.
Такой механизм проще в реализации, хотя имеет свои недостатки. Если появится задача с данными, критичными к атомарному изменению в разных системах, то да, будет необходимо применить распределенные транзакции в каком-то виде. Относительно CAP теоремы получается, что сейчас мы приносим в жертву консистентность, по сути имея AP-систему.

Ответить
Развернуть ветку
Ян Рокотов

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

Ответить
Развернуть ветку
ВсеИнструменты
Автор

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

Ответить
Развернуть ветку
Егор Егоров

Вам не кажется, что тип для тестировщика весь сайт проверять 7 рабочих дней дофига? Ща конечно набегут мамкины тестировщики, которые скажут, что им надо 30 дней и 200к, но все же? Какой штат тестировщиков у ВИ.ру и как вы их набираете? Мб я смогу удаленно поколбасить ваш сайт... p.s. даже так скать, на аватарке в касочке, можно сказать, что в корпоративном стиле

Ответить
Развернуть ветку
тест

200 микросервисов вручную протестировать, а не сайт

Ответить
Развернуть ветку
ВсеИнструменты
Автор

7 дней - это если бы у нас не было автоматизации. Сейчас тестирование занимает гораздо меньше времени.

Ответить
Развернуть ветку

Комментарий удален модератором

Развернуть ветку
ВсеИнструменты
Автор

Смотрели и изучали опыт рынка, но решение в итоге было своё с применением общепринятых практик разработки микросервисов.

Ответить
Развернуть ветку
Александр Коваль

По сути названия статьи - вообще ничего не написано.

Ответить
Развернуть ветку
Чича Ничаев

Ну такая, полу бесполезная статья, воды больше

Ответить
Развернуть ветку
Артем Арте
юнит-тестами, для другой нужен более высокий уровень — функциональные или API-тесты

Тесты сделали, а с пониманием тестов вы по хоже так и не разобрались. А от сюда может сделали, да что-то не то или дублирование.

Функциональные тесты - это тесты которые проверяют функции систем, грубо говоря ваши фичи. (А нефункциональные - это, например, нагрузочные тесты).
Функциональным будут и юнит (проверяем расчёты), и интеграционные (сохраняем что-то) и еnd-2-end (проходим от запроса к АПИ до сохранения в базу и взаимодействия с очередью или 3им и сервисами).

Апи-тесты - вообще не понятно что такое.

То ли это end-2-end тесты которые проверяют всю систему или сервис со всеми связками (аналогично как через селениум делают).

То ли это интеграционные тесты для API когда проверяется связка 2х систем, в данном случае правильность урлов\контроллеров, сериализации\обработка ошибок (статусы) а вся внутренности контроллера мокается, чтобы в базу не лезли.

Ответить
Развернуть ветку
21 комментарий
Раскрывать всегда