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

Azure Function上传至Storage Account速度慢、耗时非线性问题咨询

Azure Function 向 Storage Account 上传大文件耗时异常、触发超时

问题背景

  • 业务需求:从Azure Function向关联Storage Account上传最大0.5GB的文件,当前上传耗时远超预期,超过10分钟触发Consumption计划超时限制
  • 异常表现:文件大小与上传耗时呈非线性关系:160MB文件上传耗时1.5分钟,290MB文件上传耗时超过10分钟,查阅官方文档、社区公开资料均未定位根因
  • 运行环境:Function App部署在Linux平台,Runtime版本4.0,采用Consumption托管计划(该计划最长执行时长限制为10分钟,已将host.json中超时参数配置为该计划允许的最大值)
  • 瓶颈排查:通过运行日志验证,网站数据爬取、数据转换为CSV格式的环节耗时极短,不属于性能瓶颈,超时全部发生在文件上传阶段

现有配置

function.json

{
  "scriptFile": "az_func.py",
  "bindings": [
    {
      "name": "mytimer",
      "type": "timerTrigger",
      "direction": "in",
      "schedule": "0 0 0 * * 2"
    },
    {
      "name": "$return",
      "type": "blob",
      "path": "cvmdailyreports/test_func_json.csv",
      "connection": "AzureWebJobsCVMDataStorageConn",
      "direction": "out"
    }
  ]
}

az_func.py 业务代码

import datetime
import logging

import azure.functions as func

from src.data.import_data import import_daily_reports
from src.data.transform_data import transform_daily_reports


def main(mytimer: func.TimerRequest):
    utc_timestamp = datetime.datetime.utcnow().replace(
        tzinfo=datetime.timezone.utc).isoformat()

    if mytimer.past_due:
        logging.info('The timer is past due!')

    logging.info('Python timer trigger function ran at %s', utc_timestamp)

    csv = transform_daily_reports(import_daily_reports(n=8)).to_csv(index=False)

    logging.info('The csv was created, sending to upload now.')

    return csv

根因说明

当前使用的Blob输出绑定默认走单块同步上传逻辑,各版本Python Worker对应的Blob SDK单块上传阈值在250MB-270MB区间。文件大小超过该阈值后,绑定层不会自动触发分块上传,反而会因为全量内容内存拷贝、上传失败全量重传的机制,导致耗时非线性暴涨。这个默认实现本身仅适配小文件上传场景,完全不适合100MB以上文件传输,耗时过长不属于正常现象。

优化方案

  • 弃用默认的Blob输出绑定,直接在代码中调用Azure Blob Storage SDK v12+的高级上传接口,自动走分块并发上传逻辑。该接口会根据文件大小自动拆分上传块,支持块级并发传输、失败块单独重传,同区域部署场景下290MB文件上传耗时可控制在10秒内,0.5GB文件上传耗时不超过30秒。
    1. 先修改function.json,删除$return对应的Blob输出绑定配置,避免绑定层重复执行上传逻辑。
    2. 替换原有代码中的返回逻辑,直接通过SDK上传,参考实现如下:
    import os
    import datetime
    import logging
    import azure.functions as func
    from azure.storage.blob import BlobClient
    from src.data.import_data import import_daily_reports
    from src.data.transform_data import transform_daily_reports
    
    
    def main(mytimer: func.TimerRequest):
        utc_timestamp = datetime.datetime.utcnow().replace(
            tzinfo=datetime.timezone.utc).isoformat()
    
        if mytimer.past_due:
            logging.info('The timer is past due!')
    
        logging.info('Python timer trigger function ran at %s', utc_timestamp)
    
        csv_bytes = transform_daily_reports(import_daily_reports(n=8)).to_csv(index=False).encode("utf-8")
        logging.info('The csv was created, starting parallel upload.')
    
        # 复用现有存储连接字符串配置
        blob_client = BlobClient.from_connection_string(
            conn_str=os.environ["AzureWebJobsCVMDataStorageConn"],
            container_name="cvmdailyreports",
            blob_name="test_func_json.csv"
        )
        # 根据Consumption计划实例默认1Gbps网卡带宽,配置8并发、4MB单块大小即可打满带宽
        blob_client.upload_blob(
            csv_bytes,
            overwrite=True,
            max_concurrency=8,
            block_size=4*1024*1024
        )
        logging.info('Upload completed.')
    
  • 若后续单文件大小超过1GB,可先将生成的CSV写入Function临时目录/tmp(Consumption计划下该目录可用空间不低于1GB),再通过SDK上传文件流,进一步降低内存开销,避免大文件内存占用过高触发实例回收导致上传中断。
  • 若后续存在更大文件、更稳定的上传需求,建议将Consumption计划替换为Premium计划:一是Premium计划最长执行时长可配置为60分钟,不会受10分钟超时限制;二是Premium计划实例与Storage Account之间走内网专用带宽,网络抖动更小,上传速度更稳定。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 02:21:17