将 Web 角色和辅助角色转换成 Service Fabric 无状态服务的指南Guide to converting Web and Worker Roles to Service Fabric stateless services

本文说明如何将云服务的 Web 角色和辅助角色迁移到 Service Fabric 无状态服务。This article describes how to migrate your Cloud Services Web and Worker Roles to Service Fabric stateless services. 对于整体体系结构大致保持相同的应用程序来说,这是最简单的云服务到 Service Fabric 迁移路径。This is the simplest migration path from Cloud Services to Service Fabric for applications whose overall architecture is going to stay roughly the same.

云服务项目到 Service Fabric 应用程序项目Cloud Service project to Service Fabric application project

云服务项目和 Service Fabric 应用程序项目结构类似,两者都可代表应用程序的部署单位,也就是说,两者各自定义可在部署后运行应用程序的完整包。A Cloud Service project and a Service Fabric Application project have a similar structure and both represent the deployment unit for your application - that is, they each define the complete package that is deployed to run your application. 云服务项目包含一个或多个 Web 角色和辅助角色。A Cloud Service project contains one or more Web or Worker Roles. 同理,Service Fabric 应用程序项目包含一个或多个服务。Similarly, a Service Fabric Application project contains one or more services.

两者的差别在于,云服务项目结合应用程序部署与 VM 部署,因此其中包含 VM 配置设置,而 Service Fabric 应用程序项目只定义将要部署到 Service Fabric 群集中一组现有 VM 的应用程序。The difference is that the Cloud Service project couples the application deployment with a VM deployment and thus contains VM configuration settings in it, whereas the Service Fabric Application project only defines an application that will be deployed to a set of existing VMs in a Service Fabric cluster. Service Fabric 群集本身只可通过 Resource Manager 模板或 Azure 门户部署一次,但可在群集中部署多个 Service Fabric 应用程序。The Service Fabric cluster itself is only deployed once, either through an Resource Manager template or through the Azure portal, and multiple Service Fabric applications can be deployed to it.

Service Fabric 与云服务项目的比较

辅助角色到无状态服务Worker Role to stateless service

从概念上讲,辅助角色代表无状态的工作负荷,这意味着工作负荷的每个实例都是相同的,随时可将请求路由到任何实例。Conceptually, a Worker Role represents a stateless workload, meaning every instance of the workload is identical and requests can be routed to any instance at any time. 每个实例不需要记住前一个请求。Each instance is not expected to remember the previous request. 工作负荷的运行状态由外部状态存储(例如 Azure 表存储或 Azure Cosmos DB)管理。State that the workload operates on is managed by an external state store, such as Azure Table Storage or Azure Cosmos DB. 在 Service Fabric 中,此类工作负荷以无状态服务来表示。In Service Fabric, this type of workload is represented by a Stateless Service. 将辅助角色迁移到 Service Fabric 的最简单方法是将辅助角色代码转换成无状态服务。The simplest approach to migrating a Worker Role to Service Fabric can be done by converting Worker Role code to a Stateless Service.

辅助角色到无状态服务

Web 角色到无状态服务Web Role to stateless service

与辅助角色类似,Web 角色也代表无状态的工作负荷,因此在概念上也能映射到 Service Fabric 无状态服务。Similar to Worker Role, a Web Role also represents a stateless workload, and so conceptually it too can be mapped to a Service Fabric stateless service. 不过,与 Web 角色不同的是,Service Fabric 不支持 IIS。However, unlike Web Roles, Service Fabric does not support IIS. 要将 Web 应用程序从 Web 角色迁移到无状态服务,需要先移动到可以自我托管且不依赖 IIS 或 System.Web 的 Web 框架(例如 ASP.NET Core 1)。To migrate a web application from a Web Role to a stateless service requires first moving to a web framework that can be self-hosted and does not depend on IIS or System.Web, such as ASP.NET Core 1.

应用程序Application 支持Supported 迁移路径Migration path
ASP.NET Web 窗体ASP.NET Web Forms No 转换为 ASP.NET Core 1 MVCConvert to ASP.NET Core 1 MVC
ASP.NET MVCASP.NET MVC 使用迁移With Migration 升级到 ASP.NET Core 1 MVCUpgrade to ASP.NET Core 1 MVC
ASP.NET Web APIASP.NET Web API 使用迁移With Migration 使用自托管服务器或 ASP.NET Core 1Use self-hosted server or ASP.NET Core 1
ASP.NET Core 1ASP.NET Core 1 Yes 空值N/A

入口点 API 和生命周期Entry point API and lifecycle

辅助角色和 Service Fabric 服务 API 提供类似的入口点:Worker Role and Service Fabric service APIs offer similar entry points:

