Декабрь 2015

Том 30, номер 13

Microsoft Azure - Azure Service Fabric и архитектура микросервисов

Сесар де ла Торре, Кунал Дип Сингх и Вацлав Туречек | Декабрь 2015

Продукты и технологии:

Микросервисы, Microsoft Azure, Azure Service Fabric, ASP.NET, MVC

В статье рассматриваются:

  • архитектура микросервисов и ее поддержка приложений и сервисов, созданных в расчете на масштабируемость и гибкость;
  • преимущества Microsoft Azure Service Fabric, новой Microsoft Platform as a Service (PaaS), которая упрощает разработку и эксплуатацию приложений на основе микросервисов;
  • знакомство с моделями программирования Azure Service Fabric;
  • создание микросервисов без поддержки состояний, используя Azure Service Fabric, и введение в Reliable Services и Actor Services с поддержкой состояний.

Микросервисы — популярное сейчас модное слово. Хотя на эту тему проводится много презентаций и об этом часто говорят на конференциях, у большинства разработчиков все равно возникает уйма вопросов. Самый частый вопрос, который мы слышим: «Разве это не очередная архитектура, ориентированная на сервисы (SOA), или какая-то разновидность подхода на основе DDD (domain-driven design)?».

Определенно многие методы, применяемые в подходе на основе микросервисов, вытекают из опыта разработок с использованием SOA и DDD. Микросервисы можно рассматривать как «SOA по-настоящему», причем всех их концепции и шаблоны вроде автономных сервисов и шаблона Bounded-Context имеют свои корни в SOA и DDD.

В этой статье мы уделяем внимание как теории, так и реализации микросервисов. Мы начнем с краткого введения в микросервисы, а затем перейдем к практической стороне и тому, как можно создавать и развертывать микросервисы, используя Azure Service Fabric. Наконец, мы покажем, почему эта платформа отлично подходит для создания микросервисов.

Само название предполагает, что архитектура микросервисов является подходом к созданию серверного приложения как набора малых сервисов, где каждый сервис выполняется в своем процессе и взаимодействует с остальными сервисами по таким протоколам, как HTTP и WebSockets. Каждый микросервис реализует специфические возможности в предметной области и свою бизнес-логику в рамках определенного Bounded-Context в каждом сервисе, должен разрабатываться автономно и независимо развертываться через автоматизированные механизмы. Наконец, у каждого сервиса должны быть соответствующие собственные модель данных и логика предметной области; для каждого микросервиса можно применять разные технологии хранилищ (SQL, NoSQL) и разные языки программирования.

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

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

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

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

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

Подход на основе микросервисов в сравнении с традиционным подходом на основе серверных приложений

Рис. 1. Подход на основе микросервисов в сравнении с традиционным подходом на основе серверных приложений

Microservices Approach Подход на основе микросервисов
App 1 Приложение 1
App 2 Приложение 2
A microservice approach segregates functionality into small autonomous services. При подходе на основе микросервисов функциональность разбивается на малые автономные сервисы
And scales out by deploying independently and replicating these services across servers/VMs/containers. И масштабируется независимым развертыванием и репликацией этих сервисов по серверам/VM/контейнерам
VS. это убрать, сравнение и так очевидно
Traditional Approach Традиционный подход
A traditional application (Web app or large service) usually has most of its functionality within a single process (usually internally layered, though). Большая часть функциональности традиционного приложения (веб-приложения или большого сервиса), как правило, находится в одном процессе (но обычно она разделяется на внутренние уровни)
And scales by cloning the whole app on multiple servers/VMs/containers. И масштабируется клонированием всего приложения на множестве серверов/VM/контейнеров

Независимость данных каждого микросервиса

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

Этот подход означает, что концептуальная модель предметной области будет различаться между подсистемами или микросервисами. Возьмем корпоративные приложения, где каждое приложение для управления отношениями с клиентами (customer relationship management, CRM), транзакционная подсистема покупок и подсистема поддержки клиентов обращаются к атрибутам и данным уникальной сущности customer и используют свой Bounded-Context.

Этот принцип аналогичен таковому в DDD, где каждый Bounded-Context, который является шаблоном, сравнимым с подсистемой/сервисом, должен владеть собственной моделью предметной области (данными и логикой). Каждый DDD Bounded-Context должен был бы сопоставляться со своим микросервисом.

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

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

Рис. 2. Независимость данных в микросервисах и монолитных блоках приложениях

Microservices Approach Подход на основе микросервисов
UI UI
Presentation services Презентационные сервисы
Stateful services Сервисы с состоянием
Stateless services with related databases Сервисы без состояния со связанными базами данных
Model/Database per Microservice Модель/база данных на каждый микросервис
Traditional Application Традиционное приложение
Single app process or 3-Tier approach
Several modules
Layered modules
  • Один процесс приложения или трехуровневый подход
  • Несколько модулей
  • Многоуровневые модули
