从零踩坑到优雅落地:基于华为云 FunctionGraph 与 OBS 的无服务器图片处理实战

举报
yd_253900565 发表于 2026/10/19 12:11:21 2026/10/19
【摘要】 在最近的项目重构中,我们遇到了典型的非结构化文件处理瓶颈:用户上传的高清原图体积普遍在 5MB 以上,直接入库不仅拖慢客户端加载速度,还造成了不必要的公网下行流量开销。为了实现“上传即压缩”,我们舍弃了常驻 ECS 轮询方案,改用华为云 OBS(对象存储服务)+ FunctionGraph(函数工作流) 构建轻量级的 Serverless 事件驱动链路。核心架构思路整个链路无需常驻进程,按需...
在最近的项目重构中,我们遇到了典型的非结构化文件处理瓶颈:用户上传的高清原图体积普遍在 5MB 以上,直接入库不仅拖慢客户端加载速度,还造成了不必要的公网下行流量开销。

为了实现“上传即压缩”,我们舍弃了常驻 ECS 轮询方案,改用华为云 OBS(对象存储服务)+ FunctionGraph(函数工作流) 构建轻量级的 Serverless 事件驱动链路。

核心架构思路

整个链路无需常驻进程,按需触发:

  1. 上传原图:前端将图片直传至 OBS 桶的 raw/ 目录。

  2. 事件联动:OBS 产生 ObjectCreated 事件,自动投递并触发 FunctionGraph。

  3. 函数处理:函数拉取图片流,调用无损/有损压缩算法调整尺寸与格式(统一转 WebP),输出至 thumbnail/ 目录。

  4. 清理释放:执行完毕后容器实例自动回收,实现“零闲置成本”。

极简处理逻辑示例 (Python 3.9)

在 FunctionGraph 中,通过事件入参即可拿到触发文件的元数据:

Python
import os
from PIL import Image
from obs import ObsClient

def handler(event, context):
    # 1. 解析 OBS 触发器传递的事件信息
    record = event['Records'][0]['obs']
    bucket_name = record['bucket']['name']
    object_key = record['object']['key']
    
    # 避免无限触发递归(仅处理 raw/ 目录)
    if not object_key.startswith("raw/"):
        return {"code": 0, "msg": "Skip non-raw image"}

    # 2. 从上下文获取临时 AK/SK,无需硬编码
    ak = context.getAccessKey()
    sk = context.getSecretKey()
    server = context.getUserData('obs_server')
    
    obs_client = ObsClient(access_key_id=ak, secret_access_key=sk, server=server)

    # 3. 下载、压缩并回传
    download_path = f"/tmp/{os.path.basename(object_key)}"
    upload_path = f"/tmp/out_{os.path.basename(object_key)}"
    
    obs_client.getObject(bucket_name, object_key, downloadPath=download_path)
    
    with Image.open(download_path) as img:
        img.thumbnail((800, 800))
        img.save(upload_path, "WEBP", quality=80)
        
    target_key = object_key.replace("raw/", "thumbnail/").rsplit(".", 1)[0] + ".webp"
    obs_client.putFile(bucket_name, target_key, upload_path)
    
    return {"code": 200, "target": target_key}

两条关键避坑经验

  • 防范事件递归循环调用:OBS 触发器如果监听的是全桶,函数处理后回写新图片至同一存储桶极易陷入“生成图片 $\to$ 触发新事件 $\to$ 再次生成”的死循环。务必配置前缀过滤(如监听 raw/,写入 thumbnail/)。

  • 利用委托(Agency)鉴权:不要在代码中硬编码固定 AK/SK。为 FunctionGraph 绑定具备 OBS 操作权限的云服务委托,代码直接通过 context.getAccessKey() 动态取临时凭证,既安全又便于权限审计。

总结

切换到 Serverless 架构后,图片处理平均耗时控制在 300ms 以内,资源费用直接从包周期虚机的固定月租转为按请求毫秒计费,成本降低了 70% 以上。对于轻量、脉冲式的任务流,善用云原生组件串联能够显著提升交付效率与系统弹性。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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