华为云 FunctionGraph 函数工作流:冷启动实测与适用场景

举报
yd_271063030 发表于 2026/11/09 00:15:41 2026/11/09
【摘要】 有个定时任务的需求——每天拉一次第三方 API 的数据,清洗后写数据库。原本跑在 ECS 的 cron 里,但那台机器大部分时间是空闲的,只为每天跑一分钟的任务付费不划算。试了下 FunctionGr

有个定时任务的需求——每天拉一次第三方 API 的数据,清洗后写数据库。原本跑在 ECS 的 cron 里,但那台机器大部分时间是空闲的,只为每天跑一分钟的任务付费不划算。试了下 FunctionGraph。

先说结论

适合:定时任务、事件驱动、低频调用、突发流量。

不适合:常驻服务、有状态应用、对延迟极敏感的场景(冷启动问题)。

函数怎么写

FunctionGraph 支持多种运行时,Python、Node.js、Java、Go 都有。我用 Python,入口函数约定:

import json

def handler(event, context):
    # event 是触发事件,定时触发器时是时间信息
    # context 里有 request_id、函数名等

    print("start", context.getRequestID())

    result = {
        "statusCode": 200,
        "body": json.dumps({"ok": True})
    }
    return result

依赖放在同目录,打包成 zip 上传。Python 的第三方包要在本地装好再打包,注意平台和 Python 版本要一致。

打包命令:

pip install -r requirements.txt -t ./package
cp handler.py ./package/
cd package && zip -r ../function.zip .

定时触发器

配置界面里可以加定时触发器,用 cron 表达式。

0 0 2 * * ?     # 每天 02:00
0 0/30 * * * ?  # 每 30 分钟

注意 FunctionGraph 用的是六位 cron(秒 分 时 日 月 周),最后一位是周不是年。第一次用七位写法会报错。

冷启动实测

这是最关心的点。测了三组:

场景 耗时
连续调用(热启动) 80-150ms
空闲 5 分钟后首次调用 1.2-1.8s
空闲 30 分钟后首次调用 2.5-3.5s

Python 运行时冷启动在 1-3 秒区间,取决于包大小和初始化逻辑。

减少冷启动的几个办法:

1. 精简依赖包

我们的包一开始 45MB(因为装了 pandas),冷启动 4 秒。去掉 pandas 换成标准库的 csv 处理,包降到 3MB,冷启动 1.2 秒。

pandas、numpy 这类大包对冷启动影响极大。

2. 把初始化代码放函数外

import pymysql

# 模块级初始化,冷启动时执行一次,热启动复用
conn = None

def get_conn():
    global conn
    if conn is None or not conn.open:
        conn = pymysql.connect(...)
    return conn

def handler(event, context):
    db = get_conn()
    ...

但注意:数据库连接可能因为超时被服务端断开,要处理重连。

3. 预热

配一个定时触发器,每 5 分钟调一次空函数,保持实例热着。但这会产生额外调用次数(虽然费用很低)。

对延迟敏感的场景,预热是必要成本。

一个完整的定时任务示例

需求:每天凌晨 2 点拉数据,清洗后写入 RDS。

import os
import json
import urllib.request
import pymysql

def handler(event, context):
    api_url = os.environ.get("API_URL")
    db_conf = {
        "host": os.environ.get("DB_HOST"),
        "user": os.environ.get("DB_USER"),
        "password": os.environ.get("DB_PASSWORD"),
        "database": os.environ.get("DB_NAME"),
    }

    # 1. 拉数据
    try:
        with urllib.request.urlopen(api_url, timeout=30) as resp:
            raw = json.loads(resp.read())
    except Exception as e:
        print(f"fetch failed: {e}")
        return {"statusCode": 500, "body": str(e)}

    # 2. 清洗
    rows = []
    for item in raw.get("data", []):
        if not item.get("id"):
            continue
        rows.append((
            item["id"],
            item.get("name", "")[:100],
            item.get("value", 0),
        ))

    if not rows:
        print("no valid rows")
        return {"statusCode": 200, "body": "empty"}

    # 3. 写库
    conn = pymysql.connect(**db_conf, connect_timeout=10)
    try:
        with conn.cursor() as cur:
            cur.executemany(
                "INSERT INTO stats (id, name, value) VALUES (%s, %s, %s) "
                "ON DUPLICATE KEY UPDATE name=VALUES(name), value=VALUES(value)",
                rows
            )
        conn.commit()
    finally:
        conn.close()

    print(f"inserted {len(rows)} rows")
    return {"statusCode": 200, "body": f"ok {len(rows)}"}

配置里要设:

  • 环境变量(API_URL、DB_*)
  • 超时时间(默认 3 秒,一定要改,我们设了 60 秒)
  • 内存(默认 128MB,Python 处理 JSON 建议 256MB 起)
  • VPC 网络(要访问 RDS 必须配 VPC,否则连不通内网)

VPC 配置是最容易漏的一步。函数默认在公网环境,要访问 RDS 这样的内网服务,必须把函数挂到同一个 VPC 和子网下。

费用怎么算

FunctionGraph 计费三部分:调用次数、执行时长(GB-秒)、公网流量。

免费额度:每月 100 万次调用 + 40 万 GB-秒。

我们的场景:每天 1 次,每次 3 秒,256MB 内存。

时长:3 秒 × 0.25GB × 30 天 = 22.5 GB-秒/月

远低于免费额度,基本白嫖。

对比 ECS:一台最低配 1C2G 每月也要几十块。低频任务用函数明显划算。

踩过的坑

坑一:超时时间太短

默认 3 秒,调用外部 API 经常超时。第一次跑报 Task timed out,改成 60 秒才正常。

坑二:VPC 配了但连不上 RDS

VPC 配了还要确认:

  • 子网是否有剩余 IP
  • RDS 的安全组是否放行该子网网段
  • 函数和 RDS 是否在同一区域

坑三:日志找不到

FunctionGraph 的日志默认写到 LTS(云日志服务)。控制台的「监控」里能看到调用记录,「日志」里能看到 print 输出,但需要先开通 LTS。

坑四:环境变量明文

敏感信息放环境变量里是明文存储的。更安全的做法是用「委托」机制,让函数通过 IAM 临时凭证访问其他服务,不落地长期密钥。

坑五:并发限制

默认单函数并发上限 100。突发流量超过会被限流(返回 429)。可以在控制台申请提升配额,或者配消息队列做缓冲。

什么场景值得用

值得:

  • 定时任务(数据同步、报表生成、清理)
  • 事件驱动(OBS 上传触发图片处理、消息队列消费)
  • Webhook 接收(第三方回调)
  • 低频 API

不值得:

  • 常驻 Web 服务(冷启动影响体验)
  • 长连接(WebSocket)
  • 需要本地状态的计算
  • 超过 15 分钟的长任务(函数有最大执行时长限制)

小结

FunctionGraph 的核心价值是「不用为闲置付费」。低频任务从 ECS 迁过来,成本能降一个数量级。

代价是要接受冷启动,以及把「常驻进程」的思维改成「无状态函数」。数据库连接、临时文件、内存缓存这些在函数里都要重新设计。

包体积是冷启动的关键,能砍的依赖尽量砍。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。