3-Tier Approach Трехуровневый подход
Single App Process Один процесс приложения
Or Или
Single Monolithic Database Единая монолитная база данных

Микросервисы с состоянием или без?

Как уже упоминалось, у каждого микросервиса должна быть своя модель предметной области. В случае микросервисов без состояния базы данных будут внешними — с применением как реляционных СУБД вроде SQL Server, либо нереляционных СУБД на основе NoSQL, например MongoDB или Azure DocumentDB. Однако сами сервисы могут поддерживать состояние, т. е. данные будут находиться в том же микросервисе. Эти данные могут существовать не только в рамках одного и того же сервера, но и внутри того же процесса микросервиса, в памяти, а также храниться на жестком диске и реплицироваться на другие узлы.

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

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

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

Преимущества Azure Service Fabric

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

Что такое Service Fabric? Это платформа распределенных систем, используемая для создания в высшей степени масштабируемых, надежных и легко управляемых облачных приложений. Service Fabric устраняет многие проблемы в разработке и управлении облачными приложениями. Используя Service Fabric, разработчики и администраторы могут избавиться от решения сложных инфраструктурных задач и вместо этого сосредоточиться на реализации критически важных, требовательных к ресурсам рабочих нагрузок, зная, что они масштабируемые, надежные и управляемые. Service Fabric представляет платформу промежуточного программного обеспечения Microsoft следующего поколения для создания и управления масштабируемых облачных сервисов корпоративного класса.

Service Fabric — это универсальная среда развертывания; вы можете развернуть исполняемый файл, написанный на любом языке (Microsoft .NET Framework, Node.js, Java, C++), или даже базу данных вроде MongoDB.

Таким образом, важно прояснить, что Azure Service Fabric не ограничивается только приложениями на основе микросервисов. Вы также можете использовать ее для хостинга и развертывания традиционных веб-приложений или сервисов и получить значительную выгоду от масштабируемости, балансировки нагрузки и быстрого развертывания. Тем не менее, Azure Service Fabric является новой платформой, созданной с нуля и предназначенной прежде всего для систем на основе микросервисов с высочайшей масштабируемостью (рис. 3).

Microsoft Azure Service Fabric

Рис. 3. Microsoft Azure Service Fabric

Microservices Микросервисы
High Availability Высокая доступность
Simple Programming Models Простые модели программирования
Hybrid Operations Гибридные операции
High Density Высокая плотность
Hyper-Scale Высочайшая масштабируемость
Data Partitioning Разбиение данных на разделы
Rolling Upgrades Развертывание обновлений
Automated Rollback Автоматический откат
Service Fabric Service Fabric
Low Latency Низкая латентность
Stateful Services Сервисы с состоянием
Health Monitoring Мониторинг работоспособности
Placements Constraints Ограничения на размещение
Fast Startup & Shutdown Быстрый запуск и завершение
Container Orchestration & Lifecycle Management Координация контейнеров и управление жизненным циклом
Load Balancing Балансировка нагрузки
Self-Healing Самовосстановление
Replication & Failover Репликация и преодоление отказов
Windows Server Windows Server
Linux Linux
Azure Azure
Private Clouds Частные облака
Hosted Clouds Размещаемые облака

Ниже перечислены некоторые преимущества Service Fabric.

  • Работает в Azure, на предприятиях или в любом облаке Очень важная характеристика Service Fabric — возможность выполнения не только в Azure, но и на предприятии, на ваших серверах или виртуальных машинах (VM) — и даже в сторонних облаках. Никакой привязки к конкретному облаку нет. Вы могли бы запустить кластер Service Fabric даже в Amazon Web Services (AWS).
  • Поддерживает Windows или Linux В настоящее время (на конец 2015 года) Service Fabric поддерживает Windows, а также Linux и контейнеры (образы Windows и Docker).
  • Тщательно проверена Используется Microsoft в течение нескольких лет для поддержки многих из ее облачных продуктов.

Service Fabric родилась из-за потребности в создании крупномасштабных сервисов в рамках Microsoft. Для создания облачных сервисов, например Azure SQL Database на основе SQL Server, и обеспечения их гибкости, надежности, масштабируемости и экономичности была нужна некая распределенная технология, которая эффективно отвечала бы всем этим требованиям. Хотя базовая технология, решавшая эти сложные задачи, уже существовала, было очевидно, что SQL Server — не единственный продукт, подвергающийся такой трансформации. В продуктах вроде Skype for Business приходилось решать сходные проблемы на пути к преобразованию в приложение на основе микросервисов. Service Fabric — прикладная платформа, которая развивалась, исходя из этих вызовов, и использовалась во многих крупномасштабных сервисах в Microsoft, имеющих разные архитектуры и работающих с разными требованиями к уровню масштабирования. InTune, DocumentDB и серверная часть для Cortana и Skype for Business — все это сервисы, выполняемые в Service Fabric.

Что такое Service Fabric? Это платформа распределенных систем, используемая для создания в высшей степени масштабируемых, надежных и легко управляемых облачных приложений.

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

