Микросервисы на платформе .NET
Қосымшада ыңғайлырақҚосымшаны жүктеуге арналған QRRuStore · Samsung Galaxy Store
Huawei AppGallery · Xiaomi GetApps

автордың кітабын онлайн тегін оқу  Микросервисы на платформе .NET

 

Кристиан Хорсдал

Микросервисы на платформе .NET

2017

Переводчики Е. Зазноба, И. Пальти

Технические редакторы Г. Блинов, Н. Рощина

Литературный редактор Н. Рощина

Художники С. Заматевская , Г. Синякина (Маклакова)

Корректоры О. Андриевич, Е. Павлович

Верстка Г. Блинов

 

Кристиан Хорсдал

Микросервисы на платформе .NET. — СПб.: Питер, 2017.

 

ISBN 978-5-496-03221-6

© ООО Издательство "Питер", 2017

 

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

 

Предисловие

Когда в издательстве «Мэннинг» мне предложили написать книгу, речь шла о книге, посвященной фреймворку Nancy. С одной стороны, я был рад снова рассказать о Nancy, поскольку это удивительный фреймворк, но я уже написал о нем одну книгу, поэтому мне хотелось, чтобы новое издание было чем-то большим. Я был убе­жден, что Nancy заслуживает не просто описания и демонстрации, но демонстрации в таком контексте, который позволил бы показать, почему Nancy такой удачный фреймворк. Для меня важна простота работы с ним. Nancy дает вам возможность создавать то, что хотите. В то же время это фреймворк с огромным потенциалом, развивающийся по мере роста потребностей пользователей. После некоторых размышлений и обсуждения с издательством «Мэннинг» стало понятно, что необходимый мне контекст для демонстрации Nancy — микросервисы. Микросервисы позволяют быстро создавать «легкие» приложения — как раз это я со временем научился так ценить. Они также подчеркивают необходимость в «легковесных», но вместе с тем обладающих широкими возможностями технологиях, таких как Nancy. На этой стадии все мои идеи о том, какой должна быть книга, начали становиться на свои места: я хотел написать книгу, посвященную скорее проектированию и реа­лизации микросервисов, а не какой-то конкретной технологии, но в то же время демонстрирующую с наилучшей стороны «легковесные» технологии платформы .NET. В итоге получилась книга, которую вы сейчас читаете, и я надеюсь, что вы не только узнаете из нее, как преуспеть в разработке микросервисов, но и осознаете важность тщательного выбора тех библиотек и фреймворков, которые дорожат простотой, не мешают вам и с которыми просто приятно работать.

Что такое микросервис? Микросервис — узконаправленный сервис со следу­ющими свойствами:

• отвечает за отдельный фрагмент функциональности;

• его можно установить отдельно;

• состоит из одного или нескольких процессов;

• имеет собственное хранилище данных;

• небольшая команда разработчиков может поддерживать несколько микросервисов;

• микросервисы допускают замену.

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

Благодарности

Написание книги требует времени — много времени. Так что первые слова благодарности — моей жене Джейн Хорсдэл Гаммельгард (Jane Horsdal Gammelgaard), поддерживавшей меня все это время. Ты потрясающая, Джейн!

Я хотел бы поблагодарить моего редактора Дэна Магарри (Dan Maharry). Благодаря его замечательным советам, мягкому, а иногда и жесткому подталкиванию в нужную сторону и постоянному акцентированию внимания на создании высококачественного произведения моя книга получилась намного лучше, чем могла бы быть без него. Огромная благодарность также техническому редактору Микаэлю Лунду (Michael Lund) за внимательный анализ кода и предложения по его улучшению, а также за критику моих цепочек рассуждений в тех случаях, когда они были маловразумительны. Отдельная благодарность Карстену Стребеку (Karsten Str

b
k) за тщательную вычитку текста.

