雲函數 SCF 中如何使用 Layer 實現輕鬆部署?

在使用雲函數進行項目開發的時候,當函數數量變多後,常常碰到的一個問題,就是對這些函數的依賴庫的管理問題。因爲雲函數在建立或更新時,須要將函數的業務代碼,和依賴庫一同打包上傳,所以在本地開發時,也常常是將依賴庫和業務代碼放置在一個文件夾下。html

在這種狀況下,每一個雲函數的代碼目錄下均有一套依賴庫代碼,而這其中有不少在若干個函數中都是重複的,不但佔用了大量的空間,並且管理麻煩,在某些依賴庫須要進行升級時,要進入到每一個函數項目中去檢查依賴關係和升級操做。而另外一方面,這些依賴庫一般不會有大的變更,可是卻須要在每次函數進行更新時,都要和業務代碼一同打包上傳,致使實際的代碼更新可能就一兩行,可是須要生成一個十幾兆甚至幾十兆的包去上傳,在網絡環境很差的狀況下還須要忍受緩慢的上傳速度。python

騰訊雲的 SCF 雲函數近期推出的層功能,就是爲了這類不常常變更的依賴庫或靜態文件而準備的產品功能。經過使用層功能來存儲及管理依賴庫,並在使用時按需與函數進行綁定,就能夠實現依賴庫的多函數共享,僅需上傳一份,就能夠在多個要使用到的函數中綁定並引用;經過與雲函數綁定的使用方式,也就意味着不須要在雲函數的業務代碼中再附上相應的依賴庫了,能夠將業務代碼和依賴庫分開進行管理和部署,下降雲函數每次上傳時須要提交的包大小,加快上傳更新的速度。git

在實際案例介紹前,先介紹一下層的功能點。github

層做爲一個和雲函數獨立的資源,有獨立的建立、管理流程。和函數建立相似,能夠經過上傳 zip 包,或者控制檯上選擇文件夾,或者將 zip 包提早上傳 cos 後再引用的方式,來將文件內容提交到雲上,並建立好層。每個提交到層中的文件包,都將生成一個新的版本。express

所以,在建立好一個層之後,就將具備了第一個版本;然後續若是依賴庫或文件內容有升級,能夠繼續更新層,並生成新的版本,版本號依次增大。在建立層,或發佈新版本的時候,還能夠指定當前層所可支持的 runtime,這樣相應 runtime 的函數,才能夠瀏覽或綁定當前層。json

在使用層時,經過雲函數與具體層的具體版本綁定,來實現層內容的引入和使用。在函數的配置管理界面,新增長了層的綁定配置界面。經過選擇層及指望綁定的版本,就能夠完成綁定操做。綁定了層之後,在函數運行時,運行環境中的 /opt 目錄下就會有層的內容。固然,系統中的 NODE_PATH,PYTHONPATH 已經指定好了 /opt 目錄,綁定好的層中若是包含有依賴庫,在函數代碼中能夠直接經過 import,require 等方法直接引用,與常規寫法一致,不須要額外進行路徑的指定。同時,目前一個函數支持最多綁定 5 個層的版本,所以能夠經過這種方法,將所需的依賴庫分別引入到層中。api

在多個層綁定到同一個函數時,層之間有必定的順序關係。層是按照順序關係依次加載的,若是在相同路徑下有同名文件,會產生後加載的文件覆蓋先加載文件的問題,須要在此處注意多個層綁定時是否會有內容覆蓋,以及加載循序是不是按自身的控制須要來的。另外一方面,層與函數的綁定關係,也做爲函數的配置保存。$LATEST版本的函數能夠按需修改調整綁定配置,而一旦發佈版本後,生成的函數版本中的配置就固定了,沒法再次修改。所以,經過發佈版原本固化已經開發完成的版本,能夠避免函數代碼或層內容的修改致使的代碼不可用。瀏覽器

接下來,咱們就將經過一個使用案例來介紹層功能的使用。網絡

在這個案例中,咱們將實現一個撥測網站,並在檢測到異常時發送消息到 cmq 消息隊列中的雲函數。這個雲函數由 python 寫成,將使用兩個依賴庫,requests 庫用來實現 url 地址的 http 訪問檢測,及 cmq 庫用來實現向 cmq 的隊列發送消息。架構

在建立函數前,我將使用這兩個庫分別建立兩個層,並在後續將函數與這兩個層綁定來使用依賴庫。

首先在本地分別建立兩個文件夾: requests-libcmq-lib
經過命令行進入 requests-lib 文件夾後,執行命令

pip install requests -t

在此目錄下完成 requests 庫的下載安裝。而在 cmq-lib 文件夾內,咱們經過下載或 clone https://github.com/tencentyun/cmq-python-sdk 項目,將 cmq 的 sdk 下載到本地。

接下來,使用這兩個文件夾分別建立兩個層,
一樣命名爲 requests-libcmq-lib
經過直接選擇文件夾建立,並選擇好適配 runtime 爲 python2
在建立完成兩個層後,他們都具備版本 1可供函數綁定。

