在使用云函数进行项目开发的时候,当函数数量变多后,常常碰到的一个问题,就是对这些函数的依赖库的管理问题。因为云函数在建立或更新时,须要将函数的业务代码,和依赖库一同打包上传,所以在本地开发时,也常常是将依赖库和业务代码放置在一个文件夹下。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-lib
和 cmq-lib
经过命令行进入 requests-lib
文件夹后,执行命令
pip install requests -t
在此目录下完成 requests 库的下载安装。而在 cmq-lib 文件夹内,咱们经过下载或 clone https://github.com/tencentyun/cmq-python-sdk 项目,将 cmq 的 sdk 下载到本地。
接下来,使用这两个文件夹分别建立两个层,
一样命名为 requests-lib
和 cmq-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 开发和部署方式。在试用期内,相关联的产品及服务均提供免费资源和专业的技术支持,帮助您的业务快速、便捷地实现 Serverless!
3 秒你能作什么?喝一口水,看一封邮件,仍是 —— 部署一个完整的 Serverless 应用?
复制连接至 PC 浏览器访问:https://serverless.cloud.tencent.com/deploy/express
3 秒极速部署,当即体验史上最快的 Serverless HTTP 实战开发!
传送门:
- GitHub: github.com/serverless
- 官网:serverless.com
欢迎访问:Serverless 中文网,您能够在 最佳实践 里体验更多关于 Serverless 应用的开发!