Модели программирования в Azure Service Fabric

Service Fabric предлагает две высокоуровневые инфраструктуры для создания сервисов: Reliable Services API и Reliable Actors API. Хотя обе построены на одном и том же ядре Service Fabric, они обеспечивают разный баланс между простотой и гибкостью в отношении параллельной обработки, разбиения на разделы и коммуникации, как показано в табл. 1. Полезно понимать, как работают обе модели, чтобы вы могли делать оптимальный выбор конкретной инфраструктуры для своего сервиса. Во многих прикладных сценариях можно задействовать гибридный подход, используя акторы для определенных микросервисов, и применять надежные сервисы для агрегации данных, генерируемых рядом акторов. Поэтому надежный сервис мог бы координировать сервисы-акторы (actor services) во многих распространенных сценариях.

Табл. 1. Сравнение моделей программирования в Service Fabric

Reliable Actor API Reliable Services API
Ваш сценарий включает много малых независимых единиц/объектов состояния и логики (хорошие примеры — активные объекты Интернета вещей [Internet of Things, IoT] или игровые серверы) Вам нужно поддерживать логику и запросы между несколькими типами сущностей и компонентами
Вы работаете с массивным количеством однопоточных объектов, но должны иметь возможность масштабирования и поддерживать согласованность Вы используете надежные наборы (вроде .NET отказоустойчивых Dictionary и Queue из .NET) для хранения и управления состоянием/сущностями
Вам нужна инфраструктура для управления параллельной обработкой и детализацией состояния Вы хотите управлять детализацией и параллельной обработкой состояния
Вам нужна Service Fabric, чтобы управлять реализацией коммуникаций за вас Вы хотите сами выбирать, управлять и реализовать коммуникационные протоколы (Web API, WebSockets, Windows Communication Foundation и др.)
Вам нужна Service Fabric для управления схемой разбиения на разделы в сервисах-акторах с состоянием, чтобы оно было прозрачным для вас Вам требуется контролировать схему разбиения на разделы вашим сервисом с состоянием

Создание микросервисов без состояния с помощью Azure Service Fabric

Микросервисом в Azure Service Fabric может быть почти любой процесс на сервере, который вы хотите создать с использованием .NET Framework, Node.js, Java или C++. В настоящее время в Service Fabric API доступны только библиотеки .NET и C++. Поэтому вы должны создавать низкоуровневые реализации микросервисов в .NET Framework или на C++.

Как упоминалось, микросервис без состояния выполняется в процессе (например, клиентский сервис или сервис бизнес-логики), но в этом сервисе буквально нет состояния или же состояние есть, но оно теряется при завершении процесса и не требует синхронизации, репликации, сохранения или высокой доступности. У него могло бы быть внешнее состояние, но сохраняемое во внешнем хранилище, таком как Azure SQL Database, Azure Storage, Azure DocumentDB или любой сторонний механизм хранения (реляционный или NoSQL). Поэтому любой существующий сервис вроде ASP.NET Web API, выполняемый в Cloud Services, Worker Role или Azure Web App, можно было бы легко превратить в сервис Service Fabric без состояния.

Чтобы подготовить среду разработки, вам понадобится Service Fabric SDK, который позволяет запустить локальный кластер разработки, который не является эмулятором, а выполняет те же биты, что и в Azure. Кроме того, интеграция инструментария в Visual Studio 2015 упрощает разработку и отладку.

Прежде чем развертывать и отлаживать сервисы на локальной машине, вы должны создать кластер узлов. Для этого вы запускаете скрипт Windows PowerShell с именем DevClusterSetup.ps1, как поясняется в разделе «Install and Start a Local Cluster» на странице документации «Prepare Your Development Environment» (bit.ly/1Mfi0LB). Вы можете обратиться к этой странице за полным описанием процесса подготовки.

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

Базовый класс сервиса без состояния Любой класс сервиса без состояния в Service Fabric должен наследовать от класса Microsoft.ServiceFabric.Services.StatelessService. Этот класс предоставляет API-методы и контекст, относящиеся к кластеру Service Fabric и исполняющей среде, и включается в жизненный цикл вашего сервиса.

Имеет ваш сервис состояние или нет, Reliable Services предоставляет простой жизненный цикл, позволяющий быстро подключать ваш код и приступать к работе. Чтобы создать и запустить сервис Service Fabric, на самом деле нужно реализовать всего один или два метода — обычно RunAsync и CreateServiceReplicaListeners, которые мы поясним, когда будем рассматривать коммуникационные протоколы.

Обратите внимание на RunAsync (рис. 4). Именно здесь ваш сервис может выполнять работу в фоновом режиме. Передаваемый маркер отмены (cancellation token) сигнализирует, когда эту работу следует прекратить.

Рис. 4. Базовая структура сервиса без состояния в Azure Service Fabric

