Развертывание и удаление приложений с помощью FabricClient


После создания пакета приложения его можно развернуть в кластере Azure Service Fabric. Развертывание включает следующие три шага:

  1. передача пакета приложения в хранилище образов;
  2. регистрация типа приложения;
  3. Удаление пакета приложения из хранилища образов.
  4. создание экземпляра приложения.

После развертывания приложения и запуска экземпляра в кластере вы можете удалить экземпляр приложения и тип приложения. Полностью удалите приложение из кластера, выполнив следующие действия:

  1. удаление запущенного экземпляра приложения;
  2. отмена регистрации типа приложения, если он больше не нужен;

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

Подключение к кластеру

Подключитесь к кластеру, создав экземпляр FabricClient перед запуском всех примеров кода в этой статье. Примеры подключения к локальному кластеру разработки или удаленному кластеру или кластеру, защищенному с помощью идентификатора Microsoft Entra, сертификатов X509 или Windows Active Directory, см. Подключение в безопасный кластер. Чтобы подключиться к локальному кластеру разработки, выполните следующий пример:

// Connect to the local cluster.
FabricClient fabricClient = new FabricClient();

Загрузка пакета приложения

Предположим, вы собрали и упаковали в Visual Studio приложение с именем MyApplication. По умолчанию имя типа приложения отображается в файле ApplicationManifest.xml как MyApplicationType. Пакет приложения, содержащий необходимый манифест приложения, манифесты служб и пакеты кода/конфигурации/данных, расположен в C:\Users< username>\Documents\Visual Studio 2019\Projects\MyApplication\MyApplication\pkg\Debug.

Отправка пакета приложения означает, что он помещается в расположение, доступное внутренним компонентам Service Fabric. Service Fabric проверяет пакет приложения во время его регистрации. Но если вы хотите проверить пакет приложения локально (т.е. перед отправкой), используйте командлет Test-ServiceFabricApplicationPackage.

API CopyApplicationPackage отправляет пакет приложения в хранилище образов кластера.

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

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

Регистрация пакета приложения

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

API ProvisionApplicationAsync регистрирует тип приложения кластере и делает его доступным для развертывания.

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

Удаление пакета приложения из хранилища образов

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

Создание экземпляра приложения

Чтобы создать экземпляр приложения, можно использовать любой зарегистрированный тип приложения. Для этого примените API CreateApplicationAsync. Имя приложения должно начинаться со схемы "fabric:" и быть уникальным для каждого экземпляра приложения (в кластере). Если в манифесте приложения для конкретного его типа были определены службы по умолчанию, то они также будут созданы.

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

Чтобы увидеть, что нужные приложения и службы в кластере работают, воспользуйтесь API GetApplicationListAsync и GetServiceListAsync.

Создание экземпляра службы

Экземпляр службы можно создать из типа службы с помощью API CreateServiceAsync. Если служба в манифесте приложения объявляется службой по умолчанию, экземпляр этой службы создается с помощью экземпляра приложения. Вызов API CreateServiceAsync для уже созданной службы возвращает исключение типа FabricException. Исключение будет содержать код ошибки со значением FabricErrorCode.ServiceAlreadyExists.

Удаление экземпляра службы

Если экземпляр службы больше не нужен, его можно удалить из выполняемого экземпляра приложения путем вызова API DeleteServiceAsync.

Предупреждение

Эта операция необратима, и вы не сможете восстановить состояние службы.

Удаление экземпляра приложения

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

Предупреждение

Эта операция необратима, и вы не сможете восстановить состояние приложения.

Отмена регистрации типа приложения

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

Устранение неполадок

Команда Copy-ServiceFabricApplicationPackage запрашивает строку ImageStoreConnectionString

В пакете разработки Service Fabric SDK уже предусмотрены все необходимые значения по умолчанию. Тем не менее, при необходимости значение ImageStoreConnectionString для всех команд должно совпадать со значением, используемым кластером Service Fabric. Значение ImageStoreConnectionString можно найти в манифесте кластера, используя команды Get-ServiceFabricClusterManifest и Get-ImageStoreConnectionStringFromClusterManifest.

