阿里云函数计算部署广告数据ETL方案

一、可能用到的阿里云产品(最终版)

产品 用途 关键说明
函数计算 FC 无服务器计算服务,运行下载/上传 Python 代码 按调用次数+资源使用量计费,空闲时零成本
对象存储 OSS 存放下载的 CSV 文件,供上传函数读取 解决 FC 无状态导致的文件共享问题;内网传输免费
专有网络 VPC 打通函数与 RDS 的内网安全通道 避免数据库暴露在公网
云数据库 RDS 存储业务配置及 CSV 成果数据 与 FC 同地域,走内网访问
日志服务 SLS 记录函数执行日志,用于监控和排障 FC 自动投递,无需额外开发
访问控制 RAM 为函数授予访问 OSS、VPC 等资源的权限 通过角色授权,避免硬编码 AK
Serverless Devs 部署工具(YAML 配置) 一键部署,支持 CI/CD

二、总体架构与数据流

数据流说明

  1. 下载函数 从 ASP 获取 CSV 内容,不落本地磁盘,直接写入 OSS(以 item_id.csv 为键)。

  2. 上传函数 根据 item_id 从 OSS 读取对应的 CSV 内容,解析后存入 RDS。

  3. 两个函数完全解耦,通过 OSS 共享文件,解决了 FC 实例无状态、无法共享本地磁盘的问题。

三、程序改造核心:从本地文件系统到 OSS

3.1 原有逻辑(本地运行)

python

python 复制代码
# 下载
csv_path = os.path.join(SAVE_DIR, f"{item_id}.csv")
with open(csv_path, 'w') as f:
    f.write(csv_content)

# 上传
csv_path = os.path.join(SAVE_DIR, f"{item_id}.csv")
with open(csv_path, 'r') as f:
    data = f.read()
    save_to_db(data)

3.2 改造后(FC + OSS)

依赖安装oss2(阿里云 OSS SDK)

下载函数(保存到 OSS):

python

python 复制代码
def download_from_oss(bucket, item_id):
    key = f"csv_data/{item_id}.csv"
    obj = bucket.get_object(key)
    return obj.read().decode('utf-8')

def upload_handler(event, context):
    item_id = event['item_id']
    # 1. 从 OSS 读取 CSV 内容
    creds = context.credentials
    auth = Auth(creds.access_key_id, creds.access_key_secret)
    bucket = oss2.Bucket(auth, 'oss-cn-hangzhou-internal.aliyuncs.com', 'your-bucket-name')
    csv_content = download_from_oss(bucket, item_id)
    # 2. 解析并写入 RDS
    save_to_db(csv_content, item_id, context)
    # 3. (可选)删除 OSS 中的文件,避免冗余
    bucket.delete_object(f"csv_data/{item_id}.csv")
    return {"status": "imported", "item_id": item_id}

上传函数(从 OSS 读取):

python

python 复制代码
def download_from_oss(bucket, item_id):
    key = f"csv_data/{item_id}.csv"
    obj = bucket.get_object(key)
    return obj.read().decode('utf-8')

def upload_handler(event, context):
    item_id = event['item_id']
    # 1. 从 OSS 读取 CSV 内容
    creds = context.credentials
    auth = Auth(creds.access_key_id, creds.access_key_secret)
    bucket = oss2.Bucket(auth, 'oss-cn-hangzhou-internal.aliyuncs.com', 'your-bucket-name')
    csv_content = download_from_oss(bucket, item_id)
    # 2. 解析并写入 RDS
    save_to_db(csv_content, item_id, context)
    # 3. (可选)删除 OSS 中的文件,避免冗余
    bucket.delete_object(f"csv_data/{item_id}.csv")
    return {"status": "imported", "item_id": item_id}

关键变化

  • 不再依赖本地目录 SAVE_DIR

  • 文件读写全部通过 OSS SDK 完成。

  • 可通过 context.credentials 获取临时 AK,无需硬编码。


四、触发方式(怎么调起来)