入口点Entry Point 辅助角色Worker Role Service Fabric 服务Service Fabric service
ProcessingProcessing Run() RunAsync()
VM 启动VM start OnStart() 空值N/A
VM 停止VM stop OnStop() 空值N/A
为客户端请求打开侦听器Open listener for client requests 空值N/A
  • 适用于无状态服务的 CreateServiceInstanceListener()CreateServiceInstanceListener() for stateless
  • 适用于有状态服务的 CreateServiceReplicaListener()CreateServiceReplicaListener() for stateful

辅助角色Worker Role


using Microsoft.WindowsAzure.ServiceRuntime;

namespace WorkerRole1
{
    public class WorkerRole : RoleEntryPoint
    {
        public override void Run()
        {
        }

        public override bool OnStart()
        {
        }

        public override void OnStop()
        {
        }
    }
}

Service Fabric 无状态服务Service Fabric Stateless Service


using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.ServiceFabric.Services.Communication.Runtime;
using Microsoft.ServiceFabric.Services.Runtime;

namespace Stateless1
{
    public class Stateless1 : StatelessService
    {
        protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
        {
        }

        protected override Task RunAsync(CancellationToken cancelServiceInstance)
        {
        }
    }
}

两者都有可从中开始处理的主要“Run”重写。Both have a primary "Run" override in which to begin processing. Service Fabric 服务将 RunStartStop 合并为单一入口点 RunAsyncService Fabric services combine Run, Start, and Stop into a single entry point, RunAsync. RunAsync 启动时,服务应开始工作;发出 RunAsync 方法的 CancellationToken 信号时,应停止工作。Your service should begin working when RunAsync starts, and should stop working when the RunAsync method's CancellationToken is signaled.

辅助角色和 Service Fabric 服务的生命周期与生存期之间有几个主要差异:There are several key differences between the lifecycle and lifetime of Worker Roles and Service Fabric services:

  • 生命周期: 最大的差异为辅助角色是 VM,因此其生命周期绑定到 VM,且包含 VM 启动和停止时的事件。Lifecycle: The biggest difference is that a Worker Role is a VM and so its lifecycle is tied to the VM, which includes events for when the VM starts and stops. Service Fabric 服务的生命周期与 VM 的生命周期不同,因此不包含主机 VM 或计算机启动和停止时的事件,因为它们彼此不相关。A Service Fabric service has a lifecycle that is separate from the VM lifecycle, so it does not include events for when the host VM or machine starts and stop, as they are not related.
  • 生存期:如果 Run 方法退出,辅助角色实例将回收。Lifetime: A Worker Role instance will recycle if the Run method exits. 但是,Service Fabric 服务中的 RunAsync 方法可以运行到完成为止,服务实例将保持运行状态。The RunAsync method in a Service Fabric service however can run to completion and the service instance will stay up.

Service Fabric 为侦听客户端请求的服务提供可选的通信设置入口点。Service Fabric provides an optional communication setup entry point for services that listen for client requests. RunAsync 和通信入口点都是 Service Fabric 服务中的可选重写(服务可选择只侦听客户端请求和/或只运行处理循环),这就是 RunAsync 方法无需重新启动服务实例就可退出的原因,因为它可以继续侦听客户端请求。Both the RunAsync and communication entry point are optional overrides in Service Fabric services - your service may choose to only listen to client requests, or only run a processing loop, or both - which is why the RunAsync method is allowed to exit without restarting the service instance, because it may continue to listen for client requests.

应用程序 API 和环境Application API and environment

云服务环境 API 提供当前 VM 实例的信息和功能,以及有关其他 VM 角色实例的信息。The Cloud Services environment API provides information and functionality for the current VM instance as well as information about other VM role instances. Service Fabric 提供有关其运行时的信息,以及有关服务当前运行所在的节点的某些信息。Service Fabric provides information related to its runtime and some information about the node a service is currently running on.

环境任务Environment Task 云服务Cloud Services Service FabricService Fabric
配置设置和更改通知Configuration Settings and change notification RoleEnvironment CodePackageActivationContext
本地存储Local Storage RoleEnvironment CodePackageActivationContext
终结点信息Endpoint Information RoleInstance
  • 当前实例:RoleEnvironment.CurrentRoleInstanceCurrent instance: RoleEnvironment.CurrentRoleInstance
  • 其他角色和实例:RoleEnvironment.RolesOther roles and instance: RoleEnvironment.Roles
  • 适用于当前节点地址的 NodeContextNodeContext for current Node address
  • 适用于服务终结点发现的 FabricClientServicePartitionResolverFabricClient and ServicePartitionResolver for service endpoint discovery