using Microsoft.ServiceFabric.Services;
namespace MyApp.MyStatelessService
{
  public class MyStatelessService : StatelessService
  {
    //...реализация сервиса

    protected override async Task RunAsync(
      CancellationToken cancellationToken)
    {
      int iterations = 0;
      while (!cancellationToken.IsCancellationRequested)
      {
        ServiceEventSource.Current.ServiceMessage(this,
          "Working-{0}", iterations++);

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

         await Task.Delay(TimeSpan.FromSeconds(1),
           cancellationToken);
      }
    }
  }
}

Коммуникационные протоколы в Azure Service Fabric Reliable Services Reliable Services предоставляют подключаемую модель коммуникаций. Вы можете использовать транспорт по своему выбору, например HTTP с ASP.NET Web API, WebSockets, Windows Communication Foundation, пользовательские TCP-протоколы и т. д.

Вы можете написать свой код для выбранного вами коммуникационного протокола сервиса или использовать любой коммуникационный стек, предоставляемый с Service Fabric, например ServiceCommunicationListener/ServiceProxy, который является коммуникационным стеком по умолчанию инфраструктуры Reliable Services в Service Fabric. Кроме того, появятся отдельные NuGet-пакеты с дополнительными коммуникационными стеками, которые вы сможете подключить в Service Fabric.

ПрименениеASP.NET Web API в микросервисахService Fabric Как упоминалось, Service Fabric позовляет вам решать, как должны взаимодействовать ваши сервисы, но один из наиболее распространенных способов создания HTTP-сервисов в .NET Framework — использование ASP.NET Web API.

Web API в Service Fabric — это все тот же ASP.NET Web API, который вы знаете и любите. Вы используете контроллеры, HttpRoutes и можете создавать REST-сервисы в том же стиле, применяя MapHttpRoute или атрибуты методов, которые нужно сопоставить с маршрутами HTTP. Отличие при использовании Service Fabric в том, как вы размещаете приложение Web API. Прежде всего примите во внимание, что задействовать IIS в Azure Service Fabric нельзя, так как он использует только обычные процессы, реплицируемые в границах кластера, поэтому вы должны сами размещать HTTP-слушатель в собственном коде. Сделать это для сервисов Web API можно двумя способами:

  • применить ASP.NET 5 Web API (кодовое название «Project K») для самостоятельного хостинга HTTP-слушателя в своем процессе микросервисов Service Fabric;
  • задействовать OWIN/Katana и ASP.NET 4.x Web API для той же задачи.

Выполнение ASP.NET 5 поверх Azure Service Fabric лучше всего подходит для создания микросервисов, поскольку Service Fabric позволяет развертывать любое количество сервисов на каждом узле/VM, обеспечивая высокую плотность микросервисов на каждый кластер. Вдобавок такая высокая плотность еще больше увеличится, когда в Service Fabric в будущем появится поддержка .NET Core 5 и CoreCLR (ниже ASP.NET 5). Это будет «лучший выбор» для достижения высочайшей плотности микросервисов, так как .NET Core 5 является облегченной инфраструктурой с очень малой занимаемой памятью в сравнении с полной .NET 4.x Framework.

Применение «MVC-типа»веб-приложений и микросервисовService Fabric ASP.NET MVC — очень популярная инфраструктура для традиционных веб-сайтов, но «старую» инфраструктуру MVC (MVC версии 5 или ниже) нельзя использовать с Service Fabric. Дело в том, что в Service Fabric вы должны обеспечить самостоятельный хостинг (self-hosting) HTTP-слушателя в своем процессе и что OWIN/Katana не поддерживается в ASP.NET 4.x MVC. (Соответствующая поддержка есть только в ASP.NET 4.x Web API.) Поэтому у вас есть следующие варианты для реализация «MVC-типа» веб-приложения на основе сервисов Service Fabric.

  • Используйте MVC 6 в ASP.NET 5 для самостоятельного хостинга HTTP-слушателя внутри процесса микросервисов Service Fabric. Она поддерживает MVC, потому что в ASP.NET 5 Web API и MVC объединены и, по сути, являются инфраструктурой с теми же контроллерами безо всякой зависимости от IIS. Как только ASP.NET 5 будет официально выпущена, этот вариант станет предпочтительным.
  • Используйте ASP.NET 4.x Web API с OWIN/Katana для самостоятельного хостинга HTTP-слушателя внутри процесса микросервисов Service Fabric и симуляции MVC-контроллеров с помощью контроллеров Web API. Также применяйте HTML/JavaScript-вывод вместо обычного контента Web API (JSON/XML). На странице документации по ссылке bit.ly/1UMdKIf демонстрируется, как реализовать этот вариант.

Реализация самостоятельного хостинга с помощью ASP.NET 4.x Web API и OWIN/Katana

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

Метод CreateServiceReplicaListeners в классе сервиса В этом методе сервиса определяются коммуникационные стеки, которые вы хотите использовать. Коммуникационный стек, такой как Web API, определяет конечные точки прослушивания для сервиса и то, как поступающие сообщения будут взаимодействовать с остальным кодом сервиса.

