Лично я сталкивался с тем, как крупные компании распиливают монолит на микросервисы, но потом не переиспользуют их. Они так и остаются жить в одной системе.
Здесь мы делаем микросервисы, не ради микросервисов, а пилим наши монолиты работоспособными частями. То есть, зарефакторили кусок, и производство с ним работает. На каждый - около 3 месяцев. Правда, с таким подходом есть риск улететь в ситуацию, когда микросервисы получаются AS IS, а не в общей идее архитектуры. В поддержке потом их совокупность не лучше монолита.
В общем, расскажу, как на практике распиливаются монолиты огромных размеров, которые управляют всем производственным циклом. А размеры ещё те: НЛМК — гигант. Мы делаем 20% стали России и входим в TOP-20 по производству в мире.
Сейчас миграция в процессе, делаем послойно уже чуть больше года. Быстрее, чем за 5 лет никто пока не делал, и это считается быстро. Посмотрим, как у нас получится.
![](https://habrastorage.org/getpro/habr/upload_files/d0d/366/668/d0d366668115982128c57caeeb6a56ac.jpg)
Архитектуру и требования к ней мы продумали сразу. Правда, никто не обещал, что архитектура не будет меняться по ходу. Оказалось, что универсальные части инфраструктуры выделять чуть сложнее, чем нарисовать архитектуру на бумаге. Получилось, что где-то мы выделяли функциональные блоки, а где-то делали послойную миграцию (например, замену фронта).
![](https://habrastorage.org/getpro/habr/upload_files/368/f62/3a8/368f623a8e1c9475078f269b0fdb28ad.png)
Одновременно у нас идет много проектов на разных производственных переделах, и у каждой команды свой монолит. Мы ожидали, что в итоге у нас будет синергетический эффект от параллельной работы команд, но по факту, каждая команда делает свой функционал независимо, зачастую, не обращая внимание на то, что мы рассчитываем на общее переиспользование микросервисов. Ребятам проще сделать компонент внутри своего проекта, который, по идее, должен быть общим.
Например, есть библиотека НСИ (нормативная документация), которую внутри проекта сделать проще, чем продумывать универсальный компонент. Так каждый ваяет свой велосипед. Боль в том, чтобы потом собрать из этих велосипедов универсальные компоненты.
Наши монолиты
Для управления производством такого масштаба неизбежно нужны крупные информационные системы. Мы подошли к началу цифровой трансформации с большим количеством монолитов, реализованных на уровне баз данных Oracle. В качестве «фронтенда» использовались Oracle Forms с интерфейсом из 90-х. Надо сказать, что и некоторые участки кода – настоящий антиквариат. Естественно, ни о каких системах контроля версий и совместной работы не было и речи. Поддержка таких систем требовала самоотверженной работы десятков специалистов, и все знания были в их головах.
Производственный процесс Группы НЛМК охватывает множество предприятий на разных континентах, и при этом в каждом цехе была собственная информационная система со своими особенностями. Общались эти системы, как с помощью шины данных на базе Kafka, так и банальными DBLink.
![Схема производственного процесса липецкой площадки НЛМК https://studfile.net/preview/5990480/ Схема производственного процесса липецкой площадки НЛМК https://studfile.net/preview/5990480/](https://habrastorage.org/getpro/habr/upload_files/f0e/2ac/269/f0e2ac269bce8a2cda5202ece5957f21.png)
На данном этапе - основные объекты трансформации - это MES (manufacturing execution system) – системы управления производством. Они находятся между уровнями АСУТП (датчики, исполнительные механизмы, контроллеры) и уровнем ERP (такими системами как SAP и 1C). В нашем случае это аналитически-учетные системы уровня цеха.
![Структура систем управления производством Структура систем управления производством](https://habrastorage.org/getpro/habr/upload_files/acf/49d/e07/acf49de075e8dd8e6dea0da80b4e3488.png)
В качестве новой целевой системы был выбран микросервисный подход на базе Java стека, в частности Spring, как фреймворк, который реализует множество возможных интеграций и позволяет быстро создавать запускаемые сервисы на Spring Boot. Микросервисы позволяют вести независимую работу над отдельными частями системы, добиться эффективного масштабирования тех участков, которые испытывают большие нагрузки. В отличие от многих проектов, где микросервисы делаются ради микросервисов, мы ставим перед собой задачу реально переиспользовать их на разных системах, чтобы сократить количество кода и упростить дальнейшую разработку и поддержку систем. Как говорится, DRY в своем лучшем виде. Но такой подход таит и трудности, с которыми мы неминуемо столкнулись.
Распил на микросервисы
Для запуска прикладных сервисов у нас развернута «единая цифровая платформа» (ЕЦП) как совокупность инфраструктурных сервисов от хранения кода и CI/CD в GitLab до запуска в Openshift, сбора логов и мониторинга.
![Общая структура единой цифровой платформы (ЕЦП) в НЛМК Общая структура единой цифровой платформы (ЕЦП) в НЛМК](https://habrastorage.org/getpro/habr/upload_files/ede/0af/ddf/ede0afddf9ae2168df56b2ba46bedf45.png)
Применение инструментов ЕЦП для наших сервисов определяется уровнем зрелости разработки. Начиная от хранения кода в GitLab, и заканчивая сбором инфраструктурных и бизнес-метрик на проде.
![Ступени зрелости разработки сервисов Ступени зрелости разработки сервисов](https://habrastorage.org/getpro/habr/upload_files/1ae/e70/0f1/1aee700f121f844671dd62ca616fe651.png)
Чтобы получить синергетический эффект от использования одних микросервисов в разных системах, нужно, чтобы они были переиспользуемые. Этого проще добиться, когда система разрабатывается с нуля и есть достаточное время на проектирование. Но когда параллельно идут несколько проектов в разных цехах, и у всех свои сжатые сроки, может получиться, что каждый проект разрабатывает свою реализацию микросервиса. Большинство специфичной бизнес-логики находится в уникальных сервисах, но есть и сервисы, которые можно эффективно переиспользовать. Например, сервисы отчетов, дашбордов, нормативно-справочной информации (НСИ) и т.п. Такие сервисы приходится увязывать между несколькими проектами. Сейчас мы пришли к модели, при которой каждый сервис разрабатывается сначала внутри одного проекта, а потом переиспользуется остальными. Возможно, в идеале будет еще как-то иначе. Чаще всего, первая команда становится техническим владельцем сервиса и отвечает за его развитие.
![Задача параллельной разработки на нескольких проектах Задача параллельной разработки на нескольких проектах](https://habrastorage.org/getpro/habr/upload_files/f75/527/49c/f7552749c14a328a92197b805d659650.png)
Другой подход, когда мы используем горизонтальные сервисы, инстансы которых могут непосредственно использоваться несколькими проектами. И опять же пример - сервис нормативно-справочной информации (НСИ), который может использоваться многими системами. В данном подходе сервисы рождаются внутри проектных команд. Минус в том, что дальше эти команды пойдут заниматься другими проектами – им будет не до ранее разработанного сервиса. Мы смотрим в сторону выделения отдельных сервисных команд, которые бы занимались осознанным проектированием и развитием сервиса с учетом его широкого применения.
Важен уровень критичности сервиса и отдельной системы: сервис не может быть менее критичным, чем любая из систем, которая его использует. Иначе приходится вводить дополнительные элементы системы, которые обеспечат ее работоспособность на случай низкой доступности горизонтального сервиса.
![Применение горизонтальных сервисов Применение горизонтальных сервисов](https://habrastorage.org/getpro/habr/upload_files/b0a/fbc/f0e/b0afbcf0ed3eb97cba3f8649fa7e423e.png)
К миграции на микросервисы у нас тоже сформировалось несколько подходов. Один из них – это послойная миграция, когда мы делаем сразу новый фронт для всей системы. Но для него приходится создавать middleware прослойку, которая содержит как backend for frontend (BFA), так и адаптеры для работы со старой системой, основанной на старой БД. Плюс такого подхода в том, что мы можем сразу дать бизнесу новый интерфейс и разом пересадить на него всех пользователей. Из минусов то, что адаптеры для работы со старой системой не будут применяться в целевом варианте и по сути отправятся в корзину.
![Послойная миграция Послойная миграция](https://habrastorage.org/getpro/habr/upload_files/f86/5ac/2f6/f865ac2f6f12ec61a1eb4d064eea1c3f.png)
Более классический вид миграции - выделение отдельного микросервиса или их группы для реализации законченного функционала. Так мы сразу можем делать системы в целевом варианте. Но тоже есть сложности: не всегда можно выделить достаточно изолированный блок, чтобы он не был связан с остатками нашего монолита. Приходится делать дополнительные временные элементы, дублировать информационные потоки. Зачастую новые участки работают параллельно со старым функционалом, а пользователей не так просто склонить к использованию новой системы, когда старая еще отлично работает.
![Поэтапная миграция функций Поэтапная миграция функций](https://habrastorage.org/getpro/habr/upload_files/31e/41e/d8e/31e41ed8ee03f74177cdc9dc725b0175.png)
Миграция на новый технологический стек и архитектуру - всегда непростой процесс, который не имеет однозначного решения и иногда проходит по-разному даже на очень похожих проектах. В будущих статьях подробнее расскажу про те технические сложности, с которыми мы столкнулись, и про решения, которые применили.
На данный момент мы активно работаем, и несколько MES частично доведены до продуктива. В каждом случае есть различия по бизнес-требованиям и применяются разные подходы в переходе на микросервисную архитектуру. Также, анализируя промежуточные, мы корректируем подходы к разработке и создаем архитектуру горизонтальных сервисов, обслуживающих несколько систем.
Подобные проекты не имеют изначально правильного решения. Приходится пройти путь проб и ошибок. Сейчас мы пробуем разные подходы, чтобы из каждого выбрать лучшее. Лично я верю, что мы сделаем все правильно и круто. Будут новые результаты, будет статья о том, что эффективнее сработало именно для нас. А также коллеги уже пишут посты про конкретные технические и архитектурные кейсы.