函数计算(FC) 使用总结 详情可看官方文档
是什么函数计算
函数计算是事件驱动的全托管计算服务。使用函数计算,您无需采购与管理服务器等基础设施,只需编写并上传代码。
函数计算为您准备好计算资源,弹性地、可靠地运行任务,并提供日志查询、性能监控和报警等功能。
工作流程
使用前提
1、开发介绍以 Python 为例
1、下载 Python SDK
注:环境依赖 Python 2.7, Python 3.6
$ pip install aliyun-fc2
2、函数计算SDK开发 Demo
import fc2
import zipfile
import os
from business.api.utils import file_utils
import json
service_name = 'oss_test'
function_name = 'upload_oss'
source_arn = 'acs:oss:cn-shenzhen:<Your accountID>:ivenn-oss'
invocation_role = 'acs:ram::<Your accountID>:role/oss-allaccess'
fc_endpoint = '<Your Endpoint>'
accessKey_ID = 'xxx'
accessKey_Secret = 'xxx'
def Serialize_data(data, filename):
import pickle
filename = 'files/' + filename
with open(filename, 'wb') as f:
pickle.dump(data, f)
return filename
# 创建服务
def create_service(fc_endpoint, service_name, invocation_role):
client = fc2.Client(
endpoint=fc_endpoint,
accessKeyID=accessKey_ID,
accessKeySecret=accessKey_Secret)
# Create service.
client.create_service(service_name, role=invocation_role)
# 创建函数
# handler 表示函数的处理函数,及函数入口,格式为 (py文件名.方法名) 例:'mapCal.handler' 表示 mapCal.py 文件里的handler 方法作为入口
def create_function(service_name, function_name, handler_, files: list, zip_fp, runtime='python3'):
client = fc2.Client(
endpoint=fc_endpoint,
accessKeyID=accessKey_ID,
accessKeySecret=accessKey_Secret)
# 采用SDK 上传函数前,需要将函数压缩打包成zip
FilesToZip(files, zip_fp)
# 输入对应的服务名 service_name、函数名 function_name 以及压缩包的路径
client.create_function(service_name, function_name, runtime, handler_, codeZipFile=zip_fp)
# 创建函数触发器,前提是已经创建好函数
def create_trigger(fc_endpoint, accessKey_ID, accessKey_secret, service_name, function_name, trigger_name,
oss_source_arn, invocation_role, description=''):
import fc2
client = fc2.Client(
endpoint=fc_endpoint,
accessKeyID=accessKey_ID,
accessKeySecret=accessKey_secret)
# Create oss trigger
oss_trigger_config = {
'events': ['oss:ObjectCreated:*'],
'filter': {
'key': {
'prefix': 'prefix',
'suffix': 'suffix'
}
}
}
triggerType = 'oss' # 表示oss的触发器
client.create_trigger(service_name, function_name, trigger_name, description,
triggerType, oss_trigger_config, oss_source_arn, invocation_role)
def invoke_function(service_name, function_name):
client = fc2.Client(
endpoint=fc_endpoint,
accessKeyID=accessKey_ID,
accessKeySecret=accessKey_Secret)
# payload: (optional, bytes or seekable file-like object): the input of the function.
fcHttpResponse = client.invoke_function(service_name, function_name,
payload=bytes(json.dumps({"key": "123"}), encoding='utf-8'))
# 返回的格式为json ,转成json 对象便于后续处理
result = json.loads(fcHttpResponse.data)
# fcHttpResponse.data = b'{\n "key": "ivenn"\n}'
# fcHttpResponse.headers = {'Access-Control-Expose-Headers': 'Date,x-fc-request-id,x-fc-error-type
# ,x-fc-code-checksum,x-fc-invocation-duration,x-fc-max-memory-usage,x-fc-log-result,x-fc-invocation-code-version',
# 'Content-Length': '22','Content-Type': 'application/octet-stream', 'X-Fc-Code-Checksum': '11275691039047628071',
# 'X-Fc-Invocation-Duration': '2', 'X-Fc-Invocation-Service-Version': 'LATEST', 'X-Fc-Max-Memory-Usage': '10.73',
# 'X-Fc-Request-Id': 'f5e2b744-f014-47c7-8bad-2074f78ac132', 'Date': 'Thu, 10 Sep 2020 06:42:04 GMT'}
# 压缩py 文件的方法
def FilesToZip(fps, zip_fp, delete=False):
''' 多文件打包成zip
:param fps: [r'C:\1.txt', r'C:\2.txt', r'C:\3.txt'] 文件全路径的list
:param zip_fp: r'C:\files.zip'
:param delete: True 删除原文件
:return:
'''
if len(fps) == 0:
return None
# if not os.path.exists(zip_fp):
# file = open(zip_fp, 'w')
if not zip_fp.endswith("zip"):
return None
zipf = zipfile.ZipFile(zip_fp, "x") # 在路径中创建一个zip对象
for fp in fps:
fn = os.path.basename(fp)
zipf.write(os.path.join(file_utils.get_project_base_directory(),
fp), fn) # 第一个参数为该文件的全路径;第二个参数为文件在zip中的相对路径
zipf.close() # 关闭文件
if delete: # 删除原文件
for fp in fps:
os.remove(fp)
return zip_fp
3、本地开发 (使用Funcraft工具)
前提
- 开通函数计算服务
- 安装命令行工具 Funcraft 安装教程
本地调式还需了解 template.yml 文件的语法,例子:
ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
maptest:
Type: 'Aliyun::Serverless::Service'
Properties:
Description: 'helloworld'
oss_test:
Type: 'Aliyun::Serverless::Function'
Properties:
Handler: oss_json_test.handler # 函数入口 格式为: py文件名.函数名
Runtime: python3
CodeUri: './' # 指定要 deploy的函数的文件目录
Events:
oss-trigger-name:
Type: OSS # trigger type
Properties:
BucketName: ivenn-oss # oss bucket name
Events: # 允许相关操作的配置
- oss:ObjectCreated:*
- oss:ObjectRemoved:DeleteObject
4、入口函数的编写 (重点内容)
函数计算,要求提前编写逻辑处理的代码在一个python 文件中,并且指定其中一个函数为入口函数
Demo_1 如下:
# -*- coding: utf-8 -*-
import json
import oss2
def handler(event, context):
# 将bytes 转为json 对象
evt = json.loads(event)
result = None
if evt['oss_address'] is not None:
oss_address = evt['oss_address']
AccessKey_ID = '<Your AccessKey_ID>'
AccessKey_Secret = '<Your AccessKey_Secret>'
# 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
bucketName = 'ivenn-oss'
endPoint = 'http://oss-cn-shenzhen.aliyuncs.com'
auth = oss2.Auth(AccessKey_ID, AccessKey_Secret)
# Endpoint以深圳为例,其它Region请按实际情况填写。
bucket = oss2.Bucket(auth, endPoint, bucketName)
result = bucket.select_object(oss_address, 'select s.firstName, s.lastName from ossobject s', select_params = {"Json_Type":"DOCUMENT"})
json_result = {"result":json.loads(result.read())}
print(json_result)
return json_result
事件 event 参数
event 参数是用户调用函数时传入的数据,在 Python2.7 中是 str 类型,在 Python3 中是 bytes 类型,是函数的输入参数。
函数不对 event 参数的内容进行任何解释,您在函数中可以根据实际情况对 event 进行转换。例如输入数据是一个 JSON 字符串,您可以把它转换成一个字典 。
# 传入json 对象
{
"key": "value"
}
Demo_2 如下:
# -*- coding: utf-8 -*-
import logging
import json, oss2
import pickle
import os
# 处理 oss中 20200908文件夹下的文件序列化后保存
def handler(event, context):
evt = json.loads(event)
logger = logging.getLogger()
logger.info('input: %s ', evt)
AccessKey_ID = evt['AccessKey_ID']
AccessKey_Secret = evt['AccessKey_Secret']
endPoint = evt['endPoint']
bucketName = evt['bucketName']
auth = oss2.Auth(AccessKey_ID, AccessKey_Secret)
# Endpoint以深圳为例,其它Region请按实际情况填写。
bucket = oss2.Bucket(auth, endPoint, bucketName)
file_list = bucket.list_objects(prefix='20200908').object_list
for file in file_list:
# 获取返回的列表的文件名字
file_name = file.key
data_file = bucket.get_object(file_name).read()
result = pickle.loads(data_file)
dump_data = pickle.dumps(result)
bucket.put_object('20200908/oss_cal_result-1.txt', dump_data)
return 'success'
# 除入口函数,还可以声明其他方法
def serialize_data(data, filename):
filename = 'files/' + filename
with open(filename, 'wb') as f:
pickle.dump(data, f)
return filename