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

Книга Эрика Эванса (Eric Evans) по предметно ориентированному проектированию Domain-Driven Design (Addison-Wesley) помогла нам осознать важность отображения в коде реального мира и показала более удачные способы моделирования наших систем. Концепция непрерывной поставки показала, как можно более эффективно и рационально внедрять продукты в производство, вселяя в нас идею о том, что завершением каждого рабочего этапа должен считаться выпуск предварительной версии продукта. Понимание порядка работы Всемирной сети привело нас к разработке более эффективных способов организации межмашинного общения. Концепция Алистера Кокберна (Alistair Cockburn) о гексагональной архитектуре увела нас от многоуровневых архитектур, в которых бизнес-логика может быть скрыта. Платформы виртуализации позволяют обеспечивать наши машины и изменять их размеры по своему усмотрению, а автоматизация инфраструктуры дает способ управления этими машинами на должном уровне. Многие крупные и успешные организации, такие как Amazon и Google, поддерживают намерение небольших команд владеть полным жизненным циклом своих сервисов. А совсем недавно компания Netflix поделилась с нами способами создания прочных (antifragile) систем в том масштабе, который трудно было себе даже представить еще 10 лет назад.

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

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

Что же такое микросервисы

Микросервисы — это небольшие, автономные, совместно работающие сервисы. Разберем это определение по частям и рассмотрим, что определяет отличительные черты микросервисов.

Небольшие и нацеленные на то, чтобы хорошо справляться только с одной работой

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

Внутри монолитных систем мы стремимся бороться с этой тенденцией, пытаясь сделать свой код более связанным, зачастую путем создания абстракций или модулей. Придание связности означает стремление сгруппировать родственный код. Эта концепция приобретает особую важность при размышлении о микросервисах. Она усиливается определением, данным Робертом С. Мартином (Robert C. Martin) принципу единственной обязанности — Single Responsibility Principle, которое гласит: «Собирайте вместе все, что изменяется по одной и той же причине, и разделяйте все, что изменяется по разным причинам».

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

Мне часто задают вопрос: а что является критерием понятия «небольшой»? Задание количества строк кода для этого вряд ли подойдет, поскольку одни языки выразительнее других и способны на большее при меньшем количестве строк. Нужно также считаться с тем фактом, что мы могли бы быть втянуты в ряд зависимостей, которые сами по себе содержат множество строк кода. Кроме того, некоторые составляющие вашей области деятельности могут быть сложными по определению и требовать немалого объема кода. Джон Ивс (Jon Eaves) из Австралии на сайте RealEstate.com.au охарактеризовал микросервисы как некий код, который может быть переписан за две недели, что имело вполне определенный смысл в качестве основного правила конкретно в его контексте.

Еще один несколько банальный ответ может прозвучать так: достаточно небольшой и не меньше этого. Выступая на конференциях, я почти всегда задаю вопрос: «У кого есть слишком большая система, которую хотелось бы разбить на части?» Руку поднимают практически все. Похоже, мы прекрасно понимаем, что может считаться слишком большим, и можно будет согласиться с тем, что тот фрагмент кода, который уже нельзя назвать большим, будет, наверное, достаточно небольшим.

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

Когда решается вопрос о достаточности уменьшения объема кода, я предпочитаю размышлять в следующем ключе: чем меньше сервис, тем больше проявляются все преимущества и недостатки микросервисной архитектуры. Чем меньше делается сервис, тем больше становятся его преимущества в смысле взаимозависимости.

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

Автономные

Наш микросервис является самостоятельным образованием, которое может быть развернуто в качестве обособленного сервиса на платформе, предоставляемой в качестве услуги, — Platform as a Service (PAAS), или может быть процессом своей собственной операционной системы. Мы стараемся не заполнять несколькими сервисами одну и ту же машину, хотя определение машины в современном мире весьма размыто! Чуть позже мы разберемся в том, что, несмотря на издержки, которые могут быть вызваны обособленностью, получаемая в результате использования такого сервиса простота существенно облегчает рассуждения о распределенной системе, а самые последние технологии позволяют смягчить множество проблем, связанных с этой формой развертывания.

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

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

Наши сервисы выставляют напоказ программный интерфейс приложения — Application Programming Interface (API), и работающие на нас сервисы связываются с нами через эти API. Нужно также подумать о технологии, позволяющей не привязывать сами интерфейсы к потребителям. Это может означать выбор API, нейтральных по отношению к тем или иным технологиям, чтобы гарантировать отсутствие ограничений в выборе технологий. На страницах этой книги мы еще не раз вернемся к вопросу о важности качественных, ни к чему не привязанных API.

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

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

Основные преимущества

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

Технологическая разнородность

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

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

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

Рис. 1.1. Микросервисы позволяют упростить использование разнообразных технологий

