技术架构与核心原理
实现数字档案馆系统按量付费的核心在于抛弃传统的预留资源模式,转而使用Serverless架构。在这种架构下,存储费用根据文件实际占用的空间和时长计算,计算费用根据API调用的次数和CPU运行时间计费,带宽费用根据实际流量计费。本指南采用阿里云函数计算(FC)+ 对象存储(OSS)+ 表格存储(OTS)的组合,实现一套真正的“用多少付多少”的数字档案馆系统。
具体工作流如下:
- 对象存储(OSS):负责存储档案原文(PDF、OFD、图片等),支持低频访问和归档存储,降低长期保存成本。
- 函数计算(FC):负责处理上传、下载、元数据提取等业务逻辑,仅在请求发生时运行。
- 表格存储(OTS):存储档案元数据及计费日志,用于记录每一次操作的计量信息。
环境准备与工具安装
在开始编码前,必须配置好本地开发环境。本指南假设你使用Linux或macOS系统,Windows用户请使用Git Bash或WSL。
1. 安装Node.js环境
Serverless Devs工具依赖Node.js,请确保安装了v14.0.0及以上版本。执行以下命令验证:
```bash
node -v
```
2. 安装Serverless Devs工具
这是阿里云官方提供的Serverless应用管理工具,用于一键部署和配置。执行安装命令:
```bash
npm install -g @serverless-devs/s
```
安装完成后,配置阿里云AccessKey。请直接访问阿里云控制台“AccessKey管理”页面创建,不要使用具有Admin权限的Key,建议授予AliyunFCFullAccess和AliyunOSSFullAccess权限。
```bash
s config add
```
根据提示输入AccountID、AccessKeyID和AccessKeySecret,并选择默认地域(如cn-hangzhou)。
初始化项目骨架
使用Serverless Devs初始化一个基于HTTP触发的Python项目。我们将使用Python 3.9运行时。
```bash
s init start-fc-http-python3 -d digital-archive-system
cd digital-archive-system
```
项目初始化后,目录结构如下。我们需要重点关注`s.yaml`配置文件和`src`目录下的代码。
s.yaml:资源编排配置文件,定义函数、OSS、网络等。
src/app.py:核心业务逻辑代码。
开发档案上传与计费逻辑