Возвращаясь к классу сервиса, упомянутому ранее в табл. 1, теперь я должен просто добавить новый метод с именем CreateServiceReplicaListeners, указывающий хотя бы один коммуникационный стек, который я хочу задействовать. В данном случае это OwinCommunicationListener, используемый Web API, как показано на рис. 5.

Рис. 5. Добавление метода CreateServiceReplicaListeners в класс сервиса без состояния

using Microsoft.ServiceFabric.Services;
namespace MyApp.MyStatelessService
{
  public class MyStatelessService : StatelessService
  {
    //...реализация сервиса

    protected override async Task RunAsync(
      CancellationToken cancellationToken)
    {
      // Здесь вы пишете свою логику фоновой работы.
      // ...
    }

    protected override IEnumerable<ServiceReplicaListener>
      CreateServiceReplicaListeners()
    {
      return new List<ServiceReplicaListener>()
      {
        new ServiceReplicaListener(parameters =>
          new OwinCommunicationListener(
          "api", new Startup()))
      };
    }
  }
}

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

Класс OwinCommunicationListener — это стереотипный код, который вы повторно использовали бы во всех своих микросервисах. Аналогичным образом можно было бы подключить другие протоколы (WCF, WebSockets и т. д.).

Если вы создаете микросервис Web API, то у вас по-прежнему будут контроллеры с типичным кодом, ничем не отличающимся от того, который вы, возможно, писали при реализации сервисов Web API, например:

// Типичная реализация класса сервиса в Web API
public class CustomerController : ApiController
{
  //// Пример: GET /customers/MSFT
  [HttpGet]
  [Route("customers/{customerKey}", Name = "GetCustomer")]
  public async Task<IHttpActionResult> GetCustomer(
    string customerKey)
  {
    // ...реализация метода без состояния
  }
}

Поскольку статья является обзором Azure Service Fabric и микросервисов, мы не станем углубляться в дальнейшую реализацию OWIN в микросервисе Service Fabric. На GitHub имеется простой пример, который можно скачать и проанализировать (bit.ly/1OW5Bmj): «Web API and Service Fabric HelloWorld Example (ASP.NET 4.x)».

Реализация самостоятельного хостинга с помощью ASP.NET 5 Web API

Выполнение ASP.NET 5 поверх Azure Service Fabric лучше всего подходит для создания микросервисов, поскольку Service Fabric позволяет развертывать любое количество сервисов на каждом узле/VM, обеспечивая высокую плотность микросервисов на каждый кластер. В ASP.NET 5 также есть ряд интересных особенностей.

  • Гибкий хостинг Теперь вы можете разместить свое приложение ASP.NET 5 в IIS или в собственном процессе. Хостинг в собственном процессе является принципиально важным в Azure Service Fabric.
  • Web API, MVC и Web Pages Все эти технологии объединены в одно целое, что привело к упрощению ряда концепций.
  • Полная поддержка приложений под разные версии .NET Приложения ASP.NET 5 теперь можно устанавливать в систему, не затрагивая любые другие приложения, которые, возможно, используют другую версию .NET Framework. Это очень важно для IT-отделов.
  • Кросс-платформенная поддержка ASP.NET 5 выполняется и поддерживается в Windows, Mac OS X и Linux.
  • Готовность к работе в облаке Функциональность вроде диагностики, состояния сеанса, кеш и конфигурирование рассчитаны на работу как локально, так и в облаке (например, Azure) без изменений.

Хотя поддержка .NET Core и CoreCLR пока еще разрабатывается для Service Fabric, ее преимущества очевидны уже сейчас. Выполнение ASP.NET 5 поверх .NET Core 5 образует облегченную инфраструктуру .NET, а исполняющая среда CoreCLR занимает очень малый объем памяти в сравнении с традиционной .NET 4.x. Эта комбинация обеспечит невероятную плотность микросервисов, как показано в секции «Микросервис B» на рис. 6.

Сравнение ASP.NET 5, выполняемой в CLR и CoreCLR в контексте Service Fabric

Рис. 6. Сравнение ASP.NET 5, выполняемой в CLR и CoreCLR в контексте Service Fabric

Azure Service Fabric Context Контекст Azure Service Fabric
Microservice A Микросервис A
ASP.NET 5
Unified single framework for MVC, Web API and SignalR services
ASP.NET 5
Объединенная инфраструктура для сервисов MVC, Web API и SignalR
.NET Framework 4.6 .NET Framework 4.6
CLR CLR
Now! As Preview on top of Service Fabric Сейчас!
Как версия Preview поверх Service Fabric
Traditional full .NET Framework Fully featured and integrated Support for Windows Традиционная полная версия .NET Framework
Полнофункциональная и интегрированная
Поддержка Windows
ASP.NET 5 is the same! Та же самая ASP.NET 5!
Microservice B Микросервис B
.NET Core 5 .NET Core 5
CoreCLR CoreCLR
Future! Will come eventually to Service Fabric В будущем!
Появится в Service Fabric
Lightweight Framework Small memory footprint Modular and optimized Cross-platform beyond Windows Облегченная инфраструктура
Малый объем занимаемой памяти
Модульная и оптимизированная
Кросс-платформенная поддержка (не только Windows)

