更新时间:2023-06-01 GMT+08:00

依赖包管理

概述

函数代码一般包含公共库和业务逻辑两部分。对于公共库,您可以打包成依赖包单独管理,共享给多个函数使用,同时也减少了函数代码包部署、更新时的体积。

FunctionGraph也提供了一些公共依赖包,公共依赖包在平台内部缓存,消除了冷启动加载的影响,推荐您优先使用。

依赖包管理模块统一管理用户所有的依赖包,用户可以通过本地上传和obs地址的形式上传依赖包,并为依赖包命名。同时支持用户针对同一依赖包进行迭代更新,即同一依赖包可拥有多个版本,便于用户对依赖包进行系统化管理。

函数依赖包生成示例请参见如何制作函数依赖包。

  • 依赖包内文件名不能以~结尾。
  • 依赖包当前文件限制数为30000。
  • 如果函数配置了私有依赖包且依赖包很大的话,建议在函数详情页的“设置 > 常规设置”重新设置函数执行时间,在原基础上增加超时时间。

创建依赖包

  1. 登录FunctionGraph控制台,在左侧导航栏选择“函数 > 依赖包管理”,进入“依赖包管理”界面。
  2. 单击的“创建依赖包”,弹出“创建依赖包”对话框。
  3. 设置以下信息。

    表1 依赖包配置参数说明

    参数

    说明

    依赖包名称

    自定义的依赖包名称,用于识别不同的依赖包。

    代码上传方式

    分为上传ZIP文件和从OBS上传文件。

    • 上传ZIP文件:需单击“添加文件”,上传ZIP文件。
    • OBS链接URL:需填写“OBS链接URL”。

    运行时语言

    选择运行时语言。

    描述

    对于依赖包的描述信息,可以不填。

  4. 单击“确定”,完成依赖包的创建。默认首次创建的依赖包版本为“1”。
  5. 单击列表中的依赖包名称,进入版本历史界面,可以查看当前依赖包下的所有版本和版本相关信息。当前支持针对同一依赖包,进行不同版本的系统化管理。

    • 单击“创建版本”,填写相关信息,可以创建新的依赖包版本。
    • 单击具体的版本号,可以查看版本地址。
    • 单击版本号所在行的删除,可以删除该版本。

配置函数依赖

  1. 登录FunctionGraph控制台,在左侧导航栏选择“函数 > 函数列表”,进入函数列表界面。
  2. 单击函数名称,进入函数详情界面。
  3. 在“代码”页签,单击“代码依赖包”所在行的“添加依赖包”,弹出“选择依赖包”对话框。
  4. 选择依赖包,单击“确定”。

    表2 依赖包配置说明

    参数

    说明

    运行时语言

    默认展示当前函数的运行时语言,无法修改。

    依赖包源

    根据实际业务,选择“公共依赖包”或“私有依赖包”。

    依赖包名称

    选择当前运行时语言下的依赖包。

    版本

    选择当前依赖包的具体版本。

    • 一个函数最多可添加20个依赖包。
    • 除了您自行创建的依赖包(私有依赖包)以外,FunctionGraph还提供了一些常见的公共依赖包,您可以直接选择使用。

删除依赖包

依赖包当前无法在界面直接删除,若需删除,请删除依赖包下的所有版本。当所有版本全部删除完成后,依赖包会自动删除。

  1. 登录FunctionGraph控制台,在左侧导航栏选择“函数 > 依赖包管理”,进入“依赖包管理”界面。
  2. 单击依赖包名称,进入版本历史管理界面。
  3. 单击版本号所在行的删除可以删除该版本,存在多个版本请重复此操作。

    图1 删除依赖包版本

    如果函数正在使用此依赖包,则无法删除。

引入依赖库

支持的依赖库说明

FunctionGraph支持引入标准库及第三方依赖库。

  • 标准库

    对于标准库,无论是在线编辑或是线下开发打包上传至FunctionGraph,均可以直接在代码中引入,使用其功能。

  • FunctionGraph支持的非标准库

    FunctionGraph内置一些三方件,如表3表4所示。像标准库一样,在编写代码时直接引入,使用其功能。

    表3 Node.js Runtime集成的三方件

    名称

    功能

    版本号

    q

    异步方法封装

    1.5.1

    co

    异步流程控制

    4.6.0

    lodash

    常用工具方法库

    4.17.10

    esdk-obs-nodejs

    OBS sdk

    2.1.5

    express

    极简web开发框架

    4.16.4

    fgs-express

    在FunctionGraph和API Gateway之上使用现有的Node.js应用程序框架运行无服务器应用程序和REST API 。提供的示例允许您使用Express框架轻松构建无服务器Web应用程序/服务和RESTful API 。

    1.0.1

    request

    简化http调用,支持HTTPS并默认遵循重定向

    2.88.0

    表4 Python Runtime支持的非标准库

    模块

    功能

    版本号

    dateutil

    日期/时间处理

    2.6.0

    requests

    http库

    2.7.0

    httplib2

    httpclient

    0.10.3

    numpy

    数学计算

    1.13.1

    redis

    redis客户端

    2.10.5

    obsclient

    OBS客户端

    -

    smnsdk

    访问云smn服务

    1.0.1

  • 其他第三方库(除了上面表格列举的非标准三方库,FunctionGraph没有内置别的非标准三方库)

    将依赖的第三方库打包,上传至OBS桶或在函数界面上传,具体请参见创建依赖包,在函数代码中即可使用其功能。

