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

Azure App Service上传速度过慢问题排查与优化咨询

问题原因分析
  • Base64编码的体积膨胀:Base64会让原始二进制文件体积增加约33%,40-80MB的文件会变成53-107MB,大幅增加了网络传输量和服务端的解析耗时。
  • 全量内存加载的性能瓶颈:App Service B接收请求时,会把整个解码后的字节数组加载到内存中,S1层仅1.75GB的内存容量,大文件容易引发内存压力,导致GC频繁触发,拖慢处理速度。
  • JSON序列化/反序列化的额外开销:将大字节数组序列化为JSON再传输,服务端反序列化时需要耗费大量CPU和内存资源,这是大文件场景下的低效传输方式。
  • Blob上传方式不合理:使用MemoryStream一次性上传全量文件,没有采用分块上传机制,大文件单次上传易受网络波动影响,且无法利用Blob存储的分块优化能力。
  • S1层资源限制:S1层的CPU、网络带宽都有上限,大文件的传输、解析和上传操作很容易触达这些限制,导致处理速度骤降。
优化方案
  • 改用二进制流式传输,抛弃Base64
    用multipart/form-data直接传输二进制文件,避免编码膨胀和JSON序列化开销:
    App Service A端示例:
    private static async Task UploadFileToAppServiceB(HttpClient client, string fileName, byte[] fileContent)
    {
        var path = "https://www.foo.bar/upload";
        using var content = new MultipartFormDataContent();
        using var fileStreamContent = new ByteArrayContent(fileContent);
        content.Add(fileStreamContent, "file", fileName);
        
        client.Timeout = TimeSpan.FromMinutes(5);
        var response = await client.PostAsync(path, content);
        response.EnsureSuccessStatusCode();
    }
    
    App Service B端示例:
    [HttpPost("upload")]
    [RequestSizeLimit(209715200)]
    public async Task UploadFileToBlobStorage(IFormFile file)
    {
        var blobContainerClient = GetContainerClient();
        var blobClient = blobContainerClient.GetBlobClient(file.FileName);
        
        await using var fileStream = file.OpenReadStream();
        await blobClient.UploadAsync(fileStream, true);
    }
    
  • 流式处理,避免全量加载内存
    服务端接收文件时直接使用请求流或IFormFile的流,不将整个文件加载到字节数组,减少内存占用和GC压力。
  • 启用Blob分块上传
    对于大文件,使用BlockBlobClient进行分块上传,将文件分割为多个4MB-100MB的块并行上传,提升速度和稳定性:
    public async Task UploadFileInBlocks(IFormFile file)
    {
        var blobContainerClient = GetContainerClient();
        var blockBlobClient = blobContainerClient.GetBlockBlobClient(file.FileName);
        var blockSize = 4 * 1024 * 1024; // 4MB块大小
        var blockIds = new List<string>();
        
        await using var stream = file.OpenReadStream();
        var buffer = new byte[blockSize];
        int bytesRead;
        int blockIndex = 0;
        
        while ((bytesRead = await stream.ReadAsync(buffer, 0, blockSize)) > 0)
        {
            var blockId = Convert.ToBase64String(BitConverter.GetBytes(blockIndex++));
            blockIds.Add(blockId);
            await blockBlobClient.StageBlockAsync(blockId, new MemoryStream(buffer, 0, bytesRead));
        }
        
        await blockBlobClient.CommitBlockListAsync(blockIds);
    }
    
  • 升级App Service层
    如果业务需求无法降低文件大小,考虑将S1升级到S2/S3层,获得更高的CPU、内存和网络带宽,缓解资源瓶颈。
  • 跳过中转,直接上传Blob
    让App Service A直接上传到Blob Storage:由App Service B生成Blob的SAS令牌,A拿到令牌后直接上传,B仅负责权限校验和业务逻辑,减少中间环节的开销。
  • 优化HttpClient配置
    调整HttpClient的MaxResponseContentBufferSize,或使用HttpCompletionOption.ResponseHeadersRead避免全量缓存响应,提升传输效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 04:58:11