Хотя поддержка .NET Core 5 и CoreCLR появятся лишь в будущем, предприятия могут готовиться к ней уже сейчас, разрабатывая сервисы ASP.NET 5, выполняемые поверх .NET 4.x в Service Fabric. Это облегчит переход на CoreCLR в дальнейшем.

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

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

Высокая плотность микросервисов — крупное преимущество, если вы заинтересованы в снижении расходов на инфраструктуру. Кластер Service Fabric — это пул VM/серверов (а в будущем и контейнеров), называемых узлами кластера. На каждом узле Service Fabric автоматически развертывает несколько сервисов, поэтому в зависимости от мощности каждого сервера/VM можно добиться сверхвысокой плотности микросервисов в кластере.

В Azure Service Fabric можно запускать сотни экземпляров сервисов на каждой машине или VM. Это обеспечивает значительное уменьшение совокупной стоимости владения (Total Cost of Ownership, TCO). Для того же количества сервисов вам потребуется меньше аппаратного обеспечения. Поэтому высокая плотность — важный фактор, определяющий различия при сравнении Azure Service Fabric с Azure Cloud Services, где вы ограничены одной VM на сервис. Если бы развертывали микросервисы как веб- или рабочую роль, то, вероятно, одному сервису выделялось бы слишком много ресурсов, вызывая замедления при эксплуатации и управлении. Например, на рис. 7 вы видите по одной VM на каждый экземпляр сервиса в форме веб- или рабочей роли Azure (оттенки серого цвета указывают типы сервиса, а каждая фигура или блок обозначает другую VM и экземпляр сервиса). Этот подход не поможет добиться высокой плотности микросервисов, если только вы не будете использовать малые VM. Тем не менее, существует ограничение, и вы не сумеете достичь того же уровня высокой плотности при любом варианте развертывания в сравнении с Azure Service Fabric.

Сравнение плотности сервисов: Azure Cloud Services иService Fabric

Рис. 7. Сравнение плотности сервисов: Azure Cloud Services и Service Fabric

Azure Cloud Services (Web and Worker Roles) Azure Cloud Services
(веб- и рабочие роли)
1 service per VM with uneven workloads
Lower compute density
Slow in deployment and upgrades
  • один сервис на VM с неравномерными рабочими нагрузками
  • меньшая плотность
Slower in scaling and disaster recovery
  • медленное развертывание и обновление
  • более медленное масштабирование и восстановление после катастроф
Azure Service Fabric (Stateless, Stateful or Actor Services) Azure Service Fabric
(сервисы без состояния, с состоянием и сервисы-акторы)
Many microservices per VM
High microservices density
Fast deployment and upgrades
Fast scaling microservices across the cluster
  • множество микросервисов на VM
  • высокая плотность микросервисов
  • быстрое развертывание и обновление
  • быстрое масштабирование микросервисов в границах кластера

В противоположность этому Service Fabric позволяет развертывать любое количество микросервисов на каждом узле, поэтому плотность сервисов гораздо выше при меньшей стоимости. У вас могут быть десятки, сотни или даже тысячи VM/серверов в кластере с десятками или сотнями экземпляров микросервисов и реплик на каждый узел/VM. А поскольку каждый микросервис — это просто некий процесс, развертывание и масштабирование осуществляется гораздо быстрее, чем создание новой VM для каждого сервиса, как в случае облачных сервисов Azure.

Создание кластера в облаке Azure Перед развертыванием микросервисов вы должны создать кластер узлов в Azure или на серверах предприятия. Создав кластер в облаке Azure (как производственную или промежуточную среду), вы можете работать напрямую с Azure Portal или использовать Azure Resource Manager (ARM). На рис. 8 показан кластер Service Fabric, созданный нами по нашей Azure Subscription с помощью Azure Portal. «За кулисами» процесс создания кластера использует Azure ARM и Azure Resource Groups. В данном случае мы создали кластер с пятью узлами/VM, которые также помещены внутрь Azure Resource Group.

Кластер Service Fabric в Azure Portal

Рис. 8. Кластер Service Fabric в Azure Portal

Развертывание приложений/сервисов на кластере Подготовив и запустив кластер, можно развертывать сервисы. При развертывании на производственные кластеры обычно используют скрипт Windows PowerShell для установки приложений/сервисов в кластер в Azure, а для промежуточной или тестовой среды можно выполнять развертывание прямо из Visual Studio.