Моя благодарность также замечательной группе технических экспертов-рецензентов: Энди Киршу (Andy Kirsch), Брайану Расмуссену (Brian Rasmussen), Джемре Менгу (Cemre Mengu), Гаю Мэттью Лакроссу (Guy Matthew LaCrosse), Джеймсу Макгинну (James McGinn), Джеффу Смиту (Jeff Smith), Джиму Макгинну (Jim McGinn), Мэтту Р. Коулу (Matt R. Cole), Мортену Херману Лангьяру (Morten Herman Langkj

r), Нестору Нарваэсу (Nestor Narvaez), Нику Макгиннессу (Nick McGinness), Ронни Хегелунду (Ronnie Hegelund), Самуэлю Бошу (Samuel Bosch) и Шахиду Игбалу (Shahid Iqbal). Они предлагали мне различные темы и другие способы изложения существующих тем, находили ошибки и опечатки в коде и терминологии. Каждый этап процесса рецензирования стал этапом обретения этой книгой ее нынешних очертаний.

Наконец, я хотел бы сказать спасибо сотрудникам издательства «Мэннинг», благодаря которым книга появилась на свет: издателю Маржан Бэйс (Marjian Bace), редактору Грегу Вайлду (Greg Wild), а также всем членам редакционно-издательской команды, включая Тиффани Тэйлор (Tiffany Taylor), Кэти Теннант (Katie Tennant), Мелоди Долаб (Melody Dolab) и Гордана Салиновича (Gordan Salinovic).

Об этой книге

«Микросервисы на платформе .NET» — практическое руководство по написанию микросервисов на основе платформы .NET с помощью простых в использовании облегченных технологий, таких как веб-фреймворк Nancy и промежуточное ПО, созданное по стандарту OWIN (Open Web Interface for .NET — открытый веб-интерфейс для платформы .NET). Я приложил максимум усилий, чтобы представить материал книги в таком виде, который позволил бы вам сразу же начать применять прочитанное на практике. Поэтому я старался везде пояснять, почему делаю что-то именно так, равно как и показывать в подробностях, как именно.

Веб-фреймворк Nancy, используемый на протяжении всей книги, создан Андреа­сом Хокансоном (Andreas Ha°kansson), который по сей день руководит проектом. Через какое-то время к Андреасу присоединился Стивен Роббинс (Steven Robbins), и вдвоем они сделали из Nancy потрясающий фреймворк. В настоящее время его продвигают Андреас, Стивен и их помощники Кристиан Хелланг (Kristian Hellang), Джонатан Шеннон (Jonathan Channon), Дэмиен Хики (Damian Hickey), Филипп Хэйдон (Phillip Haydon) и ваш покорный слуга, а также многочисленное сообщество других разработчиков. Полный список участвующих в разработке и поддержке Nancy можно найти по адресу http://nancyfx.org/contribs.html.

