使用 FabricClient 部署和删除应用程序Deploy and remove applications using FabricClient


打包应用程序类型后,即可部署到 Azure Service Fabric 群集中。Once an application type has been packaged, it's ready for deployment into an Azure Service Fabric cluster. 部署涉及以下三个步骤:Deployment involves the following three steps:

  1. 将应用程序包上传到映像存储区Upload the application package to the image store
  2. 注册应用程序类型Register the application type
  3. 从映像存储中删除应用程序包Remove the application package from the image store
  4. 创建应用程序实例Create the application instance

在部署应用程序并在群集中运行实例后,可以删除应用程序实例及其应用程序类型。After you deploy an application and run an instance in the cluster, you can delete the application instance and its application type. 按照以下步骤从群集中完全删除某个应用程序:Completely remove an application from the cluster by following these steps:

  1. 删除正在运行的应用程序实例Remove (or delete) the running application instance
  2. 如果不再需要该应用程序类型,则将其取消注册Unregister the application type if you no longer need it

如果使用 Visual Studio 来部署和调试本地开发群集上的应用程序,则将通过 PowerShell 脚本自动处理上述所有步骤。If you use Visual Studio for deploying and debugging applications on your local development cluster, all the preceding steps are handled automatically through a PowerShell script. 可在应用程序项目的 Scripts 文件夹中找到此脚本。This script is found in the Scripts folder of the application project. 本文提供了有关这些脚本正在执行什么操作的背景,方便你在 Visual Studio 外部执行相同的操作。This article provides background on what that script is doing so that you can do the same operations outside of Visual Studio.

连接至群集Connect to the cluster

在运行本文中的任何代码示例之前,通过创建 FabricClient 实例连接到群集。Connect to the cluster by creating a FabricClient instance before you run any of the code examples in this article. 有关连接到本地开发群集、远程群集,或使用 Azure Active Directory、X509 证书或 Windows Active Directory 保护的群集的示例,请参阅连接到安全群集For examples of connecting to a local development cluster or a remote cluster or cluster secured using Azure Active Directory, X509 certificates, or Windows Active Directory see Connect to a secure cluster. 若要连接到本地部署群集,请运行以下示例:To connect to the local development cluster, run the following example:

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

上传应用程序包Upload the application package

假设在 Visual Studio 中生成并打包名为 MyApplication 的应用程序。Suppose you build and package an application named MyApplication in Visual Studio. 默认情况下,ApplicationManifest.xml 中列出的应用程序类型名称为“MyApplicationType”。By default, the application type name listed in the ApplicationManifest.xml is "MyApplicationType". 应用程序包(其中包含必需的应用程序清单、服务清单以及代码/配置/数据包)位于 C:\Users<username>\Documents\Visual Studio 2019\Projects\MyApplication\MyApplication\pkg\Debug 中。The application package, which contains the necessary application manifest, service manifests, and code/config/data packages, is located in C:\Users<username>\Documents\Visual Studio 2019\Projects\MyApplication\MyApplication\pkg\Debug.

上传应用程序包会将其放在一个可由内部 Service Fabric 组件访问的位置。Uploading the application package puts it in a location that's accessible by the internal Service Fabric components. Service Fabric 在注册应用程序包期间会对应用程序包进行验证。Service Fabric verifies the application package during the registration of the application package. 但是,如果要在本地(即,在上传之前)验证应用程序包,请使用 Test-ServiceFabricApplicationPackage cmdlet。However, if you want to verify the application package locally (that is, before uploading), use the Test-ServiceFabricApplicationPackage cmdlet.

CopyApplicationPackage API 可将应用程序包上传到群集映像存储。The CopyApplicationPackage API uploads the application package to the cluster image store.

如果应用程序包很大和/或包含多个文件,可使用 PowerShell 将其压缩并复制到映像存储。If the application package is large and/or has many files, you can compress it and copy it to the image store using PowerShell. 压缩可以减小文件大小,减少文件数量。The compression reduces the size and the number of files.

有关映像存储和映像存储连接字符串的补充信息,请参阅了解映像存储连接字符串See Understand the image store connection string for supplementary information about the image store and image store connection string.

注册应用程序包Register the application package

应用程序清单中声明的应用程序类型和版本会在注册应用程序包时可供使用。The application type and version declared in the application manifest become available for use when the application package is registered. 系统会读取上一步中上传的程序包,验证此包,处理包的内容,并将已处理的包复制到内部系统位置。The system reads the package uploaded in the previous step, verifies the package, processes the package contents, and copies the processed package to an internal system location.

