Микросервисы. Паттерны разработки и рефакторинга с примерами на языке Java +4


Привет, Хабр!

Мы приступаем к переводу книги Криса Ричардсона "Microservices Patterns. With examples in Java". До премьеры на русском языке еще с полгода, но мы хотели бы предложить вам своеобразный трейлер — немного сокращенный обзор этой книги от Бена Нейдела (Ben Nadel), прочитавшего MEAP-версию. В обзоре активно цитируется текст Kindle-версии Ричардсона.



Добро пожаловать под кат!

Я узнал о Крисе Ричардсоне, познакомившись с его интернет-ресурсом Microservices.io. Где, скажу честно, дается ошеломительный объем информации – которую я решил отложить на потом, поскольку к тому моменту еще не знал, как к ней подступиться, особенно, учитывая, что еще практически не имел дел с микросервисами. Мне больше нравится читать. Поэтому, узнав, что у Криса выходит авторская книга Microservices Patterns: With Examples In Java, я просто воодушевился. Настолько, что не мог дождаться ее выхода. Так что приобрел и прочел «раннюю версию» (MEAP) от Manning. На прошлой неделе только и делал, что штудировал эту книгу, и считаю, что это увлекательное, прагматичное и целостное исследование микросервисного подхода к разработке.

Вся книга построена в виде истории Мэри – CTO (генерального технического директора) компании Food To Go, Inc (FTGO). Компания стремится развить бизнес, запустив рефакторинг своего старого монолитного приложения и переделав его в микросервисную архитектуру. Мэри берется за этот проект, поскольку скорость разработки снизилась, а начальство все сильнее раздражается тем, что программисты под началом Мэри не в состоянии выдавать новые фичи в достаточно качественном виде.

Разумеется, основная проблема Мэри – это так называемый «монолитный ад» в терминологии Ричардсона. Притом, что монолит – это крупное и разрастающееся приложение, Ричардсон сосредотачивается на достаточно тонком аспекте миграции FTGO, так, чтобы было удобнее изложить и донести все концепции. При этом содержание книги получается невероятно удобоваримым. Большинство рассуждений об архитектуре обычно получаются либо чрезмерно упрощенными, либо переусложненными. Однако, Ричардсону удалось найти золотую середину, сконструировав такую модель предметной области, которая (почти) укладывается в голове, но при этом достаточно сложна, чтобы на ней можно было проиллюстрировать интересные межсервисные потоки задач.

С самого начала я предвкушал, что Ричардсон будет прагматичен во всех деталях. Ни один аспект в книге не подается как «серебряная пуля» или «единственное решение». Везде мы видим просчитанный выбор, совокупность четко очерченных компромиссов. Например, даже саму идею микросервисов автор подает в таком ключе: микросервисной архитектуры следует избегать всегда, кроме тех случаев, когда она абсолютно необходима:

Еще один вызов, связанный с использованием микросервисной архитектуры – решать, в какой момент жизненного цикла приложения приступать к использованию этой архитектуры. При разработке первой версии приложения вы зачастую еще не сталкиваетесь с проблемами, которые решает такая архитектура. Более того, использование выверенной распределенной архитектуры только замедлит разработку. Такая дилемма может возникать на стартапах, где важнейший вызов обычно заключается в стремительном развитии бизнес-модели и собственного приложения. При использовании микросервисной архитектуры значительно сложнее организовать быстрые итерации. Развитие стартапа определенно должно начинаться с монолитного приложения. (Kindle-версия, адрес 416)
Ричардсон также рассматривает микросервисы в целостной перспективе, рассуждая о динамике работы команды как о совершенно самостоятельном круге проблем, который надстраивается над технологической частью. Разумеется, он рассматривает такие темы как Закон Конвея и «Обратный маневр Конвея», но, при этом, он затрагивает и тот факт, что программисты – эмоциональные пафосные персонажи, которым вы должны «продать» идею микросервисов:
Переходя на микросервисную парадигму, вы вынуждены менять вашу архитектуру, вашу организацию и процессы разработки. Однако, в конечном итоге меняется рабочая среда, условия, в которых трудятся люди, а люди, как уже упоминалось – эмоциональны. Если человеческие эмоции игнорировать, то внедрение микросервисов в организации может превратиться в крутой маршрут. (Kindle-версия, адрес 718)
Описываемые автором стратегии касаются всего бизнеса целиком, затрагивают менеджеров и руководителей, которые, возможно, не решаются приступать к большому рефакторингу, отрывая на него ценные ресурсы, людей, которые могли бы активно разрабатывать новые фичи:
Существенная польза пошагового рефакторинга в сторону микросервисоной архитектуры – в том, что такая стратегия сразу же начинает окупаться. Это совсем не та ситуация, что при «капремонте» кода, который не принесет никакой пользы до полного завершения…

