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

.NET 6独立架构V4函数Cosmos操作频繁出现取消异常求助

问题背景
  • 基于.NET 6独立架构的V4 Azure Functions
  • CosmosClient初始化代码:
    var cosmosClient = CosmosClient.CreateAndInitializeAsync(cosmosSettings?.Endpoint, cosmosSettings?.Key, containers).Result; 
    services.AddSingleton(cosmosClient);
    
  • 仓储类通过构造函数获取容器,仅实现Save方法调用UpsertItemAsync执行数据写入
  • 批量执行逻辑:每次迭代创建25个异步任务调用Save,通过ContinueWith捕获异常,最终await Task.WhenAll等待全部完成
异常现象
  • App Insights上报大量Create/Query操作被取消的异常,但数据可正常入库
  • 自定义日志未捕获到对应异常信息
  • 当前请求量约250万次/小时,大量零RU成本的失败依赖记录严重干扰问题排查

解决方案

1. 修复CosmosClient初始化的同步阻塞问题

使用.Result会强制阻塞线程,可能引发上下文混乱或死锁,改为异步注入方式:

services.AddSingleton<CosmosClient>(async sp => 
{
    var cosmosSettings = sp.GetRequiredService<CosmosSettings>();
    return await CosmosClient.CreateAndInitializeAsync(cosmosSettings.Endpoint, cosmosSettings.Key, containers);
});

确保CosmosSettings已正确注入,避免空引用异常。

2. 替换ContinueWith为可靠的异步异常捕获

ContinueWith在异步场景下容易丢失异常上下文,且无法正确捕获取消类异常,建议在Save方法内部直接处理异常:

public async Task Save(ItemDbo itemDbo)
{
    try
    {
        await _container.UpsertItemAsync(itemDbo);
    }
    catch (OperationCanceledException ex)
    {
        _logger.LogWarning(ex, $"Upsert operation canceled for item {itemDbo.Id}");
    }
    catch (CosmosException ex)
    {
        _logger.LogError(ex, $"Upsert failed for item {itemDbo.Id}, Status Code: {ex.StatusCode}");
    }
    catch (Exception ex)
    {
        _logger.LogCritical(ex, $"Unexpected error during upsert for item {itemDbo.Id}");
    }
}

批量任务创建可简化为:

var taskList = new List<Task>();
foreach (var itemDbo in targetItems)
{
    taskList.Add(Save(itemDbo));
}
await Task.WhenAll(taskList);

3. 调整CosmosClient的超时与重试策略

默认配置可能无法应对高并发场景,延长超时时间并优化限流重试:

var cosmosClientOptions = new CosmosClientOptions
{
    RequestTimeout = TimeSpan.FromSeconds(30),
    MaxRetryAttemptsOnRateLimitedRequests = 10,
    MaxRetryWaitTimeOnRateLimitedRequests = TimeSpan.FromSeconds(30)
};

services.AddSingleton<CosmosClient>(async sp => 
{
    var cosmosSettings = sp.GetRequiredService<CosmosSettings>();
    return await CosmosClient.CreateAndInitializeAsync(
        cosmosSettings.Endpoint, 
        cosmosSettings.Key, 
        containers,
        cosmosClientOptions);
});

4. 排查函数执行超时问题

Azure Functions默认存在执行超时限制(消费计划为5分钟),如果批量任务执行时间过长,会被函数宿主强制终止,导致Cosmos请求被取消:

  • 检查函数配置(function.json或[FunctionName]属性)中的超时参数,按需调整
  • 高并发下拆分批量任务大小,例如从单次25个减少到10个,避免单次函数执行负载过高

5. 验证Cosmos容器RU配置

虽然异常显示零RU成本,但高并发下RU不足会触发限流,客户端重试过程中可能因函数超时被取消。需确认容器RU配置足够支撑250万次/小时的请求量,或开启RU自动缩放功能。


内容的提问来源于stack exchange,提问作者macm

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 17:01:15