OWIN — открытый стандарт для интерфейсов между веб-серверами и веб-приложениями. Работа над OWIN началась в конце 2010 года усилиями Райана Райли (Ryan Riley), Бенджамина ван дер Веена (Benjamin van der Veen), Маурисио Шеффера (Mauricio Scheffer) и Скотта Куна (Scott Koon). С тех пор множество специалистов внесли свой вклад в разработку спецификаций стандарта OWIN — сначала через группу Google, а потом с помощью GitHub-репозитория OWIN (https://github.com/owin/owin) — и в его реализацию.

Для кого предназначена книга

«Микросервисы на платформе .NET» — книга прежде всего для разработчиков, но дизайнеры и другие специалисты тоже могут многое почерпнуть из нее. При ее написании я ориентировался на .NET-разработчиков, которые хотят начать создавать распределенные серверные системы вообще и микросервисы в частности, поэтому основное внимание уделено тому, что необходимо знать и делать разработчику для написания кода для системы микросервисов. Предполагается, что читатели обладают практическими знаниями в области языка программирования C# и — хотя бы в небольшом объеме — протокола HTTP.

Структура издания

Книга состоит из 12 глав, разделенных на четыре части.

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

• Глава 1 рассказывает, что такое микросервисы и почему они важны. В ней перечислены шесть отличительных признаков микросервисов, которыми я руководствуюсь при их проектировании и реализации. В конце главы мы познакомимся с фреймворком Nancy и стандартом OWIN.

• Глава 2 — комплексный пример написания микросервиса с помощью фреймворка Nancy и стандарта OWIN, а также библиотеки Polly и фреймвор­ка .NET Core. К концу этой главы мы создадим законченный, хотя и простой микросервис.

Часть II охватывает вопросы разбиения системы на микросервисы и реализации функциональности в системе микросервисов.

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

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

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

• Глава 6 объясняет и демонстрирует реализацию некоторых важных методов обеспечения надежности систем микросервисов.

• В главе 7 подробно рассматривается тестирование системы микросервисов, включая тестирование системы в целом, тестирование каждого микросервиса и тестирование кода внутри микросервисов.

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

• Глава 8 детально познакомит вас со стандартом OWIN. В ней вы прочтете о методах построения промежуточного ПО OWIN и узнаете, насколько хорошо промежуточное ПО OWIN подходит для различной сквозной функциональности.

• Глава 9 разъясняет, почему в системе микросервисов так важны мониторинг и журналирование. На базе полученных в главе 8 знаний о стандарте OWIN мы создадим промежуточное ПО для поддержки мониторинга и журналирования микросервисов.

• В главе 10 обсуждается безопасность в системе микросервисов. Сильно распределенная природа системы микросервисов ставит перед нами связанные с безопасностью задачи, которые мы здесь обсудим. Мы также поговорим о возможностях использования промежуточного ПО OWIN в целях реализации различных средств безопасности в микросервисах.

• Глава 11 описывает создание на основе материала глав 9 и 10 платформы микросервисов. Эта платформа создается путем упаковки взятого из предыдущих глав промежуточного ПО OWIN. Такие пакеты NuGet уже готовы для совместного использования микросервисами. Глава включает также пример создания нового микросервиса с помощью этой платформы.

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

В целом эти 12 глав научат вас проектировать и программировать микросервисы с помощью несложных технологий на основе платформы .NET.

Условные обозначения и загрузка кода

В большинстве глав приводятся примеры программ. Их все можно найти в разделе загрузок для данной книги на сайте издательства «Мэннинг» по адресу https://www.manning.com/books/microservices-in-net-core или в репозитории Git на GitHub по адресу https://github.com/horsdal/microservices-in-dotnetcore.

Код основан на фреймворке .NET Core, так что для запуска вам понадобится установить .NET Core, а также соответствующие утилиту командной строки и интегрированную среду разработки (IDE). Информацию по их установке и настройке можно найти в приложении A.

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

В репозитории GitHub, расположенном по адресу https://github.com/horsdal/microservices-in-dotnetcore, ветка master содержит код в том виде, в котором он приведен в книге. При выходе стабильных версий библиотек для платформы .NET Core я планирую создать ветку current и хранить в ней копию кода, который будет поддерживаться в соответствующем текущим версиям библиотек виде на протяжении нескольких лет после выхода издания.

В книге вы найдете множество примеров исходного кода, как в пронумерованных листингах, так и внутри обычного текста. Исходный код листингов показан:

вот таким шрифтом отдельными строками,

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

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

Об авторе

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

Об иллюстрации на обложке

Рисунок на обложке книги называется «Император Китая в парадном облачении, 1700 год». Иллюстрация взята из четырехтомной книги Томаса Джеффериса (Thomas Jefferys) Collection of the Dresses of Different Nations, Ancient and Modern («Сборник платьев различных народов, старинных и современных»), изданной в Лондоне между 1757 и 1772 годом. Титульная страница сообщает, что это раскрашенные вручную гравюры на меди, с усилением цветности гуммиарабиком.

Томаса Джеффериса (1719–1771) называли Географом Его Величества Георга III. Он был английским картографом, гравировал и печатал карты для правительства и различных официальных органов, а также издавал различные коммерческие карты и атласы, большинсктво их которых — Северной Америки. Его работа пробудила интерес к особенностям одежды стран, которые он исследовал и картографировал. Эти особенности блестяще отражены в упомянутом сборнике.

Путешествия ради удовольствия были относительно новым явлением в то время, и сборники, подобные книге Томаса Джеффериса, были очень популярны, знакомя и настоящих, и «диванных» туристов как с другими регионами мира, так и с местными костюмами того времени. Разнообразие рисунков в книгах Джеффериса отражает уникальность и индивидуальность городов и регионов стран 200-летней давности. Изолированные друг от друга, люди говорили на разных диалектах и языках. На улицах или в сельской местности было несложно определить, где человек жил и чем занимался, каков был его социальный статус, просто по тому, как он говорил или какую одежду носил. С тех времен дресс-код изменился, и нет такого регионального разнообразия, столь богатого в тот период. Сейчас зачастую непросто даже определить, с какого континента человек. Наверное, если посмотреть на это с оптимизмом, мы променяли культурное и визуальное многообразие на более разнообразную личную жизнь — или, возможно, более разнообразную и интересную интеллектуальную и техническую жизнь.

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

Часть I. Знакомство с микросервисами

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

Ближе к концу главы 1 мы бегло рассмотрим стек технологий, используемый на протяжении всей книги. Этот стек состоит из фреймворка .NET Core, веб-фреймворка Nancy и стандарта OWIN. В главе 2 вы попробуете создать собственный микросервис. Вы также узнаете о дополнительных возможностях фреймворка Nancy.

1. Первый взгляд на микросервисы

В этой главе:

• понятие микросервиса и его основные отличительные признаки;

• плюсы и минусы микросервисов;

• пример совместной работы микросервисов при обслуживании запроса пользователя;

• использование веб-фреймворка Nancy в простом приложении.

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

1.1. Что такое микросервис

Микросервис (microservice) — сервис, предоставляемый удаленным API для использования остальной системой, обладающий одной и только одной чрезвычайно узконаправленной функциональной возможностью. Например, рассмотрим систему управления складом. Если разбить ее возможности на составные части, получится следующий список.

1. Принимаем поступающий на склад товар.

2. Определяем, где должен храниться новый товар.

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

4. Распределяем маршруты размещения товара между работниками склада.

5. Получаем заказы.

6. Рассчитываем маршруты изъятия товара со склада для составления заказов.

7. Распределяем маршруты изъятия товара между работниками склада.

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

1. По HTTP поступает запрос на приемку нового товара и занесение его в журнал. Он может исходить от другого микросервиса или, возможно, от веб-страницы, используемой диспетчером для регистрации поступившего товара. Микросервис Receive Stock должен зарегистрировать новый товар в собственном хранилище данных.

2. Микросервис отправляет ответ в качестве подтверждения приемки товара.

Рисунок 1.1 демонстрирует получение микросервисом Receive Stock запроса от другого микросервиса, работающего совместно с ним.

 

Рис. 1.1. Микросервис Receive Stock при поступлении нового товара предоставляет для использования API, к которому могут обращаться другие микросервисы

Каждая маленькая возможность в системе реализуется в виде отдельного микросервиса. Любой микросервис в системе:

• работает в собственном отдельном процессе;

• может быть развернут отдельно, независимо от других микросервисов;

• имеет собственное хранилище данных;

• взаимодействует с другими микросервисами для выполнения своих заданий.

Важно также отметить, что микросервисы могут взаимодействовать с другими микросервисами, не обязательно написанными на том же языке программирования (C#, Java, Erlang и т.д.). Все, что им требуется знать, — как обмениваться сообщения­ми друг с другом. Некоторые могут обмениваться сообщениями через служебную шину или двоичный протокол, например Thrift, в зависимости от системных требований, но гораздо чаще микросервисы обмениваются сообщениями по протоколу HTTP.

ПРИМЕЧАНИЕ

Эта книга посвящена созданию микросервисов на платформе .NET с помощью языка программирования C# и веб-фреймворка Nancy. Микросервисы, которые я буду демонстрировать, представляют собой маленькие узкоспециализированные приложения Nancy, взаимодействующие по HTTP.

Какова архитектура микросервисов

Основное внимание в этой книге уделяется проектированию и реализации отдельных микросервисов, но стоит отметить, что термин «микросервисы» можно использовать также для описания архитектурного стиля всей системы, состоящей из множества микросервисов. Микросервисы как архитектурный стиль — упрощенный вариант сервис-ориентированной архитектуры (service-oriented architecture (SOA)), в которой сервисы ориентированы на выполнение одного действия каждый, и выполнения качественного. Система с архитектурой микросервисов представляет собой распределенную систему с, вероятно, значительным количеством совместно работающих микросервисов.

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

Отличительные признаки микросервисов

Как я упоминал, микросервис — это сервис с одной узконаправленной функциональной возможностью. Что эта фраза значит? Поскольку методология микросервисов все еще находится в стадии развития (по состоянию на начало 2016 года), пока не существует общепринятого определения того, что именно представляет собой микросервис1. Можно, однако, посмотреть, что отличает микросервис в целом. Я обнаружил, что существует шесть основных отличительных признаков микросервиса.

1. Микросервис отвечает за одну функциональную возможность.

2. Микросервисы можно развертывать по отдельности.

3. Микросервис состоит из одного или нескольких процессов.

4. У микросервиса имеется собственное хранилище данных.

5. Небольшая команда разработчиков может сопровождать несколько микросервисов.

6. Микросервис можно легко заменить.

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

Ответственность за одну возможность

Микросервис отвечает за одну и только одну функциональную возможность из всей системы. Разделим это утверждение на две составные части.

• На микросервис возлагается ровно одна обязанность.

• Эта обязанность состоит в реализации отдельной возможности.

Принцип единственной обязанности формулируется несколькими различными способами. Одна из традиционных его формулировок: «У класса должна быть только одна причина для изменения»2. Хотя здесь говорится именно о классе, этот принцип может применяться и вне контекста классов в объектно-ориентированных языках программирования. В случае микросервисов принцип единственной обязанности применяется на уровне сервисов.

Более современная формулировка принципа единственной обязанности тоже обязана своим появлением дядюшке Бобу: «Собирайте воедино вещи, меняющиеся по схожим причинам. Отделяйте друг от друга вещи, меняющиеся по различным причинам»3. Эта формулировка данного принципа применима к микросервисам: микросервис должен реализовывать ровно одну функциональную возможность. Таким образом, микросервис должен изменяться только при изменении этой возможности. Более того, вы должны постараться реализовать в микросервисе эту возможность максимально полно, чтобы при ее изменении нужно было менять только один микросервис.

Существует два вида возможностей в системе микросервисов.

Бизнес-возможность — выполняемое системой действие, которое способствует реа­лизации предназначения системы. Например, это может быть отслеживание корзин заказов пользователей или расчет цен. Предметно-ориентированное проектирование — отличный способ разделения системы на отдельные бизнес-возможности.

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

ПРИМЕЧАНИЕ

Определение области действия и обязанностей микросервисов рассматривается в главе 3.

Развертываемость по отдельности

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

Рассмотрим сайт интернет-магазина. При изменении микросервиса Shopping Cart («Корзина заказов») должна быть обеспечена возможность развертывания только этого микросервиса (рис. 1.2).

 

Рис. 1.2. Во время развертывания микросервиса Shopping Cart остальные микросервисы продолжают работать

Тем временем микросервисы Price Calculation («Расчет цены»), Recommendations («Рекомендации»), Product Catalog («Каталог товаров») и другие продолжают работать и обслуживать запросы пользователей.

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

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

• Все микросервисы должны быть встроены в отдельные артефакты или пакеты.

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

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

ПРИМЕЧАНИЕ

Взаимодействие и устойчивость к ошибкам микросервисов мы рассмотрим в главах 4, 5 и 7.

Состоит из одного или нескольких процессов

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

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

• У любого микросервиса может быть более одного процесса.

Вернемся к микросервису Shopping Cart. Если он работает в том же процессе, что и микросервис Product Catalog (рис. 1.3), код микросервиса Shopping Cart может вызывать побочные эффекты в микросервисе Product Catalog. Это означает сильную (и нежелательную) связанность между микросервисами Shopping Cart и Product Catalog: работа одного может приводить к простоям или ошибкам другого.

 

Рис. 1.3. Выполнение нескольких микросервисов в одном процессе ведет к сильной связанности

Теперь рассмотрим развертывание новой версии микросервиса Shopping Cart. Оно или повлечет за собой повторное развертывание микросервиса Product Catalog, или потребует какой-нибудь разновидности динамической загрузки кода, которая бы позволила заменить код микросервиса Shopping Cart в работающем процессе. Первый вариант напрямую противоречит положению об индивидуальной развертываемости микросервисов. Второй же сложен и как минимум ставит микросервис Product Catalog под угрозу сбоя вследствие развертывания микросервиса Shopping Cart.

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

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

Наличие собственного хранилища данных

У микросервиса должно быть собственное хранилище, в котором находятся необходимые ему данные. Это еще одно следствие того, что сфера действия микросервиса — завершенная функциональная возможность. Большей части бизнес-возможностей требуется какое-либо хранилище данных. Например, микросервису Product Catalog необходимо хранить определенную информацию о каждом из товаров. Сохранение слабой связанности микросервиса Product Catalog с другими микросервисами обеспечивается тем, что содержащее информацию о товарах хранилище данных полностью принадлежит ему. Только микросервис Product Catalog определяет, как и когда сохраняется информация о товарах. Как показано на рис. 1.4, другие микросервисы, например микросервис Shopping Cart, могут обращаться к информации о товарах только через интерфейс микросервиса Product Catalog, а не напрямую в хранилище данных Product Catalog.

То, что у каждого микросервиса имеется собственное хранилище данных, позволяет использовать различные технологии баз данных для различных микросервисов в зависимости от потребностей конкретного микросервиса. Например, микросервис Product Catalog может использовать для хранения информации о товарах СУБД SQL Server, микросервис Shopping Cart — хранить содержимое корзин заказов всех пользователей в СУБД Redis, а микросервис Recommendations — использовать для выдачи рекомендаций индекс Elasticsearch. Выбираемые для микросервиса технологии баз данных — часть реализации, невидимая другим микросервисам.

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

 

Рис. 1.4. Один микросервис не может обращаться к хранилищу другого

ПРИМЕЧАНИЕ

Мы рассмотрим владение данными, доступ к ним и их хранение в главе 5.

Возможность сопровождения небольшой командой разработчиков

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

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

Заменяемость

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

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

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

1.2. Почему именно микросервисы?

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

• обеспечивают возможность непрерывной доставки ПО;

• обеспечивают эффективность процесса разработки в силу чрезвычайной легкости их сопровождения;

• изначально выполнены устойчивыми к ошибкам;

• масштабируются в сторону увеличения или уменьшения независимо друг от друга.

Обсудим эти пункты подобнее.

Возможность непрерывной доставки ПО

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

• можно быстро разработать и изменить;

• можно всесторонне тестировать с помощью автоматизированных тестов;

• можно развертывать независимо друг от друга;

• работают эффективно.

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

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

Что такое непрерывная доставка ПО

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

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

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

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

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

Эта книга не посвящена непрерывной доставке ПО или DevOps, но мы предполагаем, что в среде, в которой вы разрабатываете микросервисы, используется непрерывная доставка. Создаваемые в данной книге сервисы можно развертывать в локальных дата-центрах или в облаке с применением любого количества технологий автоматизации развертывания, допускающих использование платформы .NET. Эта книга охватывает последствия применения непрерывной доставки ПО и DevOps для отдельных микросервисов. В части III книги мы подробнее рассмотрим создание платформы, принимающей на себя немало эксплуатационных проблем, с которыми приходится иметь дело всем микросервисам. Кроме того, в приложении Б рассмотрим основные возможности ввода в производственную среду разработанных на протяжении всей книги микросервисов.

Высокий уровень удобства сопровождения

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

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

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

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

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

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

• Все микросервисы можно разворачивать по отдельности.

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

Тенденция к облегченности

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

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

Надежность и масштабируемость

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

1.3. Издержки и недостатки микросервисов

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

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

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

• У каждого микросервиса — собственная база кода. Следовательно, рефакторинг с перемещением кода из одного микросервиса в другой требует больших усилий. Необходимо заранее позаботиться о правильном определении области действия всех микросервисов.

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

Насколько производительны микросервисы

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

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

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

1.4. С нуля или на базе существующей системы?

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

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

• Сильная связанность внутри базы кода.

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

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

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

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

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

• Пойдет ли этой системе на пользу возможность раздельного развертывания подсистем?

• Сможете ли вы создать довольно сильно автоматизированную систему развертывания?

• Достаточно ли хорошо вы знакомы с предметной областью, чтобы правильно распознать и разделить различные независимые бизнес-возможности системы?

• Достаточно ли широка сфера действия системы, чтобы оправдать сложность распределенной архитектуры?

• Достаточно ли широка сфера действия системы, чтобы оправдать затраты на создание системы автоматизации развертывания?

• Просуществует ли проект достаточно долго, чтобы оправдать предварительные вложения средств в автоматизацию и развертывание?

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

1.5. Многократное использование кода

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

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

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

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

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

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

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

1.6. Обслуживание запросов пользователя: пример совместной работы микросервисов

Чтобы понять, как работает микросервисная архитектура, рассмотрим пример: посетитель интернет-магазина добавляет товар в корзину заказов. С точки зрения клиентского кода в систему прикладной части через микросервис API Gateway (API-шлюз) передается запрос Ajax, а возвращается обновленная корзина с информацией о цене. Это простое взаимодействие показано на рис. 1.5. Мы вернемся к разговору об API-шлюзах в главе 12.

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

 

Рис. 1.5. Код клиентской части, выполняя запрос для добавления товара в корзину заказов, обменивается сообщениями только с микросервисом API-шлюза. Происходящее «за кулисами» шлюза не видно

Основная обработка пользовательского запроса

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

 

Рис. 1.6. Клиент видит только микросервис API Gateway, но это лишь тонкий наружный слой системы микросервисов. Стрелки обозначают обращения между различными частями системы, а номера на них показывают последовательность вызовов

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

• Микросервис API-шлюза отвечает только за беглую проверку входящего запроса. После проверки выполнение задачи передается сначала микросервису Shopping Cart, а затем микросервису Price Calculation.

• Микросервис Shopping Cart использует другой микросервис — Product Catalog — для поиска нужной информации о добавленном в корзину товаре. После этого Shopping Cart сохраняет информацию о корзине заказов пользователя в своем хранилище данных и возвращает микросервису API Gateway представление обновленной корзины. Ради повышения производительности и большей устойчивости к ошибкам микросервис Shopping Cart, вероятно, будет кэшировать поступающие от микросервиса Product Catalog ответы.

• Микросервис Price Calculation использует текущие бизнес-правила интернет-магазина для расчета общей цены товаров в корзине заказов пользователя с учетом всех применимых в данном случае скидок.

Каждый из этих совместно выполняющих запрос пользователя микросервисов предназначен для решения конкретной узкой задачи и знает об остальных микросервисах настолько мало, насколько это возможно. Например, микросервис Shopping Cart ничего не знает о ценообразовании или микросервисе Price Calculation, а также о том, как товары хранятся в микросервисе Product Catalog. Это основная идея микросервисов: на каждый из них возлагается только одна обязанность.

Побочные действия пользовательских запросов

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

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

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

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

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

Выполнение побочных действий запускает публикуемое микросервисом Shopping Cart событие ItemAddedtoCart. Два других микросервиса, подписанных на исходящие от микросервиса Shopping Cart события, выполняют соответствующие действия при наступлении событий, таких как ItemAddedtoCart. Эти два подписчика реагируют на события асинхронно — вне контекста исходного запроса, так что побочные действия могут выполняться параллельно с основным потоком обработки запроса или после его завершения.

 

Рис. 1.7. Микросервис Shopping Cart публикует события, а другие подписанные на него микросервисы реагируют на них

Примечание

Реализация подобного взаимодействия, основанного на потоках событий, рассматривается в главе 4.

Общая картина

В целом в обработке запроса на добавление товара в корзину заказов участвуют шесть микросервисов (рис. 1.8). Ни один из них не знает ничего о внутреннем устройстве остальных. У пяти микросервисов есть собственные хранилища данных, обслуживающие только их. Часть обработки происходит синхронно в контексте пользовательского запроса, а часть — асинхронно.

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

После подробного рассмотрения конкретного примера обработки пользовательского запроса системой микросервисов пришло время ненадолго остановиться на стеке технологий платформы .NET для микросервисов.

 

Рис. 1.8. При добавлении пользователем товара в свою корзину заказов клиентская часть делает запрос к микросервису API gateway, который совместно с другими микросервисами выполняет запрос. Во время обработки микросервисы могут порождать события, на которые другие микросервисы могут подписываться и затем обрабатывать их асинхронно

1.7. Стек технологий платформы .NET для микросервисов

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

Фреймворк Nancy

Nancy (http://nancyfx.org/) — основанный на платформе .NET веб-фреймворк с открытым исходным кодом, явным образом декларирующий своей целью предоставление разработчикам супер-пупер-крутого способа разработки веб-приложений и сервисов. Термин «супер-пупер-крутой способ» в данном случае описывает базовые принципы фреймворка Nancy.

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

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

• Фреймворк Nancy не требует особых формальностей и не мешает вам работать. При создании приложения Nancy фреймворк не становится на вашем пути. API спроектированы гибкими, они позволяют писать код так, как вам удобно. Другими словами, при использовании фреймворка Nancy можно сосредоточиться на коде своего приложения, а не разбираться с Nancy.

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

Благодаря этим базовым принципам и обеспечиваемому ими супер-пупер-крутому способу разработки Nancy — мой излюбленный веб-фреймворк для создания микросервисов на платформе .NET. Мы будем использовать Nancy на протяжении всей книги, и по мере описания трудностей реализации микросервисов я продемонстрирую множество его возможностей. В последнем разделе этой главы вы увидите небольшой фрагмент кода приложения Nancy. Однако сначала я хотел бы познакомить вас со стандартом OWIN.

Стандарт OWIN

Открытый веб-интерфейс для платформы .NET (Open Web Interface for .NET, OWIN, http://owin.org/) — это открытый стандарт, описывающий интерфейс между веб-серверами .NET и веб-приложениями .NET. Интерфейс OWIN отцепляет веб-сервер и веб-приложение друг от друга. OWIN-совместимый веб-сервер, получив HTTP-запросы из сети, передает их на обработку веб-приложению через стандартизованный интерфейс OWIN. Такой веб-сервер не знает никаких подробностей о веб-приложении. Все, что ему известно и важно для него, — это то, что веб-приложение может получать запросы через интерфейс OWIN. Аналогично веб-приложение не знает ничего о веб-сервере. Оно знает только, что через интерфейс OWIN поступают запросы.

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

...