PS C:\> Get-ImageStoreConnectionStringFromClusterManifest(Get-ServiceFabricClusterManifest)

Командлет Get-ImageStoreConnectionStringFromClusterManifest , являющийся частью модуля PowerShell пакета SDK для Service Fabric, позволяет получить строку подключения хранилища образов. Чтобы импортировать модуль пакета SDK, выполните следующую команду.

Import-Module "$ENV:ProgramFiles\Microsoft SDKs\Service Fabric\Tools\PSModule\ServiceFabricSDK\ServiceFabricSDK.psm1"

Ниже представлено значение ImageStoreConnectionString из манифеста кластера.

<ClusterManifest xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" Name="Server-Default-SingleNode" Version="1.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">

    [...]

    <Section Name="Management">
      <Parameter Name="ImageStoreConnectionString" Value="file:D:\ServiceFabric\Data\ImageStore" />
    </Section>

    [...]

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

Развертывание пакета приложения большего размера

Проблема. Время ожидания API CopyApplicationPackage истекает для пакета большого приложения (несколько ГБ). Попробуйте следующее:

  • Задайте больше времени ожидания для метода CopyApplicationPackage с помощью параметра timeout. По умолчанию время ожидания составляет 30 минут.
  • Проверьте сетевое подключение между исходным компьютером и кластером. Если подключение медленное, рассмотрите возможность использовать машину с лучшим сетевым соединением. Возможно, клиентский компьютер находится не в одном регионе с кластером, тогда перейдите на компьютер, который находится с ним в одном регионе или в регионе поблизости.
  • Проверьте, достигнуто ли внешнее регулирование. Например, если хранилище образов настроено для использования хранилища Аzure, загрузку можно регулировать.

Проблема. Отправка пакета завершена успешно, но время ожидания API ProvisionApplicationAsync истекло. Попробуйте следующее решение:

  • Выполните сжатие пакета перед копированием в хранилище образов. Сжатие уменьшает размер и число файлов, что, в свою очередь, снижает объем трафика и работу, которую необходимо выполнить Service Fabric. Операция отправки может выполняться медленнее (особенно при выполнении сжатия), но регистрация и отмена регистрации типа приложения выполняются быстрее.
  • Задайте больше времени ожидания для API ProvisionApplicationAsync с помощью параметра timeout.

Развертывание пакета приложения с несколькими файлами

Проблема. Время ожидания метода ProvisionApplicationAsync для пакета приложения со множеством (несколько тысяч) файлов истекло. Попробуйте следующее:

Пример кода

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Threading.Tasks;

using System.Fabric;
using System.Fabric.Description;
using System.Threading;