При развертывания на локальном кластере на вашем компьютере для разработок с использованием Visual Studio 2015 вы обычно щелкаете правой кнопкой мыши проект приложения Service Fabric и выбираете команду Deploy. Кроме того, можно задействовать Windows PowerShell для развертывания на кластер разработки на вашем лэптопе, поскольку на таком кластере выполняются те же биты Service Fabric, что и в облачном кластере Azure.

Для беспроблемного выполнения сервисов в долгосрочной перспективе нужно управлять развернутыми сервисами, и средства управления жизненным циклом приложения встроены в Service Fabric; при этом учитывается подход на основе микросервисов. Средства эксплуатации и управления, доступные в Service Fabric, включают функционал быстрого развертывания, обновления приложений без их остановки, мониторинг работоспособности сервисов, а также увеличение и уменьшение масштаба кластера. Обновления без остановки приложений возможны потому, что технология обновления в Service Fabric обеспечивает комбинацию развертывания обновлений и автоматические проверки работоспособности, при которых распознаются и откатываются изменения в обновлении, если они дестабилизируют приложение. Управлять кластерами и приложениями Service Fabric можно командами Windows Powershell, которая предоставляет всю мощь CLI и скриптов, а также использовать поддержку визуальных инструментов, в том числе Visual Studio, для упрощения работы.

Развертывание обновлений выполняется поэтапно. На каждом этапе обновление применяется к подмножеству узлов в кластере, которое называют доменом обновления (upgrade domain). В итоге приложение остается доступным в процессе обновления. Также возможны строгий контроль версий и поддержка сосуществования разных версий (side-by-side), поэтому вы можете развертывать версии v1 и v2 одного и того же микросервиса, и Service Fabric будет перенаправлять соответствующие клиентские запросы той или иной версии. Подробнее на эту тему см. документацию по ссылке bit.ly/1kSupz8.

Отладка сервисов на локальном кластере благодаря Visual Studio проста, даже когда процессы сервисов выполняются до того, как вы приступаете к отладке. IDE автоматически подключается ко всем процессам микросервисов, относящимся к вашему проекту, и позволяет легко использовать обычные точки прерывания в коде микросервисов Service Fabric. Просто установите точки прерывания в коде и нажмите клавишу F5. Вам не потребуется выяснять, к какому процессу следует подключить Visual Studio.

Service Fabric Explorer Это веб-инструмент, предоставляемый кластером для визуализации состояния развернутых приложений, изучения содержимого индивидуальных узлов и выполнения различных административных операций (рис. 9). Инструмент Explorer обслуживается тем же сервисом HTTP Gateway, который поддерживает Service Fabric REST API и доступен по адресу http://<конечная точка вашего кластера>:19007/Explorer. В случае локального кластера URL будет другим: http://localhost:19007/Explorer.

Service Fabric Explorer

Рис. 9. Service Fabric Explorer

Подробнее о Service Fabric Explorer см. страницу документации «Visualizing Your Cluster Using Service Fabric Explorer» (bit.ly/1MUNyad).

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

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

Автоматическая балансировка ресурсов Service Fabric обеспечивает балансировку ресурсов для сервисов (или координацию сервисов), распознавая общее количество доступных ресурсов в кластере (например, вычислительных ресурсов в VM). Соответствующее средство автоматически перемещает микросервисы в зависимости от определенной политики и ограничений для оптимизации размещения создаваемых сервисов по VM (рис. 10). При этом алгоритм стремится к оптимизации расходов и производительности.

Распределение сервисов по узлам кластера и автоматическая балансировка ресурсов

Рис. 10. Распределение сервисов по узлам кластера и автоматическая балансировка ресурсов

Too many noisy microservices neighbors Слишком много «шумных» соседних микросервисов
Too stressed Processor, Memory & Network Слишком большая нагрузка на процессор, память и сеть
Services being “moved” to a different node Сервисы, перемещаемые на другой узел
Can handle more microservices Может обрабатывать больше микросервисов

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

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

Балансировка нагрузки запросов Не путайте с автоматической балансировкой ресурсов — балансировка запросов обрабатывается не Service Fabric, а средствами балансировки нагрузки Azure (Azure Load Balancers) или другими платформами, внешними по отношению к Service Fabric.

Мониторинг работоспособности Позволяет отслеживать и диагностировать ваши системы. Также используется при обновлениях приложения, обеспечивая проверки их безопасности, чтобы обновления можно было откатывать в случае дестабилизации приложения. Подробнее на эту тему см. страницу документации «Introduction to Service Fabric Health Monitoring» (bit.ly/1jSvmHB).

Микросервисы с состоянием в Azure Service Fabric

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

Микросервис с состоянием в Service Fabric комбинирует вычисления и данные, при этом состояние находится в самом микросервисе (как в памяти, так и на локальном диске). Надежность состояния достигается локальным сохранением в сочетании с репликацией данных на другие узлы/VM. В целом, с каждым разделом данных сопоставляется несколько реплик. Каждую реплику можно развернуть на другом узле/VM, чтобы обеспечить высокую доступность на случай отказа основной реплики. Это похоже на то, как Azure SQL Database работает с репликами базы данных, поскольку все основано на Azure Service Fabric.

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

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