Разумеется, использование нескольких технологий не обходится без определенных издержек. Некоторые организации предпочитают накладывать на выбор языков ограничения. В Netflix и Twitter, к примеру, в качестве платформы используется преимущественно Java Virtual Machine (JVM), поскольку они очень ценят надежность и производительность этой системы. В этих организациях также разрабатываются библиотеки и инструментальные средства для JVM, существенно упрощающие работу в масштабе платформы, но сильно усложняющие ее для сервисов и клиентов, не работающих на Java-платформе. Но для всех заданий ни в Twitter, ни в Netflix не используется лишь один набор технологий. Еще одним аргументом в противовес опасениям по поводу смешения различных технологий является размер. Если я действительно могу переписать свой микросервис за две недели, то вы также можете снизить риск применения новой технологии.

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

Устойчивость

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

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

Устойчивость в ее лучших проявлениях и методы борьбы с отказами будут рассматриваться в главе 11.

Масштабирование

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

Рис. 1.2. Можно расширять только те микросервисы, которые в этом нуждаются

Именно по этой причине микросервисами воспользовалась компания Gilt, занимающаяся продажей через Интернет модной одежды. Начав в 2007 году с использования монолитного Rails-приложения, к 2009 году компания столкнулась с тем, что используемая система не в состоянии справиться с возлагаемой на нее нагрузкой. Разделив основные части своей системы, Gilt смогла намного успешнее справляться со всплесками трафика, и теперь компания использует 450 микросервисов, каждый из которых запущен на нескольких отдельных машинах.

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

Простота развертывания

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

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

За последние пару лет технология в данной области сильно изменилась, и тема развертывания в мире микросервисов более глубоко будет рассмотрена в главе 6.

Решение организационных вопросов

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

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

Компонуемость

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

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

Оптимизация с целью последующей замены

Если вы работаете в организации среднего размера или крупной, то, скорее всего, знаете, что такое большая, противная, унаследованная от прошлых времен система, стоящая где-то в углу. Никто не хочет к ней даже прикасаться. Но ваша компания не может без нее работать, несмотря на то что она написана на каком-то странном варианте Фортрана и работает только на оборудовании, которое следовало бы списать лет 25 назад. Почему же никто эту систему не заменил? Вы знаете почему: это слишком объемная и рискованная работа.

А в случае использования отдельных небольших по объему сервисов с их заменой на более подходящую реализацию или даже полным удалением справиться гораздо легче. Часто ли вам приходилось удалять более 100 строк кода в день без особых переживаний? При работе с микросервисами, у которых зачастую примерно такой же объем кода, психологический барьер, мешающий их перезаписи или полному удалению, весьма низок.

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

А как насчет сервис-ориентированной архитектуры?

Сервис-ориентированная архитектура (Service-oriented Architecture (SOA)) представляет собой подход в проектировании, при котором несколько сервисов работают совместно для предоставления некоего конечного набора возможностей. Под сервисом здесь обычно понимается полностью отдельный процесс операционной системы. Связь между такими сервисами осуществляется через сетевые вызовы, а не через вызовы методов в границах процесса.

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

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

Многие проблемы на пути развития SOA, по сути, имеют отношение к сложностям, связанным с протоколами обмена данными (например, SOAP), поставщиками связующих программных средств, отсутствием методик, позволяющих определить степень детализации сервисов, или неверными методиками выбора мест разделения системы. На страницах этой книги мы попытаемся найти решение каждой из этих проблем. Циник может предположить, что поставщики скооперировались (и в некоторых случаях выступили единым фронтом) в вопросах продвижения SOA с целью продать как можно больше своих продуктов и эти самые продукты дискредитировали саму цель SOA.

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

Использование микросервисов связано с потребностями реального мира, и для того, чтобы добиться построения качественной SOA, требуется лучше разбираться в системах и архитектурах. Поэтому о микросервисах лучше думать как о конкретном подходе к SOA, в том же ключе, в котором XP или Scrum являются конкретными подходами к разработке гибких программных систем.

Другие технологии декомпозиции

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

Совместно используемые библиотеки

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

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

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

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

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

Модули

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

В качестве одной из технологий подхода к модульной декомпозиции стоит упомянуть спецификацию динамической плагинной (модульной) шины для создания Java-приложений — Open Source Gateway Initiative (OSGI). В самом языке Java понятие «модули» отсутствует, и чтобы увидеть его добавленным к языку, придется, видимо, ждать выхода Java 9. Спецификация OSGI, появившаяся в качестве среды, позволяющей устанавливать дополнительные модули (плагины) в Eclipse Java IDE, используется в данное время в качестве способа подгонки модульной концепции в Java посредством библиотеки.

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

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

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

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

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

Никаких универсальных решений

Перед тем как завершить главу, я должен заявить, что микросервисы не похожи на бесплатный обед или универсальное решение, но их нельзя назвать и негодным вариантом вроде золотого молотка. У них существуют те же сложности, что и у всех распределенных систем, и даже если как следует научиться управлять распределенными системами (о чем, собственно, и будет идти речь в данной книге), легкой жизни я все равно не обещаю. Если вы смотрите на все это с позиции монолитной системы, то, чтобы раскрыть все те преимущества, о которых уже говорилось, придется совершенствоваться в вопросах развертывания, тестирования и мониторинга. Также нужно будет изменить взгляд на расширение своих систем и убедиться в том, что они остаются устойчивыми. И не стоит удивляться, если у вас заболит голова от таких вещей, как распределенные транзакции или теорема CAP!

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

Резюме

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

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