环境模拟Environment Emulation RoleEnvironment.IsEmulated 空值N/A
同时更改事件Simultaneous change event RoleEnvironment 空值N/A

配置设置Configuration settings

云服务中的配置设置是针对 VM 角色设置的,将应用到该 VM 角色的所有实例。Configuration settings in Cloud Services are set for a VM role and apply to all instances of that VM role. 这些设置是 ServiceConfiguration.*.cscfg 文件中设置的键-值对,可直接通过 RoleEnvironment 进行访问。These settings are key-value pairs set in ServiceConfiguration.*.cscfg files and can be accessed directly through RoleEnvironment. 在 Service Fabric 中,设置单独应用到每个服务和每个应用程序,而不是应用到 VM,因为 VM 可以托管多个服务和应用程序。In Service Fabric, settings apply individually to each service and to each application, rather than to a VM, because a VM can host multiple services and applications. 服务由三个包组成:A service is composed of three packages:

  • 代码: 包含服务的可执行文件、二进制文件、DLL 和服务需要运行的任何其他文件。Code: contains the service executables, binaries, DLLs, and any other files a service needs to run.
  • 配置: 服务的所有配置文件和设置。Config: all configuration files and settings for a service.
  • 数据: 与服务关联的静态数据文件。Data: static data files associated with the service.

其中每个包可独立设置版本和进行升级。Each of these packages can be independently versioned and upgraded. 与云服务类似,可通过 API 以编程方式访问配置包。发生配置包更改时,系统会提供事件来通知服务。Similar to Cloud Services, a config package can be accessed programmatically through an API and events are available to notify the service of a config package change. Settings.xml 文件可用于键-值配置和编程访问,这与 App.config 文件的应用设置部分类似。A Settings.xml file can be used for key-value configuration and programmatic access similar to the app settings section of an App.config file. 但是,与云服务不同的是,Service Fabric 配置包可以包含任何格式的任何配置文件,不管是 XML、JSON、YAML 还是自定义的二进制格式。However, unlike Cloud Services, a Service Fabric config package can contain any configuration files in any format, whether it's XML, JSON, YAML, or a custom binary format.

访问配置Accessing configuration

云服务Cloud Services

可通过 RoleEnvironment 访问 ServiceConfiguration.*.cscfg 中的配置设置。Configuration settings from ServiceConfiguration.*.cscfg can be accessed through RoleEnvironment. 这些设置可全局提供给同一云服务部署中的所有角色实例使用。These settings are globally available to all role instances in the same Cloud Service deployment.


string value = RoleEnvironment.GetConfigurationSettingValue("Key");

Service FabricService Fabric

每个服务都有自身的独立配置包。Each service has its own individual configuration package. 可供群集中所有应用程序访问的全局配置设置没有内置机制。There is no built-in mechanism for global configuration settings accessible by all applications in a cluster. 使用配置包中的 Service Fabric 特殊配置文件 Settings.xml 时,Settings.xml 中的值可以在应用程序级别覆盖,实现应用程序级别的配置设置。When using Service Fabric's special Settings.xml configuration file within a configuration package, values in Settings.xml can be overwritten at the application level, making application-level configuration settings possible.

通过服务的 CodePackageActivationContext 可在每个服务实例中访问配置设置。Configuration settings are accesses within each service instance through the service's CodePackageActivationContext.


ConfigurationPackage configPackage = this.Context.CodePackageActivationContext.GetConfigurationPackageObject("Config");

// Access Settings.xml
KeyedCollection<string, ConfigurationProperty> parameters = configPackage.Settings.Sections["MyConfigSection"].Parameters;

string value = parameters["Key"]?.Value;

// Access custom configuration file:
using (StreamReader reader = new StreamReader(Path.Combine(configPackage.Path, "CustomConfig.json")))
{
    MySettings settings = JsonConvert.DeserializeObject<MySettings>(reader.ReadToEnd());
}

配置更新事件Configuration update events

云服务Cloud Services

当环境中发生更改(例如配置更改)时,将使用 RoleEnvironment.Changed 事件来通知所有角色实例。The RoleEnvironment.Changed event is used to notify all role instances when a change occurs in the environment, such as a configuration change. 通过此事件可以使用配置更新,却无需回收角色实例或重新启动辅助角色进程。This is used to consume configuration updates without recycling role instances or restarting a worker process.


RoleEnvironment.Changed += RoleEnvironmentChanged;