同時,我在相同地域下也建立好了名字爲 testq 的 cmq 隊列,並根據 sdk 須要準備好了帳號 id,secret id,secret key 等信息。

接下來,我將使用以下代碼建立函數 detect-sendmsg,實現 url 的撥測,並向 cmq 消息隊列中發送消息。代碼中的 appid、secretid、secretkey,須要替換爲自身帳號下的相關內容。

# -*- coding: utf8 -*-
import json
import logging
import os

from cmq.account import Account
from cmq.cmq_exception import *
from cmq.topic import *
import requests

logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

print('Loading function')

appid = 1252724xxx #please change to your appid. Find it in Account Info
secretId = 'AKIDkkxxxxxxxxxxxxxxx' #please change to your API secret id. Find it in API secret key pair
secretKey = ‘xxxxxxxxxxxxxxxxxx' #please change to your API secret key. Find it in API secret key pair
region = u'gz'
endpoint = 'https://cmq-queue-gz.api.qcloud.com'

my_account = Account(endpoint, secretId, secretKey)
my_account.set_log_level(logging.INFO)
queue_name = 'testq'
my_queue = my_account.get_queue(queue_name)

test_url_list = [
    "http://www.baidu.com",
    "http://www.qq.com",
    "http://cloud.tencent.com",
    "http://unkownurl.com"
]


def test_url(url_list):
    errorinfo = []
    for url in url_list:
        resp = None
        try:
            resp = requests.get(url,timeout=3)
        except (requests.exceptions.Timeout, requests.exceptions.ConnectionError, requests.exceptions.ConnectTimeout) as e:
            logger.warn("request exceptions:"+str(e))
            errorinfo.append("Access "+ url + " timeout")
        else:
            if resp.status_code >= 400:
                logger.warn("response status code fail:"+str(resp.status_code))
                errorinfo.append("Access "+ url + " fail, status code:" + str(resp.status_code))
    if len(errorinfo) != 0:
        send_msg("撥測異常通知:"+"\r\n".join(errorinfo))

def send_msg(msg_body):
    try:
        logger.info("send msg"+msg_body)
        msg = Message(msg_body)
        ret_msg = my_queue.send_message(msg)
    except CMQExceptionBase as e:
        logger.warn("Send msg to queue Fail! Exception:%s\n" % e)
        raise e

def main_handler(event, context):
    test_url(test_url_list)
    return 「finish"

使用此代碼建立好函數,並在函數的層管理中,分別綁定好 requests-lib、cmq-lib 兩個層。因爲這兩個層沒有重複部分,所以能夠以任意順序綁定。

完成綁定後,能夠直接經過控制檯觸發函數,查看運行狀況。一切正常的狀況下,能夠看到撥測的過程,以及消息發送到消息隊列中的記錄。同時,也能夠到消息隊列的對應 queue 中,經過獲取消息,獲取到發送到其中的消息記錄。

從這個例子中能夠看到,函數代碼中應用了 requests 庫,和 cmq 的 sdk,但並未經過和函數一同打包上傳來實現,而是將依賴庫放置到層裏面後,經過綁定關係來引用。經過這種方式,若是下次咱們啓動一個新的函數也須要使用到 requests 庫,直接與已有的層綁定便可使用,而一樣不須要再次打包上傳。而函數代碼僅一個文件,不須要帶有較大的依賴庫,也能夠下降每次更新上傳時的包大小,甚至直接快速的使用 WebIDE 來進行編輯就行。

層的功能爲依賴庫和不常常修改的靜態文件提供了新的存儲方案,與函數的剝離使得這類文件可以多函數複用,版本化管理;隨着層功能的發展,騰訊雲 Serverless team 也將進一步拓展層功能的使用,包括了在開發工具中實現自動化的層建立和綁定、層的共享、提供公共層供用戶直接複用等,都已經在 roadmap 中,將在接下來的發展中逐步落地,供雲函數的開發體驗更加便利。

Tencent Serverless Hours 線上分享會第一期回放觀看請戳:https://cloud.tencent.com/edu/learning/live-2437

Serverless Framework 30 天試用計劃

咱們誠邀您來體驗最便捷的 Serverless 開發和部署方式。在試用期內,相關聯的產品及服務均提供免費資源和專業的技術支持,幫助您的業務快速、便捷地實現 Serverless!

詳情可查閱:Serverless Framework 試用計劃

One More Thing

3 秒你能作什麼?喝一口水,看一封郵件,仍是 —— 部署一個完整的 Serverless 應用?

複製連接至 PC 瀏覽器訪問:https://serverless.cloud.tencent.com/deploy/express

3 秒極速部署,當即體驗史上最快的 Serverless HTTP 實戰開發!

傳送門:

歡迎訪問:Serverless 中文網,您能夠在 最佳實踐 裏體驗更多關於 Serverless 應用的開發!


推薦閱讀:《Serverless 架構:從原理、設計到項目實戰》

相關文章
相關標籤/搜索