Начало работы с Reliable Services

Приложение Azure Service Fabric содержит одну или несколько служб, которые выполняют код. В этом руководстве показано, как создавать приложения Service Fabric как без сохранения состояния, так и с сохранением состояния с помощью Reliable Services.

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

Основные понятия

Чтобы приступить к работе со службами Reliable Services, необходимо только понять несколько основных понятий:

  • Тип службы: это реализация службы. Он определяется классом, который расширяет StatelessService, а также любым другим кодом или зависимостями, которые в нём используются, наряду с именем и номером версии.
  • Именованный экземпляр службы: для запуска службы вы создаете именованные экземпляры типа службы, как и создание экземпляров объектов типа класса. Экземпляр службы имеет имя в виде универсального идентификатора ресурса (URI) с использованием схемы "fabric:/", например, "fabric:/MyApp/MyService".
  • Хост службы: создаваемые вами именованные экземпляры службы должны выполняться внутри процесса хоста. Хост службы — это просто процесс, в котором могут выполняться экземпляры вашей службы.
  • Регистрация службы: регистрация объединяет все. Тип службы должен быть зарегистрирован в среде выполнения Service Fabric в узле службы, чтобы разрешить Service Fabric создавать экземпляры для запуска.

Создайте бестейтлесс сервис

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

Запустите Visual Studio 2017 или Visual Studio 2019 от имени администратора и создайте проект приложения Service Fabric с именем HelloWorld:

Создание нового приложения Service Fabric с помощью диалогового окна

Затем создайте проект службы без сохранения состояния с помощью .NET Core 2.0 с именем HelloWorldStateless:

Во втором диалоговом окне создайте проект службы без отслеживания состояния

Теперь ваше решение содержит два проекта:

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

Реализация службы

Откройте файл HelloWorldStateless.cs в проекте службы. В Service Fabric служба может выполнять любую бизнес-логику. API службы предоставляет две точки входа для кода:

  • Открытый метод точки входа с именем RunAsync, где можно начать выполнение любых рабочих нагрузок, включая длительные вычислительные рабочие нагрузки.
protected override async Task RunAsync(CancellationToken cancellationToken)
{
    ...
}
  • Точка входа связи, в которой можно подключиться к выбранному стеку связи, например ASP.NET Core. Здесь можно начать получать запросы от пользователей и других служб.
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
    ...
}

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

Замечание

Дополнительные сведения о работе с коммуникационным стеком см. в разделе "Связь службы с ASP.NET Core"

RunAsync

protected override async Task RunAsync(CancellationToken cancellationToken)
{
    // TODO: Replace the following sample code with your own logic
    //       or remove this RunAsync override if it's not needed in your service.

    long iterations = 0;

    while (true)
    {
        cancellationToken.ThrowIfCancellationRequested();

        ServiceEventSource.Current.ServiceMessage(this.Context, "Working-{0}", ++iterations);

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

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

  • Система перемещает экземпляры сервисов для балансировки ресурсов.
  • Ошибки возникают в коде.
  • Приложение или система обновлены.
  • Базовое оборудование испытывает сбой.

Эта оркестрация управляется системой для поддержания высокой доступности услуги и надлежащей балансировки.

RunAsync() не должен блокироваться синхронно. Реализация RunAsync должна возвращать объект Task или дождаться завершения длительных или блокирующих операций, чтобы разрешить среде выполнения продолжать работу. Обратите внимание на цикл while(true) в предыдущем примере: используется задача, возвращаемая await Task.Delay(). Если ваша рабочая нагрузка должна блокироваться синхронно, вам следует запланировать новую задачу с Task.Run() в вашей реализации RunAsync.

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

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

Создание сервиса с сохранением состояния

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

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

В том же приложении HelloWorld вы можете добавить новую службу, щелкнув правой кнопкой мыши ссылки на службы в проекте приложения и выбрав "Добавить —> новая служба Service Fabric".

Добавление службы в приложение Service Fabric

Выберите .NET Core 2.0 —> служба с отслеживанием состояния и назовите ее HelloWorldStateful. Нажмите кнопку ОК.

Используйте диалоговое окно

Теперь приложение должно иметь две службы: безгосударственную службу HelloWorldStateless и службу с состоянием HelloWorldStateful.

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

Откройте HelloWorldStateful.cs в HelloWorldStateful, который содержит следующий метод RunAsync:

protected override async Task RunAsync(CancellationToken cancellationToken)
{
    // TODO: Replace the following sample code with your own logic
    //       or remove this RunAsync override if it's not needed in your service.

    var myDictionary = await this.StateManager.GetOrAddAsync<IReliableDictionary<string, long>>("myDictionary");

    while (true)
    {
        cancellationToken.ThrowIfCancellationRequested();

        using (var tx = this.StateManager.CreateTransaction())
        {
            var result = await myDictionary.TryGetValueAsync(tx, "Counter");

            ServiceEventSource.Current.ServiceMessage(this.Context, "Current Counter Value: {0}",
                result.HasValue ? result.Value.ToString() : "Value does not exist.");

            await myDictionary.AddOrUpdateAsync(tx, "Counter", 0, (key, value) => ++value);

            // If an exception is thrown before calling CommitAsync, the transaction aborts, all changes are
            // discarded, and nothing is saved to the secondary replicas.
            await tx.CommitAsync();
        }

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

RunAsync

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

Надежные коллекции и менеджер надежных состояний

var myDictionary = await this.StateManager.GetOrAddAsync<IReliableDictionary<string, long>>("myDictionary");

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

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

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

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

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

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

Транзакционные и асинхронные операции

using (ITransaction tx = this.StateManager.CreateTransaction())
{
    var result = await myDictionary.TryGetValueAsync(tx, "Counter-1");

    await myDictionary.AddOrUpdateAsync(tx, "Counter-1", 0, (k, v) => ++v);

    await tx.CommitAsync();
}

Надежные коллекции обладают многими из тех же операций, что и их System.Collections.Generic и System.Collections.Concurrent аналоги, за исключением Language Integrated Query (LINQ). Операции с надежными коллекциями выполняются асинхронно. Это связано с тем, что операции записи с надежными коллекциями выполняют операции ввода-вывода для репликации и сохранения данных на диск.

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

Запуск приложения

Теперь мы вернемся к приложению HelloWorld . Теперь вы можете создавать и развертывать службы. При нажатии клавиши F5 приложение будет создано и развернуто в локальном кластере.

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

Замечание

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

Просмотр диагностических событий в Visual Studio

Дальнейшие действия

Отладка приложения Service Fabric в Visual Studio

Начало работы: службы веб-API Service Fabric с самостоятельным размещением OWIN

Дополнительные сведения о надежных коллекциях

Развертывание приложения

Обновление приложения

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