进入src目录,修改app.py。我们需要实现接收前端上传的文件,将其存入OSS,并将元数据及本次操作的“计费权重”写入OTS。
修改requirements.txt,添加OSS和OTS SDK依赖:
```text
oss2
tablestore
```
以下是完整的app.py代码。这段代码实现了文件上传、OSS存储、元数据入库以及计费日志记录功能。
```python
import oss2
import tablestore as ots
import json
import uuid
import os
from datetime import datetime
环境变量由s.yaml配置注入
OSS_ENDPOINT = os.environ.get('OSS_ENDPOINT')
OSS_BUCKET_NAME = os.environ.get('OSS_BUCKET_NAME')
OTS_ENDPOINT = os.environ.get('OTS_ENDPOINT')
OTS_INSTANCE_NAME = os.environ.get('OTS_INSTANCE_NAME')
OTS_TABLE_NAME = 'archive_metadata'
OTS_LOG_TABLE = 'billing_log'
auth = oss2.Auth(os.environ.get('OSS_ACCESS_KEY_ID'), os.environ.get('OSS_ACCESS_KEY_SECRET'))
bucket = oss2.Bucket(auth, OSS_ENDPOINT, OSS_BUCKET_NAME)
ots_client = ots.OTSClient(
OTS_ENDPOINT,
os.environ.get('OSS_ACCESS_KEY_ID'),
os.environ.get('OSS_ACCESS_KEY_SECRET'),
OTS_INSTANCE_NAME
)
def handler(environ, start_response):
try:
简单的路由判断
path = environ.get('PATH_INFO')
if path == '/upload' and environ['REQUEST_METHOD'] == 'POST':
return handle_upload(environ, start_response)
else:
start_response('404 Not Found', [('Content-type', 'text/plain')])
return [b'Not Found']
except Exception as e:
start_response('500 Internal Server Error', [('Content-type', 'text/plain')])
return [str(e).encode('utf-8')]
def handle_upload(environ, start_response):
1. 解析Form数据获取文件
content_length = int(environ.get('CONTENT_LENGTH', 0))
body = environ['wsgi.input'].read(content_length)
这里简化处理,实际生产建议使用multipart库解析
假设前端直接上传文件流,文件名为file
file_key = f"archives/{uuid.uuid4()}.pdf"
2. 上传至OSS (标准存储)
按量付费点:OSS存储费、请求次数费
bucket.put_object(file_key, body)
file_size = len(body)
archive_id = str(uuid.uuid4())
3. 写入元数据到OTS
primary_key = [('archive_id', archive_id)]
attr_columns = [
('file_name', file_key),
('file_size', file_size),
('create_time', datetime.now().strftime('%Y-%m-%d %H:%M:%S')),
('status', 'active')
]
ots_client.put_row(OTS_TABLE_NAME, primary_key, attr_columns)
4. 记录计费日志
按量付费核心:记录本次操作消耗的资源量,用于后续出账
log_id = str(uuid.uuid4())
log_pk = [('log_id', log_id)]
log_attrs = [
('user_id', 'user_001'), 实际应从Token解析
('action', 'upload'),
('size_bytes', file_size),
('timestamp', int(datetime.now().timestamp()))
]
ots_client.put_row(OTS_LOG_TABLE, log_pk, log_attrs)
response = {
'code': 200,
'message': 'Upload success',
'data': {
'archive_id': archive_id,
'file_size': file_size,
'storage_cost_estimate': file_size 0.00012 示例单价
}
}
start_response('200 OK', [('Content-type', 'application/json')])
return [json.dumps(response).encode('utf-8')]
```
配置资源编排文件
打开项目根目录下的s.yaml,这是实现按量付费架构的关键配置。我们需要定义FC函数、OSS Bucket以及OTS表。请将以下内容完整覆盖原文件:
```yaml
edition: 3.0.0
name: digital-archive-app
access: default
services:
digital-archive-service:
component: fc
props:
region: cn-hangzhou
service:
name: digital-archive-service
description: Digital archive service with pay-as-you-go billing
internetAccess: true
function:
name: archive-api
description: Handle archive uploads and metadata
handler: app.handler
runtime: python3.9
timeout: 60
memorySize: 512 按量付费:内存大小 执行时间
codeUri: ./src
environmentVariables:
OSS_ENDPOINT: http://oss-cn-hangzhou-internal.aliyuncs.com
OSS_BUCKET_NAME: your-digital-archive-bucket 请替换为实际Bucket名
OSS_ACCESS_KEY_ID: ${env.OSS_ACCESS_KEY_ID} 从本地环境变量读取
OSS_ACCESS_KEY_SECRET: ${env.OSS_ACCESS_KEY_SECRET}
OTS_ENDPOINT: https://ots-cn-hangzhou.aliyuncs.com
OTS_INSTANCE_NAME: your-ots-instance 请替换为实际OTS实例名
triggers:
- name: httpTrigger
type: http
config:
authType: anonymous
methods:
- GET
- POST
- PUT
定义OSS资源
oss-bucket:
component: oss
props:
region: cn-hangzhou
bucket: your-digital-archive-bucket
acl: private
lifecycle:
- rules:
- id: archive-lifecycle-rule
prefix: archives/
status: Enabled
按量付费优化:30天后转低频访问,180天后转归档存储,大幅降低成本
transitions:
- Days: 30
StorageClass: InfrequentAccess
- Days: 180
StorageClass: Archive
定义表格存储资源
ots-table:
component: tablestore
props:
region: cn-hangzhou
instanceName: your-ots-instance
table:
- tableName: archive_metadata
primaryKey:
- name: archive_id
type: STRING
capacityUnit: 0 开启按量付费模式
- tableName: billing_log
primaryKey:
- name: log_id
type: STRING
capacityUnit: 0 开启按量付费模式
```
配置说明:
- memorySize:设置为512MB。计费公式为 GB-秒,调大此值会增加计算成本。
- capacityUnit: 0:在OTS配置中设置为0,表示开启按量付费模式。如果不设置为0,默认为预留模式,即使没有数据也会产生费用。
- lifecycle:这是数字档案馆省钱的关键。配置了生命周期规则,自动将冷数据沉降到更便宜的存储类型。
部署与验证
代码和配置准备就绪后,执行部署命令。Serverless Devs会自动创建OSS Bucket、OTS表并部署函数代码。
```bash
s deploy
```
终端输出日志显示“Deploy Success”后,会返回一个HTTP触发器的URL。复制该URL,假设为:https://xxx.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/digital-archive-service/archive-api/
使用curl命令模拟上传一个测试文件进行验证:
```bash
创建一个测试文件
echo "This is a test archive file content." > test.pdf
执行上传请求
curl -v -X POST -F "file=@test.pdf" https://xxx.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/digital-archive-service/archive-api/upload
```
如果返回JSON结果显示"Upload success",并且包含了archive_id,说明系统运行正常。
成本监控与账单查看
系统上线后,查看费用的具体步骤如下:
- 查看实时计量:登录阿里云控制台,进入“函数计算 -> 服务详情 -> 监控信息”,你可以看到调用的次数、执行时间(计费时长)和内存使用量。
- 查看存储用量:进入“对象存储 -> Bucket概览”,查看存储大小。由于配置了生命周期规则,你可以分别查看标准存储、低频访问和归档存储的量。
- 查看应用层账单:进入“表格存储 -> 实例详情 -> 数据管理”,查询
billing_log表。这里记录了每一次上传的文件大小和时间戳。你可以编写一个简单的脚本定期拉取此表数据,乘以设定的单价,生成给用户的对账单。
通过以上步骤,你已经构建了一个完全基于Serverless的数字档案馆系统。在该系统中,你不需要预先购买ECS实例或购买存储包。当没有人访问档案时,计算资源费用为0;当档案存储量增加时,OSS费用自动线性增加;当数据变老时,自动沉降到归档存储以节省90%以上的成本。这就是真正的按量付费落地实操。