Stateful Azure Reliable Services предоставляют массу возможностей, включая разбиение данных на разделы, поддержку реплик и выборы ведущего, именование сервиса реплик и обнаружение адреса сервиса через сервис шлюза. Кроме того, они обеспечивают управление параллельной обработкой и уровнем детализации (гранулярностью) изменений состояния, используя транзакции, способность поддерживать согласованную репликацию состояния и применение надежных, распределенных наборов пар «ключ-значение» (Reliable Dictionary и Reliable Queue). Хорошая новость в том, что Service Fabric берет на себя все сложности и детали этих процессов, так что вы можете сосредоточиться на написании приложений.

Надежные сервисы-акторы в Azure Service Fabric

Azure Service Fabric Reliable Actors — модель программирования актора для Service Fabric. Это модель асинхронного, однопоточного актора. Актор представляет единицу состояния и вычислений. В некоторых отношениях он подобен проекту программного обеспечения «Orleans» с открытым исходным кодом, созданным в Microsoft Research. Важный момент в том, что Service Fabric Reliable Actors API основан на нижележащей инфраструктуре, предоставляемой Service Fabric.

Реализация экземпляров актора для IoT-устройств — хороший пример использования сервисов-акторов. Тип Vehicle-Actor в виде C#-класса мог бы инкапсулировать логику предметной области IoT-устройства плюс его состояния реального времени (live states), такие как GPS-координаты и другие данные. Затем мы могли бы создать потенциально миллионы объектов или экземпляров актора упомянутого класса, распределенных по множеству узлов в кластере.

Конечно, акторы не ограничиваются IoT-объектами — их можно было бы применять в любой области, но «IoT-объекты реального времени» являются самым поучительным сценарием.

Акторы распределяются по кластеру для достижения высокой масштабируемости и доступности и обрабатываются как объекты в памяти в каждой VM кластера. Они также сохраняются на локальный диск и реплицируются по кластеру.

Акторы являются изолированными однопоточными объектами, которые инкапсулируют как состояние, так и поведение. Каждый актор — это экземпляр типа актора, примерно такой, как в .NET-коде ниже:

// Определение актора (State+Behaviour) для выполнения
// в серверной части. Экземпляры объекта этого класса Actor
// будут выполняться прозрачно в серверной части сервиса.

public class VehicleActor : Actor<Vehicle>, IVehicleActor
{
  public void UpdateGpsPosition(GpsCoordinates coord)
  {
    // Обновляем координаты и инициируем любую обработку данных
    // через свойство State базового класса Actor<TState>
    this.State.Position= coord;
  }
}

Далее следующий код показывает пример клиентского кода, использующего актор через прокси-объект:

// Клиентский .NET-код
ActorId actorId = ActorId.NewId();
string applicationName = "fabric:/IoTVehiclesActorApp";
IVehicleActor vehicleActorProxy =
  ActorProxy.Create<IVehicleActor>(actorId, applicationName);
vehicleActorProxy.UpdateGpsPosition(
  new GpsCoordinates(40.748440, -73.984559));

Всю коммуникационную инфраструктуру берет на себя инфраструктура Service Fabric Reliable Actors.

Вы могли бы запустить миллионы объектов VehicleActor в кластере, распределив их по множеству узлов/VM, и Service Fabric позаботилась бы о необходимой инфраструктуре, включая разделы и реплики, где распределены и балансируются миллионы ваших акторов.

Actors Client API обеспечивает взаимодействие между экземпляром актора и клиентом актора. Для взаимодействия с актором клиент создает прокси-объект, который реализует интерфейс актора. Клиент взаимодействует с актором, вызывая методы прокси-объекта.

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

Заключение

Архитектуры микросервисов требуют ориентации на децентрализованные подходы, строгие процессы проектирования, новые технологии вроде Azure Service Fabric и перехода на малые группы разработки с соблюдением принципов Agile-разработки, применяемым к каждому микросервису.


Сесар де ла Торре (Cesar de la Torre) — старший менеджер программ в Microsoft, живет в Редмонде (штат Вашингтон). Его интересы включают разработку для Microsoft Azure и .NET с применением архитектур микросервисов и DDD, а также создание мобильных приложений, взаимодействующих с сервисами.

Кунал Дип Сингх (Kunal Deep Singh) — старший менеджер программ в группе Microsoft Azure Service Fabric. До Azure работал над несколькими выпусками Windows Phone, Silverlight, а также разработчиком ряда игр для Xbox. Живет в Сиэтле (штат Вашингтон).

Вацлав Туречек (Vaclav Turecek) — старший менеджер программ в Microsoft. Неустанно трудится с очень талантливой группой людей, чтобы сделать Azure Service Fabric лучшей Platform as a Service следующего поколения.

Выражаем благодарность за рецензирование статьи эксперту Microsoft Марку Фасселу (Mark Fussell).