ProvisionApplicationAsync API 可在群集中注册应用程序并使其可供部署。The ProvisionApplicationAsync API registers the application type in the cluster and make it available for deployment.

GetApplicationTypeListAsync API 提供有关所有已成功注册的应用程序类型的信息。The GetApplicationTypeListAsync API provides information about all successfully registered application types. 可以使用此 API 来确定注册的完成时间。You can use this API to determine when the registration is done.

从映像存储中删除应用程序包Remove an application package from the image store

建议在成功注册应用程序后删除应用程序包。It's recommended that you remove the application package after the application is successfully registered. 从映像存储区中删除应用程序包可以释放系统资源。Deleting application packages from the image store frees up system resources. 保留未使用的应用程序包会占用磁盘存储空间,导致应用程序出现性能问题。Keeping unused application packages consumes disk storage and leads to application performance issues. 使用 RemoveApplicationPackage API,从映像存储区删除应用程序包。Delete the application package from the image store using the RemoveApplicationPackage API.

创建应用程序实例Create an application instance

可以使用 CreateApplicationAsync API 通过已成功注册的任何应用程序类型来实例化应用程序。You can instantiate an application from any application type that has been registered successfully by using the CreateApplicationAsync API. 每个应用程序的名称必须以“fabric:” 方案开头,并且必须对每个应用程序实例是唯一的(在群集中)。The name of each application must start with the "fabric:" scheme and must be unique for each application instance (within a cluster). 还会创建目标应用程序类型的应用程序清单中定义的任何默认服务。Any default services defined in the application manifest of the target application type are also created.

可以为已注册应用程序类型的任何给定版本创建多个应用程序实例。Multiple application instances can be created for any given version of a registered application type. 每个应用程序实例都将隔离运行,具有其自己的工作目录和进程集。Each application instance runs in isolation, with its own working directory and set of processes.

若要查看哪些已命名应用和服务正在群集中运行,请运行 GetApplicationListAsyncGetServiceListAsync API。To see which named applications and services are running in the cluster, run the GetApplicationListAsync and GetServiceListAsync APIs.

创建服务实例Create a service instance

可以使用 CreateServiceAsync API 通过服务类型实例化服务。You can instantiate a service from a service type using the CreateServiceAsync API. 如果该服务被声明为应用程序清单中的默认服务,则该服务在应用程序实例化时实例化。If the service is declared as a default service in the application manifest, the service is instantiated when the application is instantiated. 为已经实例化的服务调用 CreateServiceAsync API 会返回类型为 FabricException 的异常。Calling the CreateServiceAsync API for a service that is already instantiated will return an exception of type FabricException. 该异常会包含值为 FabricErrorCode.ServiceAlreadyExists 的错误代码。The exception will contain an error code with a value of FabricErrorCode.ServiceAlreadyExists.

删除服务实例Remove a service instance

当不再需要某个服务实例时,可以通过调用 DeleteServiceAsync API 从正在运行的应用程序实例中将其删除。When a service instance is no longer needed, you can remove it from the running application instance by calling the DeleteServiceAsync API.

警告

此操作无法撤消,并且无法恢复服务状态。This operation cannot be reversed, and service state cannot be recovered.

删除应用程序实例Remove an application instance

当不再需要某个应用程序实例时,可以使用 DeleteApplicationAsync API 通过指定其名称将其永久删除。When an application instance is no longer needed, you can permanently remove it by name using the DeleteApplicationAsync API. DeleteApplicationAsync 也会自动删除属于该应用程序的所有服务,永久删除所有服务状态。DeleteApplicationAsync automatically removes all services that belong to the application as well, permanently removing all service state.

警告

此操作无法撤消,并且无法恢复应用程序状态。This operation cannot be reversed, and application state cannot be recovered.

取消注册应用程序类型Unregister an application type

当不再需要应用程序类型的某个特定版本时,应使用 Unregister-ServiceFabricApplicationType API 取消注册该应用程序类型的该特定版本。When a particular version of an application type is no longer needed, you should unregister that particular version of the application type using the Unregister-ServiceFabricApplicationType API. 取消注册未使用的应用程序类型版本将释放映像存储使用的存储空间。Unregistering unused versions of application types releases storage space used by the image store. 只要没有针对某个版本的应用程序类型将应用程序实例化,就可以注销该版本的应用程序类型。A version of an application type can be unregistered as long as no applications are instantiated against that version of the application type. 另外,只要没有挂起的应用程序升级在引用某个版本的应用程序类型,就可以注销该版本的应用程序类型。Also, the application type can have no pending application upgrades are referencing that version of the application type.

故障排除Troubleshooting