private void RoleEnvironmentChanged(object sender, RoleEnvironmentChangedEventArgs e)
{
   // Get the list of configuration changes
   var settingChanges = e.Changes.OfType<RoleEnvironmentConfigurationSettingChange>();
foreach (var settingChange in settingChanges) 
   {
      Trace.WriteLine("Setting: " + settingChange.ConfigurationSettingName, "Information");
   }
}

Service FabricService Fabric

在服务中的三个包类型(代码、配置和数据)中,每个类型都会提供可在包更新、添加或删除时通知服务实例的事件。Each of the three package types in a service - Code, Config, and Data - have events that notify a service instance when a package is updated, added, or removed. 一个服务可以包含每种类型的多个包。A service can contain multiple packages of each type. 例如,一个服务可以有多个配置包,其中每个包可单独设置版本并且可升级。For example, a service may have multiple config packages, each individually versioned and upgradeable.

通过这些事件可以使用服务包中的更改,而无需重新启动服务实例。These events are available to consume changes in service packages without restarting the service instance.


this.Context.CodePackageActivationContext.ConfigurationPackageModifiedEvent +=
                    this.CodePackageActivationContext_ConfigurationPackageModifiedEvent;

private void CodePackageActivationContext_ConfigurationPackageModifiedEvent(object sender, PackageModifiedEventArgs<ConfigurationPackage> e)
{
    this.UpdateCustomConfig(e.NewPackage.Path);
    this.UpdateSettings(e.NewPackage.Settings);
}

启动任务Startup tasks

启动任务是应用程序启动前执行的操作。Startup tasks are actions that are taken before an application starts. 启动任务通常用于以提升的权限运行设置脚本。A startup task is typically used to run setup scripts using elevated privileges. 云服务和 Service Fabric 均支持启动任务。Both Cloud Services and Service Fabric support start-up tasks. 两者的主要差异是,云服务中的启动任务绑定到 VM,因为 VM 是角色实例的一部分;而 Service Fabric 中的启动任务则绑定到服务,而不绑定到任何特定 VM。The main difference is that in Cloud Services, a startup task is tied to a VM because it is part of a role instance, whereas in Service Fabric a startup task is tied to a service, which is not tied to any particular VM.

Service FabricService Fabric 云服务Cloud Services
配置位置Configuration location ServiceDefinition.csdefServiceDefinition.csdef
特权Privileges “受限”或“提升”"limited" or "elevated"
序列Sequencing “简单”、“后台”、“前台”"simple", "background", "foreground"

云服务Cloud Services

云服务中的启动入口点是在 ServiceDefinition.csdef 中针对每个角色配置的。In Cloud Services a startup entry point is configured per role in ServiceDefinition.csdef.


<ServiceDefinition>
    <Startup>
        <Task commandLine="Startup.cmd" executionContext="limited" taskType="simple" >
            <Environment>
                <Variable name="MyVersionNumber" value="1.0.0.0" />
            </Environment>
        </Task>
    </Startup>
    ...
</ServiceDefinition>

Service FabricService Fabric

Service Fabric 中的启动入口点是在 ServiceManifest.xml 中针对每个服务配置的。In Service Fabric a startup entry point is configured per service in ServiceManifest.xml:


<ServiceManifest>
  <CodePackage Name="Code" Version="1.0.0">
    <SetupEntryPoint>
      <ExeHost>
        <Program>Startup.bat</Program>
      </ExeHost>
    </SetupEntryPoint>
    ...
</ServiceManifest>

有关开发环境的说明A note about development environment

云服务和 Service Fabric 都使用项目模板来与 Visual Studio 集成,并支持在本地和 Azure 中调试、配置及部署。Both Cloud Services and Service Fabric are integrated with Visual Studio with project templates and support for debugging, configuring, and deploying both locally and to Azure. 此外,云服务和 Service Fabric 都提供本地开发运行时环境。Both Cloud Services and Service Fabric also provide a local development runtime environment. 差别在于,云服务的开发运行时模拟其运行所在的 Azure 环境,Service Fabric 不使用模拟器,而是使用完整的 Service Fabric 运行时。The difference is that while the Cloud Service development runtime emulates the Azure environment on which it runs, Service Fabric does not use an emulator - it uses the complete Service Fabric runtime. 在本地开发计算机运行的 Service Fabric 环境就是在生产时运行的同一环境。The Service Fabric environment you run on your local development machine is the same environment that runs in production.

后续步骤Next steps

阅读有关 Service Fabric Reliable Services 的详细信息以及云服务与 Service Fabric 应用程序体系结构之间的根本差异,以了解如何利用 Service Fabric 的完整功能集。Read more about Service Fabric Reliable Services and the fundamental differences between Cloud Services and Service Fabric application architecture to understand how to take advantage of the full set of Service Fabric features.