You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 16:01:14