Copy-ServiceFabricApplicationPackage 请求 ImageStoreConnectionStringCopy-ServiceFabricApplicationPackage asks for an ImageStoreConnectionString

Service Fabric SDK 环境应已默认设置正确。The Service Fabric SDK environment should already have the correct defaults set up. 若有需要,所有命令的 ImageStoreConnectionString 都应匹配 Service Fabric 群集正在使用的值。But if needed, the ImageStoreConnectionString for all commands should match the value that the Service Fabric cluster is using. 可以在使用 Get-ServiceFabricClusterManifest 和 Get-ImageStoreConnectionStringFromClusterManifest 命令检索到的群集清单中找到 ImageStoreConnectionString:You can find the ImageStoreConnectionString in the cluster manifest, retrieved using the Get-ServiceFabricClusterManifest and Get-ImageStoreConnectionStringFromClusterManifest commands:

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

Service Fabric SDK PowerShell 模块中包含的 Get-ImageStoreConnectionStringFromClusterManifest cmdlet,用于获取映像存储连接字符串。The Get-ImageStoreConnectionStringFromClusterManifest cmdlet, which is part of the Service Fabric SDK PowerShell module, is used to get the image store connection string. 要导入 SDK 模块,请运行:To import the SDK module, run:

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

ImageStoreConnectionString 可在群集清单中找到:The ImageStoreConnectionString is found in the cluster manifest:

<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>

    [...]

有关映像存储和映像存储连接字符串的补充信息,请参阅了解映像存储连接字符串See Understand the image store connection string for supplementary information about the image store and image store connection string.

部署大型应用程序包Deploy large application package

问题:对于大型(GB 级别的)应用程序包,CopyApplicationPackage API 方法超时。Issue: CopyApplicationPackage API times out for a large application package (order of GB). 请尝试:Try:

  • 通过 timeout 参数为 CopyApplicationPackage 方法指定更长的超时时间。Specify a larger timeout for CopyApplicationPackage method, with timeout parameter. 此超时默认为 30 分钟。By default, the timeout is 30 minutes.
  • 检查源计算机和群集之间的网络连接。Check the network connection between your source machine and cluster. 如果连接缓慢,请考虑使用一台网络连接状况更好的计算机。If the connection is slow, consider using a machine with a better network connection. 如果客户端计算机位于另一个区域,而不在此群集中,请考虑使用此群集的邻近区域或同区域中的客户端计算机。If the client machine is in another region than the cluster, consider using a client machine in a closer or same region as the cluster.
  • 检查是否已达到外部限制。Check if you are hitting external throttling. 例如,将映像存储区配置为使用 Azure 存储时,可能会限制上传。For example, when the image store is configured to use azure storage, upload may be throttled.

问题:上传包已成功完成,但 ProvisionApplicationAsync API 超时。请尝试:Issue: Upload package completed successfully, but ProvisionApplicationAsync API times out. Try:

  • 复制到映像存储之前对包进行压缩Compress the package before copying to the image store. 压缩可减小文件大小,减少文件数量,这反过来会减少通信流量和 Service Fabric 必须执行的工作量。The compression reduces the size and the number of files, which in turn reduces the amount of traffic and work that Service Fabric must perform. 上传操作可能会变慢(尤其是包括压缩时间时),但注册和注销应用程序类型会加快。The upload operation may be slower (especially if you include the compression time), but register and unregister the application type are faster.
  • 通过 timeout 参数为 ProvisionApplicationAsync API 指定更长的超时时间。Specify a larger timeout for ProvisionApplicationAsync API with timeout parameter.

部署包含多个文件的应用程序包Deploy application package with many files

问题:具有多个文件(上千个)的应用程序包的ProvisionApplicationAsync 超时。Issue: ProvisionApplicationAsync times out for an application package with many files (order of thousands). 请尝试:Try:

代码示例Code example

以下示例将应用程序包复制到映像存储区并预配应用程序类型。The following example copies an application package to the image store and provisions the application type. 然后,该示例创建应用程序实例并创建服务实例。Then, the example creates an application instance and creates a service instance. 最后,该示例删除应用程序实例、取消预配应用程序类型,并从映像存储中删除应用程序包。Finally, the example removes the application instance, unprovisions the application type, and deletes the application package from the image store.

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();
}        
}
}

后续步骤Next steps

Service Fabric 应用程序升级Service Fabric application upgrade

Service Fabric 运行状况简介Service Fabric health introduction

对 Service Fabric 进行诊断和故障排除Diagnose and troubleshoot a Service Fabric service

在 Service Fabric 中对应用程序建模Model an application in Service Fabric