引入依赖库示例

处理图片的函数代码如下。

# -*- coding: utf-8 -*-
from PIL import Image, ImageEnhance

from com.obs.client.obs_client import ObsClient

import sys
import os

current_file_path = os.path.dirname(os.path.realpath(__file__))
# append current path to search paths, so that we can import some third party libraries.
sys.path.append(current_file_path)
region = 'your region'
obs_server = 'obs.xxxxxxcloud.com'
def newObsClient(context):
    ak = context.getAccessKey()
    sk = context.getSecretKey()
    return ObsClient(access_key_id=ak, secret_access_key=sk, server=obs_server,
                     path_style=True, region=region, ssl_verify=False, max_retry_count=5, timeout=20)
def downloadFile(obsClient, bucket, objName, localFile):
    resp = obsClient.getObject(bucket, objName, localFile)
    if resp.status < 300:
        print 'download file', file, 'succeed'
    else:
        print('download failed, errorCode: %s, errorMessage: %s, requestId: %s' % resp.errorCode, resp.errorMessage,
              resp.requestId)
def uploadFileToObs(client, bucket, objName, file):
    resp = client.putFile(bucket, objName, file)
    if resp.status < 300:
        print 'upload file', file, 'succeed'
    else:
        print('upload failed, errorCode: %s, errorMessage: %s, requestId: %s' % resp.errorCode, resp.errorMessage,
              resp.requestId)
def getObjInfoFromObsEvent(event):
    s3 = event['Records'][0]['s3']
    eventName = event['Records'][0]['eventName']
    bucket = s3['bucket']['name']
    objName = s3['object']['key']
    print "*** obsEventName: %s, srcBucketName: %s, objName: %s", eventName, bucket, objName
    return bucket, objName
def set_opacity(im, opacity):
    """设置透明度"""
    if im.mode != "RGBA":
        im = im.convert('RGBA')
    else:
        im = im.copy()
    alpha = im.split()[3]
    alpha = ImageEnhance.Brightness(alpha).enhance(opacity)
    im.putalpha(alpha)
    return im
def watermark(im, mark, opacity=0.6):
    """添加水印"""
    try:
        if opacity < 1:
            mark = set_opacity(mark, opacity)
        if im.mode != 'RGBA':
            im = im.convert('RGBA')
        if im.size[0] < mark.size[0] or im.size[1] < mark.size[1]:
            print "The mark image size is larger size than original image file."
            return False
        x = (im.size[0] - mark.size[0]) / 2
        y = (im.size[1] - mark.size[1]) / 2
        layer = Image.new('RGBA', im.size, )
        layer.paste(mark, (x, y))
        return Image.composite(layer, im, layer)
    except Exception as e:
        print ">>>>>>>>>>> WaterMark EXCEPTION:  " + str(e)
        return False
def watermark_image(localFile, fileName):
    im = Image.open(localFile)
    watermark_image_path = os.path.join(current_file_path, "watermark.png")
    mark = Image.open(watermark_image_path)
    out = watermark(im, mark)
    print "**********finish water mark"
    name = fileName.split('.')
    outFileName = name[0] + '-watermark.' + name[1]
    outFilePath = "/tmp/" + outFileName
    if out:
        out = out.convert('RGB')
        out.save(outFilePath)
    else:
        print "Sorry, Save watermarked file Failed."
    return outFileName, outFilePath
def handler(event, context):
    srcBucket, srcObjName = getObjInfoFromObsEvent(event)
    outputBucket = context.getUserData('obs_output_bucket')
    client = newObsClient(context)
    # download file uploaded by user from obs
    localFile = "/tmp/" + srcObjName
    downloadFile(client, srcBucket, srcObjName, localFile)
    outFileName, outFile = watermark_image(localFile, srcObjName)
    # 将转换后的文件上传到新的obs桶中
    uploadFileToObs(client, outputBucket, outFileName, outFile)
    return 'OK'

对于标准库和FunctionGraph支持的非标准库,可以直接引入。

对于FunctionGraph暂没有内置的非标准三方库,通过以下步骤引入。

  1. 将依赖的库文件压缩成ZIP包,上传至OBS存储桶,获得依赖包的OBS存储链接。
  2. 登录FunctionGraph控制台,在左侧导航栏选择“函数 > 依赖包管理”,进入“依赖包管理”界面。
  3. 选择“创建依赖包”,弹出“创建依赖包”对话框。
  4. 输入依赖包名称、运行时语言和OBS存储链接,单击“确定”。
    图2 设置依赖包
  5. 进入函数详情页面,在“代码”页签,单击“依赖代码包”所在行的“添加依赖包”,选择4中创建的依赖包,单击“确定”。
    图3 添加依赖包

    各个依赖包和代码包之间尽量不要有相同的目录或文件,比如依赖包depends.zip,里面有index.py这个文件,如果代码采用在线编辑方式,函数执行入口为index.handler,这样在函数执行的时候会产生一个代码文件index.py,跟依赖包里面的index.py文件同名,两个文件可能会因覆盖合并而出错。