Еще один плюс той ситуации, в которой ценность от перехода приобретается уже на раннем этапе – мы можем привлекать для обеспечения миграции поддержку со стороны бизнеса. Такая текущая поддержка принципиальна, поскольку чем активнее рефакторинг – тем меньше времени удастся тратить на разработку фич. В некоторых организациях сложно избавиться от технического долга, поскольку предыдущие попытки могли получаться чрезмерно амбициозными и не приносили желаемой пользы. В результате бизнес с неохотой продолжает инвестиции в «наведение порядка». Пошаговая природа рефакторинга в случае микросервисов означает, что команда может демонстрировать ценные результаты очень часто. (Kindle-версия адрес 10769)
С технологической точки зрения в книге «Микросервисы. Паттерны разработки и рефакторинга» рассмотрен широкий спектр тем: от гексагональных архитектур, тестирования и непрерывной интеграции до паттернов обмена сообщениями и создания наблюдаемых систем. Такой охват подразумевает, что некоторые темы в книге освещены подробнее других. Однако, опять же, Ричардсону отлично удается все сбалансировать и дать именно столько подробностей, чтобы можно было предметно рассуждать на тему, не обескураживая при этом читателя.

На самом деле, содержимое книги организовано таким образом, что вы сами можете выбирать, в какие темы углубляться. В каждой главе перед подробным погружение в тему дается список TL;DR, в котором кратко перечисляются все «за» и «против». Таким образом, вам удается уловить наиболее важные моменты главы, не вчитываясь в каждое слово.

Честно говоря, я просто пролистнул две главы о тестировании микросервисов и одну главу о развертывании микросервисов. Уверен, у автора эти темы проработаны отлично, но мне показалось, что там попросту больше информации, чем я смогу переварить. Развертывание не является для меня актуальной повседневной задачей. За всю жизнь написал несколько тестов.
Таким образом, хотел оставить в моем незамутненном пещерном сознании достаточно места, чтобы уложить там материал из всех остальных глав: о предметно-ориентированном проектировании (DDD), межпроцессной коммуникации и синхронизации данных.

Один из разделов, оказавших на меня особенно сильное впечатление, рассказывает о том, какой сервис должен обрабатывать запросы одного специализированного типа, а именно: находить подходящие рестораны поблизости от текущего местоположения пользователя:
Однако, бывает сложно реализовать даже такие запросы, которые локальны с точки зрения конкретного сервиса. Такое возможно по нескольким причинам. Во-первых, потому что (как описано ниже), иногда нецелессобразно реализовывать запрос в том сервисе, который владеет данными. Другая причина – иногда база данных сервиса (или модель данных) не может эффективно поддерживать запрос (Kindle-версия, адрес 5659)
… Если в приложении FTGO информация о ресторанах хранится в [какой-то иной] базе данных, то реализация запроса findAvailableRestaurant() значительно усложняется. Реплика данных о ресторанах должна храниться в такой форме, которая позволяет поддерживать геопространственные запросы. Например, в приложении можно было бы использовать библиотеку геопространственного индексирования (Geospatial Indexing Library) для DynamoDB, где таблица используется как геопространственный индекс. Альтернативный вариант: приложение может хранить реплику данных о ресторанах в базе данных совершенно другого типа. Схожая ситуация возникает, когда мы используем текстовые запросы с базой данных для текстового поиска. (Kindle-версия, адрес 5675)
… В таком случае, целесообразно (как минимум, на первый взгляд), чтобы операцию запроса реализовывал именно тот сервис, что владеет данными. Однако, кроме владения данными приходится учитывать и другие факторы.

Также требуется принимать во внимание необходимость разделения обязанностей и избегать перегрузки сервисов слишком большим количеством возможностей. Например, основная обязанность команды, разрабатывающей сервис Restaurant – помочь ресторанным менеджерам обслуживать работу заведения. Эта задача совсем не того плана, что реализация критичного запроса для работы с большими объемами данных. Более того, если бы команда разработчиков отвечала за операцию findAvailableRestaurants(), то постоянно боялась бы внедрять такие изменения, которые могли бы помешать потребителям делать заказы. (Kindle-версия, адрес 5675)
Здесь мне немного взорвало мозг, потому что я впервые видел сервис, чья единственная функция сводилась к оптимизации данных другого сервиса для выполнения конкретной задачи. Однако, как указывает Ричардсон, это всего лишь более обобщенная абстракция той самой идеи, что лежит в основе полнотекстового поиска, например, в Apache Lucene (этот инструмент обеспечивает полнотекстовое индексирование поверх другого хранилища данных).

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

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

Я мог бы упомянуть еще массу всего интересного. Чего стоит, например, тот факт, что Ричардсон как следует рассказывает об аутентификации и авторизации в распределенной системе – думаю, эта тема пока исследована, мягко говоря, недостаточно полно. Автор объясняет предметно-ориентированное проектирование максимально доступным образом. Также он демонстрирует, что даже очень простые классы могут обладать поведением.

Вот уже более года я пытаюсь как следует разобраться в архитектуре распределенных систем и микросервисных паттернах (что особенно сложно, поскольку моя повседневная работа связана с обслуживанием монолита). Многие тексты, которые я читал по этим темам, либо чрезмерно поверхностные, либо слишком узкие и при этом углубленные. Книга «Микросервисы. Паттерны разработки и рефакторинга» действительно является золотой серединой между этими двумя крайностями. Решительно рекомендую эту книгу всем (bold наш), кто пытается (в том числе, пока безуспешно) перейти от монолитной архитектуры к распределенной системе.




К сожалению, не доступен сервер mySQL