Azure Function槽交换终止运行进程:是否为预期行为?
问题解答
这是槽交换的预期行为,同时你的配置存在可优化点来缓解该问题对生产场景的影响。
为什么槽交换会终止运行中的进程?
Azure App Service槽交换操作会触发原生产槽的宿主进程重启:交换过程中,生产槽的应用会被停止并替换为槽的应用内容/配置,所有依赖宿主进程运行的进程内函数实例(包括ServiceBus触发任务、Durable Functions编排/活动)都会被强制终止。对于ServiceBus触发器,未完成的消息默认会回到队列/主题触发重试,这与你的生产需求冲突。
解决方案
针对你的场景,需从配置和代码两方面调整,确保运行中任务能优雅完成,同时Durable Functions可持续运行:
1. 配置优雅关闭超时
添加应用设置WEBSITE_SHUTDOWN_TIMEOUT,给宿主进程足够时间完成正在执行的任务(最大支持1800秒)。
在你的Bicep配置中,给生产槽和槽都添加该设置:
// 生产槽的appSettings中添加 'WEBSITE_SHUTDOWN_TIMEOUT': '300' // 匹配你的任务5分钟执行时长 // 槽的siteConfig.appSettings中添加 { name: 'WEBSITE_SHUTDOWN_TIMEOUT' value: '300' }
2. 函数代码监听关闭信号
修改ServiceBus触发器函数,加入CancellationToken参数,响应宿主关闭请求,确保任务能在终止前完成:
using System; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.WebJobs; using Microsoft.Extensions.Logging; namespace ServiceBusFunctions { public class ServiceBusReceiver { private readonly ILogger<ServiceBusReceiver> _logger; public ServiceBusReceiver(ILogger<ServiceBusReceiver> log) { _logger = log; } [FunctionName("ServiceBusReceiver")] public async Task Run( [ServiceBusTrigger("functionslottestpfh-topic", "functionslottestpfh-subs", Connection = "ServiceBusConnection")] string mySbMsg, CancellationToken cancellationToken) { // 提前检测关闭信号,避免无意义执行 if (cancellationToken.IsCancellationRequested) { _logger.LogInformation("收到关闭请求,提前退出任务"); return; } // 将取消令牌传入耗时操作,确保能响应关闭信号 await Task.Delay(300000, cancellationToken); _logger.LogInformation("任务执行完成: {Msg}", mySbMsg); } } }
3. 保护Durable Functions的持久化配置
Durable Functions的状态存储在AzureWebJobsStorage指定的存储账户中,需确保该配置在槽交换时不被覆盖:
- 将
AzureWebJobsStorage设置为粘性槽设置,这样生产槽的该配置不会被槽的配置替换。 - 你的Bicep中设置了
WEBSITE_OVERRIDE_PRESERVE_DEFAULT_STICKY_SLOT_SETTINGS = 'false',这会取消默认粘性设置(包括AzureWebJobsStorage),建议改为true,或手动指定粘性设置:
resource function 'Microsoft.Web/sites@2022-09-01' = { name: functionAppName location: resourceGroup().location kind: 'functionapp' identity: { type: 'SystemAssigned' } properties: { alwaysOn: true serverFarmId: hostingPlan.id slotStickySettings: { appSettings: [ 'AzureWebJobsStorage' // 其他需要保留在生产槽的配置,如ServiceBus连接字符串(若生产与槽不同) ] } } }
4. 启用槽预热(可选)
配置槽的预热路径,确保槽在交换前已启动就绪,减少切换后新请求的延迟:
resource slot 'Microsoft.Web/sites/slots@2016-08-01' = { name: 'slot' location: resourceGroup().location kind: 'functionapp' parent: function identity: { type: 'SystemAssigned' } properties: { httpsOnly: true enabled: true alwaysOn: true serverFarmId: hostingPlan.id siteConfig: { warmupPath: '/api/health' // 假设你有健康检查函数 // 其他配置... } } }
总结
槽交换终止运行中进程是预期行为,但通过上述配置和代码调整,可确保正在执行的任务优雅完成、避免不必要重试,同时保证Durable Functions状态不丢失,满足你的生产需求。
内容的提问来源于stack exchange,提问作者Farizio
相关产品推荐
相关产品推荐

