本指南提供了将应用程序从 Azure 云服务迁移到 Azure Service Fabric 的详细步骤和最佳做法。 在本指南中,我们建议使用 Service Fabric 托管群集 ,因为它们提供简化的群集管理、增强的安全性和自动修补。
应查看 从云服务迁移的决策矩阵 ,以确保从体系结构中选择正确的 Azure 服务。
迁移前的评估
在从 Azure 云服务迁移到 Service Fabric 之前,请进行全面的评估:
应用程序清单
- 记录所有 Web 角色和辅助角色
- 确定依赖项和集成点
- 映射存储需求(本地磁盘、Azure Storage 存储等)
- 文档缩放要求
流量模型和扩展要求
- 分析当前流量模式
- 记录缩放触发器和规则
- 评估自动缩放要求
状态管理
- 标识有状态组件
- 文档数据持久性机制
- 评估缓存依赖项
标识应用程序约束
- 启动依赖项
- 角色通信模式
- 部署要求
- 身份验证和安全约束
生产就绪情况评估
查看 Service Fabric 生产就绪情况清单 ,确保未来的 Service Fabric 应用程序符合生产标准。
体系结构规划
Service Fabric 托管群集与经典群集
Service Fabric 提供两种部署模型:
Service Fabric 托管群集(建议):简化的群集资源模型,其中Microsoft管理底层群集基础结构。
- 自动操作系统补丁更新
- 简化的部署和管理
- 减少了操作开销
- 内置安全最佳实践
- 详细了解 Service Fabric 托管群集
传统 Service Fabric 群集:可自定义,但需要更多作管理。
强烈建议使用 Service Fabric 托管群集 从云服务迁移,以简化操作并确保更好的安全态势。
Service Fabric 体系结构模式
将云服务组件映射到 Service Fabric 体系结构模式:
| 云服务组件 | Service Fabric 等效项 |
|---|---|
| Web 角色 | 使用 ASP.NET Core 的无状态服务 |
| 工作角色 | 具有后台处理的无状态服务 |
| 角色实例 | 服务实例和分区 |
| 角色环境 | Service Fabric 应用程序上下文 |
| 本地存储 | Service Fabric 本地存储卷 |
| RoleEntryPoint | ServiceInstanceListener 或 RunAsync 方法 |
托管群集的 Service Fabric 群集架构
若要设置 Service Fabric 托管群集,请参阅 Azure 快速入门模板存储库中提供的官方 ARM 模板。
基本的托管群集 ARM 模板如下所示(如 官方文档所示):
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json",
"contentVersion": "1.0.0.0",
"parameters": {
"clusterName": {
"type": "string",
"defaultValue": "GEN-UNIQUE",
"metadata": {
"description": "Name of your cluster - Between 3 and 23 characters. Letters and numbers only."
}
},
"adminUsername": {
"type": "string",
"metadata": {
"description": "Remote desktop user Id"
}
},
"adminPassword": {
"type": "securestring",
"metadata": {
"description": "Remote desktop user password. Must be a strong password"
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Location of the Cluster"
}
}
},
"variables": {
"sfManagedClusterName": "[parameters('clusterName')]",
"managedNodeType": "NT1"
},
"resources": [
{
"apiVersion": "2021-11-01-preview",
"type": "Microsoft.ServiceFabric/managedClusters",
"name": "[variables('sfManagedClusterName')]",
"location": "[parameters('location')]",
"sku": {
"name": "Basic"
},
"properties": {
"dnsName": "[variables('sfManagedClusterName')]",
"adminUserName": "[parameters('adminUsername')]",
"adminPassword": "[parameters('adminPassword')]"
}
},
{
"apiVersion": "2021-11-01-preview",
"type": "Microsoft.ServiceFabric/managedClusters/nodeTypes",
"name": "[concat(variables('sfManagedClusterName'), '/', variables('managedNodeType'))]",
"location": "[parameters('location')]",
"dependsOn": [
"[concat('Microsoft.ServiceFabric/managedClusters/', variables('sfManagedClusterName'))]"
],
"sku": {
"name": "Standard",
"tier": "Standard"
},
"properties": {
"isPrimary": true,
"vmInstanceCount": 5,
"dataDiskSizeGB": 100,
"vmSize": "Standard_D2s_v3"
}
}
]
}
有关详细的设置说明,请参阅 快速入门:使用 ARM 模板部署 Service Fabric 托管群集。
安全注意事项
Service Fabric 托管群集会自动处理大多数安全配置,包括:
- 自动群集证书轮换
- 默认安全节点到节点通信
- 群集配置数据的加密
- 内置网络安全规则
若要对群集进行客户端身份验证,需要配置客户端证书:
客户端证书:用于访问群集和 Service Fabric Explorer
- 使用自签名证书(用于开发/测试)或
- CA 颁发的证书(建议用于生产)
- 将客户端证书添加到托管群集配置
应用程序安全性:实施 应用程序和服务安全 建议
网络安全:根据 Service Fabric 安全性最佳做法配置 NSG 和防火墙
使用托管群集,可以主要关注应用程序级安全性和对群集的控制访问,同时Microsoft处理底层群集安全基础结构。
迁移策略
选择迁移方法
直接迁移
对应用程序体系结构的最小更改,侧重于调整现有代码以在 Service Fabric 中运行。
优点:
- 更快的迁移时间线
- 降低初始开发工作量
- 降低功能更改的风险
缺点:
- 不完全利用 Service Fabric 功能
- 可能将来需要重构以优化
重要限制:Service Fabric 托管群集当前 不支持容器。 如果应用程序需要 IIS、特定于 Windows 的服务器组件或其他最佳容器化的依赖项,则需要将传统的 Service Fabric 群集与 Windows 容器支持(而不是托管群集)配合使用。 规划直接迁移方法时,请仔细考虑此限制。 请参阅 容器化现有 Windows 应用程序
重构到微服务
将应用程序分解为微服务,以提高可伸缩性和更轻松的维护。
优点:
- Service Fabric 功能的完整利用
- 改进了可伸缩性和复原能力
- 更好地分离职责
缺点:
- 较高的初始开发工作量
- 需要建筑学专业知识
- 迁移时间线更长
基于应用程序要求的迁移方法
何时使用托管群集:
- 基于 .NET 构建的应用程序,可直接迁移到 Service Fabric 服务
- ASP.NET 可在不使用 IIS 的情况下运行的核心 Web 应用程序
- 具有轻型依赖项的应用程序
- 专为 Service Fabric 编写的新应用程序
何时使用经典版服务结构群集:
- 需要 Windows 容器的应用程序
- 具有 IIS 依赖项的工作负荷(应容器化)
- 具有复杂服务器组件依赖项的应用程序
- 需要容器化的方案
迁移阶段
设置 Service Fabric 环境
- 对于没有容器依赖项的应用程序:使用 Service Fabric 托管群集部署教程创建托管群集
- 对于需要容器的应用程序:使用 Windows 容器支持创建传统的 Service Fabric 群集
- 配置网络和安全性
- 为 Service Fabric 建立 CI/CD 流水线
迁移配置和设置
- 将云服务配置 (.cscfg, .csdef) 映射到 Service Fabric 应用程序清单
- 将环境设置迁移到 Service Fabric 参数
迁移代码
- 将 Web 角色适应无状态服务或容器化应用程序
- 使辅助角色适应无状态服务或 Reliable Services
- 将启动任务迁移到 Service Fabric 安装代码
迁移状态管理
- 实现适当的状态管理解决方案(可靠集合)
- 从外部存储迁移持久性状态
实现服务通信
- 将角色通信替换为 Service Fabric 通信模式
- 配置服务发现
测试和优化
- 验证功能和性能
- 测试扩展和故障转移场景
- 优化资源使用情况
分步迁移过程
1.设置 Azure Service Fabric 托管群集
若要部署 Service Fabric 托管群集,可以使用 PowerShell 命令,如 教程:部署 Service Fabric 托管群集中所述。
使用 PowerShell:
# Connect to your Azure account
Login-AzAccount
Set-AzContext -SubscriptionId <your-subscription>
# Create a new resource group
$resourceGroup = "myResourceGroup"
$location = "ChinaEast2"
New-AzResourceGroup -Name $resourceGroup -Location $location
# Create a Service Fabric managed cluster
$clusterName = "<unique cluster name>"
$password = "Password4321!@#" | ConvertTo-SecureString -AsPlainText -Force
$clientThumbprint = "<certificate thumbprint>" # Client certificate for authentication
$clusterSku = "Standard"
New-AzServiceFabricManagedCluster -ResourceGroupName $resourceGroup -Location $location -ClusterName $clusterName -ClientCertThumbprint $clientThumbprint -ClientCertIsAdmin -AdminPassword $password -Sku $clusterSKU -Verbose
# Add a primary node type to the cluster
$nodeType1Name = "NT1"
New-AzServiceFabricManagedNodeType -ResourceGroupName $resourceGroup -ClusterName $clusterName -Name $nodeType1Name -Primary -InstanceCount 5
重要说明:
- 对于生产部署,请使用标准 SKU(基本 SKU 仅用于测试)
- 需要提供用于访问群集的客户端证书指纹
- 每个 Service Fabric 群集都需要一个主节点类型,并且可能具有一个或多个辅助节点类型
- 使用 Service Fabric Explorer 工具对您的群集进行可视化操作
还可以使用 Azure 门户或 Azure CLI 进行部署。 有关基于门户的设置,请遵循 快速入门:创建 Service Fabric 托管群集 教程。
2. 创建 Service Fabric 应用程序项目
使用 Visual Studio 创建 Service Fabric 应用程序:
使用 Visual Studio:
3. 迁移云服务 Web 角色 - 综合示例
- 使用 ASP.NET Core 创建无状态服务
- 迁移控制器和视图
- 配置服务终结点
// Service registration in Program.cs
internal sealed class Program
{
private static void Main()
{
try
{
ServiceRuntime.RegisterServiceAsync("WebFrontEndType",
context => new WebFrontEnd(context)).GetAwaiter().GetResult();
ServiceEventSource.Current.ServiceTypeRegistered(
Process.GetCurrentProcess().Id, typeof(WebFrontEnd).Name);
Thread.Sleep(Timeout.Infinite);
}
catch (Exception e)
{
ServiceEventSource.Current.ServiceHostInitializationFailed(e.ToString());
throw;
}
}
}
// Service implementation
internal sealed class WebFrontEnd : StatelessService
{
public WebFrontEnd(StatelessServiceContext context)
: base(context)
{ }
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new ServiceInstanceListener[]
{
new ServiceInstanceListener(serviceContext =>
new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
{
var builder = WebApplication.CreateBuilder();
builder.Services.AddSingleton<StatelessServiceContext>(serviceContext);
// Add services to the container
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
// Configure middleware
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllers();
app.MapRazorPages();
return app;
}))
};
}
}
4. 移植云服务工作角色 - 综合示例
- 使用后台处理创建无状态服务
- 将工作逻辑移至 RunAsync 方法
- 实现服务事件和计时器功能
internal sealed class WorkerBackgroundService : StatelessService
{
private readonly TimeSpan _interval = TimeSpan.FromSeconds(30);
public WorkerBackgroundService(StatelessServiceContext context)
: base(context)
{ }
protected override async Task RunAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
try
{
// Migrated worker role processing logic
await ProcessQueueMessagesAsync(cancellationToken);
await Task.Delay(_interval, cancellationToken);
}
catch (Exception ex)
{
ServiceEventSource.Current.ServiceMessage(Context, $"Exception in RunAsync: {ex.Message}");
// Implement appropriate retry logic
}
}
}
private async Task ProcessQueueMessagesAsync(CancellationToken cancellationToken)
{
// Implement your worker logic here
}
}
5. 配置迁移
Service Fabric 使用分层配置模型:
- ApplicationManifest.xml:应用程序范围的配置
<ApplicationManifest ApplicationTypeName="MyApplicationType"
ApplicationTypeVersion="1.0.0"
xmlns="http://schemas.microsoft.com/2011/01/fabric"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Parameters>
<Parameter Name="WebFrontEnd_InstanceCount" DefaultValue="-1" />
<Parameter Name="StorageAccountConnectionString" DefaultValue="" />
<Parameter Name="ASPNETCORE_ENVIRONMENT" DefaultValue="Production" />
</Parameters>
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="WebFrontEndPkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides>
<ConfigOverride Name="Config">
<Settings>
<Section Name="ConnectionStrings">
<Parameter Name="StorageAccount" Value="[StorageAccountConnectionString]" />
</Section>
<Section Name="Environment">
<Parameter Name="ASPNETCORE_ENVIRONMENT" Value="[ASPNETCORE_ENVIRONMENT]" />
</Section>
</Settings>
</ConfigOverride>
</ConfigOverrides>
</ServiceManifestImport>
</ApplicationManifest>
- ServiceManifest.xml:特定于服务的配置
<ServiceManifest Name="WebFrontEndPkg"
Version="1.0.0"
xmlns="http://schemas.microsoft.com/2011/01/fabric"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ConfigPackage Name="Config" Version="1.0.0" />
<CodePackage Name="Code" Version="1.0.0">
<EntryPoint>
<ExeHost>
<Program>WebFrontEnd.exe</Program>
<WorkingFolder>CodeBase</WorkingFolder>
</ExeHost>
</EntryPoint>
</CodePackage>
<Resources>
<Endpoints>
<Endpoint Name="ServiceEndpoint" Protocol="http" Port="8080" />
</Endpoints>
</Resources>
</ServiceManifest>
- Settings.xml:配置设置
<?xml version="1.0" encoding="utf-8" ?>
<Settings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<Section Name="ConnectionStrings">
<Parameter Name="StorageAccount" Value="" />
</Section>
<Section Name="Environment">
<Parameter Name="ASPNETCORE_ENVIRONMENT" Value="Production" />
</Section>
</Settings>
6. Service Fabric 中的访问配置
// Accessing configuration in a Service Fabric service
public sealed class WebFrontEnd : StatelessService
{
private readonly IConfiguration _configuration;
public WebFrontEnd(StatelessServiceContext context)
: base(context)
{
// Load Service Fabric configuration
var configPackagePath = context.CodePackageActivationContext.GetConfigurationPackageObject("Config").Path;
_configuration = new ConfigurationBuilder()
.SetBasePath(configPackagePath)
.AddJsonFile("appsettings.json", optional: true)
.AddXmlFile("Settings.xml")
.AddEnvironmentVariables()
.Build();
}
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
// Create service listeners using configuration
var connectionString = _configuration.GetSection("ConnectionStrings")["StorageAccount"];
// Use connection string to configure services
}
}
7.部署到 Service Fabric 托管群集
- 打包 Service Fabric 应用程序:
# Package the Service Fabric application
$appPkgPath = "C:\MyServiceFabricApp\pkg"
Copy-ServiceFabricApplicationPackage -ApplicationPackagePath $appPkgPath -CompressPackage -SkipCopy
- 部署到托管群集:
# Connect to the cluster
Connect-ServiceFabricCluster -ConnectionEndpoint "mycluster.chinanorth.cloudapp.chinacloudapi.cn:19000"
# Register and create the application
Register-ServiceFabricApplicationType -ApplicationPackagePathInImageStore MyServiceFabricApp
New-ServiceFabricApplication -ApplicationName fabric:/MyServiceFabricApp -ApplicationTypeName MyServiceFabricAppType -ApplicationTypeVersion 1.0.0
您也可以使用 Azure Pipelines 来自动化部署至 Service Fabric 托管群集。
测试和验证
功能测试
- 验证所有应用程序功能
- 测试服务发现和通信
- 验证配置是否已正确加载
- 验证用户体验和流程
性能测试
- 将响应时间与云服务进行比较
- 在预期的用户负载下进行测试
- 验证自动缩放参数
- 度量资源使用情况
复原测试
- 测试故障转移方案
- 验证实例回收行为
- 测试升级和回滚过程
- 模拟基础结构故障
验证清单
- [ ] 所有功能都正常运行
- [ ] 性能满足或超过云服务
- [ ] 配置迁移已完成
- [ ] 日志记录和诊断工作
- [ ] 满足安全要求
- [ ] 已建立部署管道
- [ ] 已配置监视和警报
- [ ] 回滚程序已记录在案
迁移后注意事项
监视和诊断
警告
不再支持用于 Service Fabric SDK 的 Application Insights。
使用 Service Fabric Explorer 工具对您的群集进行可视化操作
配置 Service Fabric 的监控和诊断以用于您的应用程序
- 启用 Application Insights
- 配置 Service Fabric 诊断数据收集
- 设置警报和仪表板
- 实现运行状况报告
// Adding health reporting in your service
var healthClient = new FabricClient().HealthManager;
var healthReport = new HealthReport(
serviceName: new Uri("fabric:/MyApp/MyService"),
sourceId: "MyHealthWatcher",
healthProperty: "Connectivity",
healthState: HealthState.Ok,
description: "Service is connected to dependencies"
);
await healthClient.ReportHealthAsync(healthReport);
缩放和优化
Service Fabric 托管群集支持 手动缩放 和自动缩放:
{
"apiVersion": "2021-05-01",
"type": "Microsoft.ServiceFabric/managedClusters/nodeTypes",
"name": "[concat(parameters('clusterName'), '/FrontEnd')]",
"location": "[parameters('location')]",
"properties": {
"vmInstanceCount": 5,
"primaryCount": 5,
"dataDiskSizeGB": 100,
"vmSize": "Standard_D2s_v3"
}
}
灾难恢复规划
- 配置 Service Fabric 备份和还原服务
- 根据需要实现异地复制
- 文档恢复过程
- 测试灾难恢复方案
安全状况
遵循安全最佳做法:
- 应用 Service Fabric 安全最佳做法
- 定期更新客户端证书
- 审查网络安全
- 在应用程序中实现适当的身份验证和授权
故障排除指南
部署问题
- 验证应用程序清单是否正确
- 检查群集运行状况和容量
- 验证服务包版本
- 查看部署日志
运行时错误
- 检查服务日志
- 验证配置设置
- 验证服务通信
- 查看健康事件
性能问题
- 分析资源使用情况
- 检查 分区负载
- 验证缩放策略
- 查看服务代码中的瓶颈
常见错误方案和解决方法
| 错误 | 可能的原因 | 决议 |
|---|---|---|
| 服务激活失败 | 缺少依赖项或配置 | 验证服务包中包含所有依赖项和配置值 |
| 通信失败 | 网络/防火墙问题 | 检查负载均衡器规则/探测器、NSG 规则和服务终结点 |
| 配置错误 | 参数不匹配 | 在所有层中验证配置设置 |
| 缩放问题 | 群集容量 | 查看节点资源利用率并根据需要增加容量 |
常见迁移方案
Web 角色迁移
有关将 ASP.NET Web 角色迁移到 Service Fabric 无状态服务的综合分步指南,请参阅 Web 角色迁移示例。 本指南提供了原始 Web 角色与 Service Fabric 实现之间的详细代码比较,包括项目结构、配置文件、中间件迁移和部署策略以及并行代码示例。
工作角色迁移
有关将辅助角色后台处理转换为 Service Fabric 的详细指南,请参阅 辅助角色迁移示例。 本指南演示了从云服务后台处理到 Service Fabric 中的可靠任务执行的体系结构转换,包括可靠计时器、队列处理和状态持久性的实现以及实际代码示例。
状态管理迁移
有关将应用程序状态管理迁移到 Service Fabric 的深入指南,请参阅 状态管理迁移示例。 本技术指南介绍了如何使用会话管理、工作流处理和缓存的实现模式以及数据迁移策略、备份/还原过程以及将 Service Fabric 状态管理与外部存储相结合的混合方法转换为 Reliable Collections。