namespace ServiceFabricAppLifecycle
{
class Program
{
static void Main(string[] args)
{

    string clusterConnection = "localhost:19000";
    string appName = "fabric:/MyApplication";
    string appType = "MyApplicationType";
    string appVersion = "1.0.0";
    string serviceName = "fabric:/MyApplication/Stateless1";
    string imageStoreConnectionString = "file:C:\\SfDevCluster\\Data\\ImageStoreShare";
    string packagePathInImageStore = "MyApplication";
    string packagePath = "C:\\Users\\username\\Documents\\Visual Studio 2019\\Projects\\MyApplication\\MyApplication\\pkg\\Debug";
    string serviceType = "Stateless1Type";

    // Connect to the cluster.
    FabricClient fabricClient = new FabricClient(clusterConnection);

    // Copy the application package to a location in the image store
    try
    {
        fabricClient.ApplicationManager.CopyApplicationPackage(imageStoreConnectionString, packagePath, packagePathInImageStore);
        Console.WriteLine("Application package copied to {0}", packagePathInImageStore);
    }
    catch (AggregateException ae)
    {
        Console.WriteLine("Application package copy to Image Store failed: ");
        foreach (Exception ex in ae.InnerExceptions)
        {
            Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
        }
    }

    // Provision the application.  "MyApplicationV1" is the folder in the image store where the application package is located. 
    // The application type with name "MyApplicationType" and version "1.0.0" (both are found in the application manifest) 
    // is now registered in the cluster.            
    try
    {
        fabricClient.ApplicationManager.ProvisionApplicationAsync(packagePathInImageStore).Wait();

        Console.WriteLine("Provisioned application type {0}", packagePathInImageStore);
    }
    catch (AggregateException ae)
    {
        Console.WriteLine("Provision Application Type failed:");

        foreach (Exception ex in ae.InnerExceptions)
        {
            Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
        }
    }

    // Delete the application package from a location in the image store.
    try
    {
        fabricClient.ApplicationManager.RemoveApplicationPackage(imageStoreConnectionString, packagePathInImageStore);
        Console.WriteLine("Application package removed from {0}", packagePathInImageStore);
    }
    catch (AggregateException ae)
    {
        Console.WriteLine("Application package removal from Image Store failed: ");
        foreach (Exception ex in ae.InnerExceptions)
        {
            Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
        }
    }

    //  Create the application instance.
    try
    {
        ApplicationDescription appDesc = new ApplicationDescription(new Uri(appName), appType, appVersion);
        fabricClient.ApplicationManager.CreateApplicationAsync(appDesc).Wait();
        Console.WriteLine("Created application instance of type {0}, version {1}", appType, appVersion);
    }
    catch (AggregateException ae)
    {
        Console.WriteLine("CreateApplication failed.");
        foreach (Exception ex in ae.InnerExceptions)
        {
            Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
        }
    }

    // Create the stateless service description.  For stateful services, use a StatefulServiceDescription object.
    StatelessServiceDescription serviceDescription = new StatelessServiceDescription();
    serviceDescription.ApplicationName = new Uri(appName);
    serviceDescription.InstanceCount = 1;
    serviceDescription.PartitionSchemeDescription = new SingletonPartitionSchemeDescription();
    serviceDescription.ServiceName = new Uri(serviceName);
    serviceDescription.ServiceTypeName = serviceType;

    // Create the service instance.  If the service is declared as a default service in the ApplicationManifest.xml,
    // the service instance is already running and this call will fail.
    try
    {
        fabricClient.ServiceManager.CreateServiceAsync(serviceDescription).Wait();
        Console.WriteLine("Created service instance {0}", serviceName);
    }
    catch (AggregateException ae)
    {
        Console.WriteLine("CreateService failed.");
        foreach (Exception ex in ae.InnerExceptions)
        {
            Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
        }
    }

    // Delete a service instance.
    try
    {
        DeleteServiceDescription deleteServiceDescription = new DeleteServiceDescription(new Uri(serviceName));

        fabricClient.ServiceManager.DeleteServiceAsync(deleteServiceDescription);
        Console.WriteLine("Deleted service instance {0}", serviceName);
    }
    catch (AggregateException ae)
    {
        Console.WriteLine("DeleteService failed.");
        foreach (Exception ex in ae.InnerExceptions)
        {
            Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
        }
    }

    // Delete an application instance from the application type.
    try
    {
        DeleteApplicationDescription deleteApplicationDescription = new DeleteApplicationDescription(new Uri(appName));

        fabricClient.ApplicationManager.DeleteApplicationAsync(deleteApplicationDescription).Wait();
        Console.WriteLine("Deleted application instance {0}", appName);
    }
    catch (AggregateException ae)
    {
        Console.WriteLine("DeleteApplication failed.");
        foreach (Exception ex in ae.InnerExceptions)
        {
            Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
        }
    }

    // Un-provision the application type.
    try
    {
        fabricClient.ApplicationManager.UnprovisionApplicationAsync(appType, appVersion).Wait();
        Console.WriteLine("Un-provisioned application type {0}, version {1}", appType, appVersion);
    }
    catch (AggregateException ae)
    {
        Console.WriteLine("Un-provision application type failed: ");
        foreach (Exception ex in ae.InnerExceptions)
        {
            Console.WriteLine("HResult: {0} Message: {1}", ex.HResult, ex.Message);
        }
    }

    Console.WriteLine("Hit enter...");
    Console.Read();
}        
}
}

Следующие шаги

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

Общие сведения о работоспособности Service Fabric

Диагностика и устранение неполадок службы Service Fabric

Моделирование приложения в Service Fabric