触发方式 适用场景 配置示例
定时触发器 定期执行(如每小时下载,每日上传) Cron: 0 0 * * * *
HTTP 触发器 外部系统按需调用,携带 item_id POST 请求,Body 为 {"item_id": 123}

推荐:为下载和上传分别配置独立的定时触发器,可设置不同频率。例如:

  • 下载函数:每小时执行一次,拉取最新 CSV。

  • 上传函数:每小时执行一次(在下载后 5 分钟),处理新文件。


五、网络与权限配置

5.1 网络配置(VPC + OSS 内网)

资源 网络要求 说明
RDS 只允许 VPC 内网访问 在 RDS 控制台将网络类型设置为 VPC
FC 函数 配置 VPC(与 RDS 相同 VPC) 同时开启 公网访问(因需访问 ASP 和 OSS)
OSS 使用内网 endpoint 例如 oss-cn-hangzhou-internal.aliyuncs.com,走内网免费且更快

⚠️ FC 配置 VPC 后,默认会失去公网访问能力,需在服务配置中同时勾选 "允许函数访问公网"

5.2 权限配置(RAM 角色)

为 FC 服务创建角色,并附加以下权限策略:

json

复制代码
{
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ecs:CreateNetworkInterface",
        "ecs:DescribeNetworkInterfaces",
        "ecs:AttachNetworkInterface"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "oss:PutObject",
        "oss:GetObject",
        "oss:DeleteObject"
      ],
      "Resource": "acs:oss:*:*:your-bucket-name/*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "rds:DescribeDBInstances",
        "rds:Modify*"
      ],
      "Resource": "*"
    }
  ]
}

也可以直接使用系统策略:

  • AliyunECSNetworkInterfaceManagementAccess(VPC 访问)

  • AliyunOSSFullAccess(或自定义更细粒度的 OSS 权限)

  • AliyunRDSReadOnlyAccess / AliyunRDSFullAccess


六、部署步骤(使用 Serverless Devs)

6.1 项目结构

text

复制代码
fc-ad-project/
├── index.py                  # 统一入口,根据 event 调用下载或上传逻辑
├── download_module.py        # 下载业务逻辑(含 OSS 上传)
├── upload_module.py          # 上传业务逻辑(含 OSS 下载)
├── db_utils.py               # 数据库连接(使用 VPC 内网地址)
├── requirements.txt          # 依赖:oss2, pymysql, requests...
├── s.yaml                    # Serverless Devs 配置

6.2 关键配置 s.yaml

yaml

复制代码
edition: 1.0.0
name: fc-ad-project
access: "default"

services:
  ad-service:
    component: fc
    props:
      region: cn-hangzhou
      service:
        name: ad-data-service
        internetAccess: true                    # 访问公网(ASP 和 OSS)
        vpcConfig:                              # VPC 内网访问 RDS
          vpcId: vpc-xxxxx
          vSwitchIds: [vsw-xxxxx]
          securityGroupId: sg-xxxxx
        logConfig:                              # 日志服务
          project: fc-ad-log
          logstore: ad-logstore
        role: acs:ram::xxx:role/fc-role         # RAM 角色
        environmentVariables:
          OSS_BUCKET: your-bucket-name
          OSS_ENDPOINT: oss-cn-hangzhou-internal.aliyuncs.com
          DB_HOST: rm-xxxxx.mysql.rds.aliyuncs.com

      functions:
        download-func:
          name: download-func
          runtime: python3.9
          codeUri: ./
          handler: index.handler
          memorySize: 512
          timeout: 300
          events:
            - timerTrigger:
                name: hourly-download
                type: timer
                properties:
                  cronExpression: "0 0 * * * *"      # 每小时整点
                  payload: '{"action":"download"}'

        upload-func:
          name: upload-func
          runtime: python3.9
          codeUri: ./
          handler: index.handler
          memorySize: 512
          timeout: 300
          events:
            - timerTrigger:
                name: hourly-upload
                type: timer
                properties:
                  cronExpression: "0 5 * * * *"      # 每小时过5分
                  payload: '{"action":"upload"}'

6.3 统一入口 index.py 示例

python

python 复制代码
import json
import logging
from download_module import run_download
from upload_module import run_upload

