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

.NET Framework 4.8下Azure.Storage库如何实现Blob重试日志记录?

升级Azure.Storage库实现Blob上传重试与日志记录

我有一个基于.NET Framework 4.8的老旧C# WinForms项目,原使用Microsoft.WindowsAzure.Storage库,现计划升级至最新的Azure.Storage库。原项目通过Microsoft.WindowsAzure.Storage.OperationContext记录Blob上传的重试及请求完成日志,目前已在BlobClientOptions中配置了重试次数,但不清楚如何在新库中实现类似的重试、错误及成功日志记录,且未找到相关的完善文档。

旧代码示例

var context = new OperationContext();
context.ClientRequestID = myid; //"some request id";
context.Retrying += (sender, args) =>
{
    int retryCnt = context.RequestResults.Count;               
    ErrorMessage("Upload failed. Start Retry " + retryCnt + " for BLOB: " + blobName, myid);
};

// define action when request is completed -> the request is also completed when the upload failed
context.RequestCompleted += (sender, args) =>
{
    /* Collect operation completion information */
    if (args.Response != null)
    {
        DebugMessage("Upload completed for BLOB " + blobName, myid);
    }
    else
    {
        int retryCnt = context.RequestResults.Count - 1;
        ErrorMessage("Upload failed (Retry " + retryCnt + ") for BLOB " + blobName, myid);
    }
};

已实现的新库重试配置

BlobContainerClient container = null;            
var options = new BlobClientOptions();            
options.Retry.MaxRetries = 4;

/* Create Handle to storage container using the sas to identify */
try
{                
    container = new BlobContainerClient(new Uri(sasToken),options);              
}
catch (Exception ex)
{
    ErrorMessage("container reference couldn't be set" + ex.Message, String.Empty);
}

解决方案

新的Azure.Storage库没有直接对应OperationContext的类,但可以通过自定义重试策略和请求处理器实现相同的日志需求,具体步骤如下:

1. 自定义重试策略记录重试事件

继承RetryPolicy类,重写ShouldRetryAsync方法,在重试触发时写入日志:

public class LoggingRetryPolicy : RetryPolicy
{
    private readonly string _blobName;
    private readonly string _requestId;
    public int RetryCount { get; private set; } = 0;

    public LoggingRetryPolicy(RetryPolicy basePolicy, string blobName, string requestId) 
        : base(basePolicy.MaxRetries, basePolicy.Delay, basePolicy.MaxDelay, basePolicy.Mode)
    {
        _blobName = blobName;
        _requestId = requestId;
    }

    public override async ValueTask<bool> ShouldRetryAsync(
        int attemptNumber,
        Exception exception,
        CancellationToken cancellationToken)
    {
        bool shouldRetry = await base.ShouldRetryAsync(attemptNumber, exception, cancellationToken);
        if (shouldRetry)
        {
            RetryCount++;
            ErrorMessage($"Upload failed. Start Retry {RetryCount} for BLOB: {_blobName}", _requestId);
        }
        return shouldRetry;
    }
}

2. 添加请求处理器记录请求完成事件

通过HttpPipelinePolicy拦截请求的完成状态,判断成功或失败并写入日志:

public class RequestLoggingPolicy : HttpPipelinePolicy
{
    private readonly string _blobName;
    private readonly string _requestId;

    public RequestLoggingPolicy(string blobName, string requestId)
    {
        _blobName = blobName;
        _requestId = requestId;
    }

    public override async ValueTask ProcessAsync(
        HttpPipelineMessage message,
        ReadOnlyMemory<HttpPipelinePolicy> pipeline,
        CancellationToken cancellationToken)
    {
        // 执行后续管道处理
        await ProcessNextAsync(message, pipeline, cancellationToken);

        // 请求完成后判断状态并记录日志
        if (message.Response.Status >= 200 && message.Response.Status < 300)
        {
            DebugMessage($"Upload completed for BLOB {_blobName}", _requestId);
        }
        else
        {
            var retryPolicy = message.Pipeline.GetRetryPolicy() as LoggingRetryPolicy;
            int retryCount = retryPolicy?.RetryCount ?? 0;
            ErrorMessage($"Upload failed (Retry {retryCount}) for BLOB {_blobName}", _requestId);
        }
    }
}

3. 配置BlobClientOptions并应用自定义策略

创建容器时替换默认重试策略,添加请求日志处理器:

var myid = "some request id";
var blobName = "your-target-blob-name";

var options = new BlobClientOptions();
// 基于默认指数退避策略创建带日志的重试策略
var baseRetry = new ExponentialBackoffRetryPolicy(4, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(10));
options.Retry.CustomPolicy = new LoggingRetryPolicy(baseRetry, blobName, myid);
// 添加请求日志处理器
options.AddPolicy(new RequestLoggingPolicy(blobName, myid), HttpPipelinePosition.PerCall);

BlobContainerClient container = null;
try
{
    container = new BlobContainerClient(new Uri(sasToken), options);
}
catch (Exception ex)
{
    ErrorMessage($"container reference couldn't be set: {ex.Message}", string.Empty);
}

补充说明

  • 如果需要全局复用日志策略,可以将请求ID、BlobName通过HttpPipelineMessage.Properties字典传递,避免每次创建策略时传入参数。
  • 不同Blob操作(上传、下载等)可以在调用具体方法前动态添加对应的日志策略。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 08:22:43