def handler(event, context):
    logger = logging.getLogger()
    if isinstance(event, str):
        event = json.loads(event)
    action = event.get("action")
    item_id = event.get("item_id")  # 可从 event 中获取,也可从 DB 查询待处理列表
    if action == "download":
        return run_download(item_id, context)
    elif action == "upload":
        return run_upload(item_id, context)
    else:
        return {"error": "unknown action"}

注意 :如果每次需要处理多个 item_id,可以在函数内遍历查询 DB 获取所有待处理项,逐一处理。

6.4 部署命令

bash

复制代码
# 安装 Serverless Devs
npm install @serverless-devs/s -g

# 配置阿里云凭证
s config add

# 构建(在容器内安装 Linux 依赖)
s build --use-docker

# 部署
s deploy

七、迁移检查清单(从本地到 FC+OSS)

项目 本地模式 云上模式(FC + OSS) 改动点
文件存储 本地磁盘 SAVE_DIR OSS 对象存储 替换文件读写为 OSS SDK
文件共享 同一台机器多进程共享 跨实例、跨函数共享 通过 OSS 实现
调度方式 cron 或手动执行 定时触发器 / HTTP 触发器 移除 crontab,改用 FC 触发器
数据库访问 直连公网 IP VPC 内网地址 + 白名单 配置 VPC 和安全组
日志查看 本地文件 日志服务 SLS 无需代码改动,自动收集
密钥管理 配置文件或环境变量 RAM 角色 + context.credentials 删除硬编码 AK
部署方式 手动打包上传 Serverless Devs 一键部署 引入基础设施即代码(IaC)

八、成本与收益分析

8.1 成本

  • 函数计算:每月前 100 万次调用免费;资源使用量约 0.00011 元/GB-秒(极低)。

  • OSS:存储费用 0.12 元/GB/月;内网请求免费;少量 CSV 文件可忽略。

  • 日志服务:每月前 500 MB 免费。

  • VPC & RAM:免费。

预估:日均执行 100 次下载+上传,月成本 < 5 元。

8.2 收益

  • 零运维:无需管理服务器、无需关心磁盘空间。

  • 自动弹性:高并发时自动扩容,空闲时缩容到零。

  • 高可用:FC 多可用区容灾,OSS 数据 99.9999999% 持久性。

  • 安全合规:数据库不暴露公网,密钥不落地。


九、总结

通过引入 OSS 作为共享存储层,完美解决了 FC 无状态环境下的文件传递问题。改造后的方案:

  • 下载函数:ASP → OSS

  • 上传函数:OSS → RDS

两个函数可独立调度、独立扩缩容,架构清晰,成本极低。建议您按照本文档的步骤进行 POC 验证,再将生产流量逐步迁移。

相关推荐
阿里云大数据AI技术3 小时前
千亿级 AI 搜索的效能实战:从混合检索到 Agentic RAG 的三年实战
人工智能·elasticsearch·阿里云·agentic·ai 搜索
天草二十六_简村人4 小时前
对接AI大模型之nginx代理配置SSE接口
运维·网络·nginx·http·阿里云·ai·云计算
yyuuuzz5 小时前
独立站部署的几个常见技术问题
运维·服务器·网络·云计算·aws
China_Yanhy6 小时前
AWS RDS PostgreSQL 大版本升级故障复盘与 SRE 最佳实践指南
运维·云计算·aws
阿里-于怀7 小时前
Nacos Skill Registry: 面向个人场景的Skill中心实践
阿里云·云原生·nacos·agent·skills
HehuaTang7 小时前
IPOIB TCP ROCE IB 性能比较
网络·云计算
小小的木头人1 天前
Ubuntu 26.04 换阿里云镜像源
linux·ubuntu·阿里云
ZStack开发者社区1 天前
青海交科携手云轴科技ZStack为青海交控集团打造智慧物流大数据平台
大数据·服务器·科技·云计算·gpu算力
yyuuuzz1 天前
aws亚马逊云上部署常见问题梳理
运维·服务器·网络·数据库·云计算·aws