【知识点】如何快速开发、部署 Serverless 应用?
点击上方蓝字关注我们,免费解锁新书内容
本文将详细介绍如何开发和部署 Serverless 应用,并通过阿里云函数计算控制台与开发者工具 Serverless Devs 进行应用的初始化、部署;最后分享应用的调试,通过科学发布、可观测性等介绍应用的部署和运维总结,进而实现从应用初始化到调试、发布、运维基础流程、核心步骤的探索。
01
Serverless应用开发部署
通过控制台进行函数创建
阿里云函数计算产品首页
选择左侧的“服务及函数”,并进行服务的创建,如图所示:
阿里云函数计算创建服务页面
阿里云函数计算创建函数页面
相关联的函数可以放在一个服务下进行分类,这种分类实际上比标签分类更直观明了。 相关联的函数在同一个服务下共享一定的配置,例如 VPC 配置、NAS 配置,甚至某些日志仓库的配置等。 通过服务,我们可以很好地做函数环境的划分,例如对于一个相册项目,该项目可能存在线上环境、测试环境、开发环境,那么可以在服务层面做区分,即可以设定 album-release、album-test、album-dev 三个服务,进而做环境的隔离。 通过服务,我们可以很好地收纳函数。如果项目比较大,可能会产生很多函数,统一放在同一层级会显得非常混乱,这时就可以通过服务进行有效的收纳。
通过工具进行函数创建与部署
通过 Serverless 开发者工具入门 Serverless 应用开发、部署、运维是非常方便的,下面我们以 Serverless Devs 为例介绍阿里云函数计算应用的部署,并对工具侧的函数创建、部署以及其他相关功能进行探索。
Serverless Devs 是一个开源的 Serverless 开发者平台,致力于为开发者提供强大的工具链。通过该平台,开发者可以一键体验多云 Serverless 产品,极速部署 Serverless 项目。按照官方目前的描述,Serverless Devs 已经支持包括 AWS Lanbda、阿里云函数计算、百度智能云函数计算、腾讯云云函数、华为云函数工作流等在内的多个云厂商的 Serverless 相关产品。
我们通过 Serverless Devs 开发者工具,以阿里云函数计算为例进行实践,探索如何创建、部署 Serverless 应用:
1)安装 Serverless Devs 开发者工具(执行npm install -g @Serverless-devs/s命令)。
2)设置阿里云凭证信息(执行s config add --AccessKeyID AccessKeyID --AccessKeySecret AccessKeySecret --AccountID AccountID命令)。
3)建立模板项目(执行s init node.js12-http -d fc-hello-world-demo命令),初始化过程如图所示:
通过 Serverless Devs 创建项目图
通过 Serverless Devs 部署项目
02
如何调试Serverless应用
在应用开发过程中,或者应用开发完成后,当执行结果不符合预期时,通常要进行一定的调试。
但是在 Serverless 架构下,调试往往会受到极大的考验,尤其在受环境因素限制时,通常会出现这样的情况:所开发的应用在本地可以健康、符合预期地运行,但是在 FaaS 平台上则有一些不可预测的问题;或者在一些特殊环境下,本地没有办法模拟线上环境,难以进行应用的调试。
虽然 Serverless 应用的调试一直备受诟病,但是各个云厂商并没有因此放弃在调试方向上的深入探索,下面我们介绍几种方式。
在线调试
简单调试
所谓的简单调试,就是在控制台进行调试。以阿里云函数计算为例,可以在控制台通过“代码执行”按钮进行基本的调试,如下图所示:
函数计算代码编辑页面
必要的时候也可以通过设置 Event 来模拟一些事件。
阿里云函数计算事件页面
在线调试的好处是可以使用一些线上环境进行代码的测试。当线上环境拥有 VPC 等资源时,在本地环境是很难进行调试的。
断点调试
除了简单的在线调试之外,部分云厂商还支持断点调试,例如阿里云函数计算的远程调试。我们以阿里云函数计算远程调试为例,可以实现通过控制台进行函数的在线调试。当创建好函数之后,可以选择远程调试,并单击“开启调试”按钮:
函数计算远程调试页面
开启调试之后,稍等片刻,系统将会进入远程调试界面:
函数计算远程调试开始页面当出现图
当出现下图所示界面,我们可以进行断点调试。
函数计算远程调试断点调试页面
端云联调
在本地进行 Serverless 应用开发时,往往会涉及一些线上资源,例如通过对象存储触发器触发函数执行,通过 VPC 访问数据库等,此时线上和线下环境不一致会让线下开发、调试面临极大的挑战。
Serverless Devs 开发者工具通过搭建 Proxy 辅助函数的方法将线上和线下资源打通,可以快速帮助开发者在本地进行应用的开发与调试,这种调试方式称为端云联调。
如下图所示, Serverless Devs 开发者工具会根据 Yaml 配置文件,创建辅助服务和辅助函数,并通过辅助服务和辅助函数实现线上和线下资源打通,以及完整的端云联调。
Serverless Devs 端云联调原理示意图
Serverless Devs 开发者工具会根据 Yaml 配置文件的内容,创建辅助服务和辅助函数(辅助服务和 Yaml 中所声明的业务服务配置是一致的)。
通过触发器(包括通过 SDK、API、s proxied invoke 命令,或者其他触发器)触发辅助函数(函数计算 C),请求流量回到本地调试实例(本地环境 A),这时本地调试实例(本地函数执行环境容器)收到的 event 和 context 是真实来自线上的。
本地调试实例(本地环境 A)可以直接访问以下内容:
VPC 内网资源,比如 RDS、Kafka 内网地址等; 一些云服务的内网地址; 硬盘挂载服务(直接访问 NAS)。
端云联调流程如下:
1)执行 s proxied setup 命令准备端云联调所需的辅助资源以及本地环境;
2)对于无触发器的普通事件函数或者 HTTP 触发器,准备工作完成后,启动另一个新的终端,切换到该项目路径下,执行 s proxied invoke 命令调用本地函数;
3)完成调试任务后,执行 s proxied cleanup 命令清理端云联调所需的辅助资源以及本地环境。
除了通过命令使用端云联调功能外,我们也可以在 VSCode 开发者工具中使用端云联调功能,如图所示:
在 VSCode 中使用端云联调功能
远程调试
端云联调在本地除了有一个通道服务容器外,还有一个函数计算容器,用来执行本地函数;远程辅助函数只是单纯将远程流量发送到本地。在实际调试过程中,需要登录到实例进行项目调试,此时可以选择使用远程调试。
相比于端云联调,远程调试在本地只有一个通道服务容器,执行过程全部依赖线上;远程函数将执行结果返回。远程调试整体架构简图如图所示。
除了通过上面远程调试架构简图所示的通道服务登录线上环境进行代码调试或问题定位之外,部分云厂商还提供了直接登录实例进行代码调试的功能。以 Serverless Devs 为例,当使用阿里云函数计算时,我们就可以直接通过 instance 命令进行线上实例登录。
尽管实例登录命令已经提供了便捷的登录体验,能帮助用户解决复杂场景下的应用异常定位等问题,但是登录实例后,用户无法直接通过函数日志、监控指标来具体定位问题,还需要借助例如 coredump、tcpdump、jmap 等工具进行问题的深入排查。
例如,某用户发现自己的线上程序最近出现一些函数错误提示,报错内容都是连接远程某服务时超时。该用户怀疑是函数实例与远端服务的网络连接不稳定,因此想进入实例内部,分析实例与远端服务的网络情况。此时,我们可以按照以下步骤进行问题的排查。
1)如图所示,登录实例内部后,需要执行 apt-get update 和 apt-get install tcpdump 两条命令,进行 tcpdump 工具的安装。
实例登录与安装软件效果图
2)安装完毕后,执行 tcpdump 命令,对远端服务 IP 的请求进行抓包,并将抓包结果保存在 tcpdump.cap 文件中。
3)抓包完毕后,借助 OSS 命令行工具 ossutil64,将 tcpdump.cap 文件上传到自己的 OSS,然后下载到本地借助分析工具 Wireshark 进行分析。
本地调试
命令行工具
大部分 FaaS 平台会为用户提供相对完备的命令行工具,如阿里云的 Funcraft,同时也有一些开源项目如 Serverless Framework、Serverless Devs 等支持多云厂商的 FaaS 平台。
通过命令行工具进行代码调试的方法很简单。以 Serverless Devs 为例,本地调试阿里云函数计算方法为:首先确保本地拥有一个函数计算的项目,然后在项目下执行调试指令,例如在 Docker 中进行调试,如下面所示:
通过命令行进行本地调试
编辑器插件
以 VSCode 插件为例,下载好阿里云函数计算的 VSCode 插件,并且配置好账号信息之后,在本地新建函数,并且在打点之后进行断点调试,如图所示:
编辑器插件中进行调试
其他调试方案
Web 框架的本地调试
app = bottle.default_app()
并且对 run() 方法进行条件限制(if __name__ == '__main__'):
if __name__ == '__main__':
bottle.run(host='localhost', port=8080, debug=True)
例如:
# index.py
import bottle
@bottle.route('/hello/<name>')
def index(name):
return "Hello world"
app = bottle.default_app()
if __name__ == '__main__':
bottle.run(host='localhost', port=8080, debug=True)
本地模拟事件调试
import jsondef handler(event, context): print(event)def test(): event = { "events": [ { "eventName": "ObjectCreated:PutObject", "eventSource": "acs:oss", "eventTime": "2017-04-21T12:46:37.000Z", "eventVersion": "1.0", "oss": { "bucket": { "arn": "acs:oss:cn-shanghai:123456789:bucketname", "name": "testbucket",
"ownerIdentity": "123456789", "virtualBucket": "" }, "object": { "deltaSize": 122539, "eTag": "688A7BF4F233DC9C88A80BF985AB7329", "key": "image/a.jpg", "size": 122539 }, "ossSchemaVersion": "1.0", "ruleId": "9adac8e253828f4f7c0466d941fa3db81161****" }, "region": "cn-shanghai", "requestParameters": { "sourceIPAddress": "140.205.***.***" }, "responseElements": { "requestId": "58F9FF2D3DF792092E12044C" }, "userIdentity": { "principalId": "123456789" } } ] } handler(json.dumps(event), None)if __name__ == "__main__": print(test())
03
如何进行项目构建?
通过开发者工具去依赖安装和项目构建
Serverless 架构下的应用开发和传统架构下的应用开发有一个比较大的区别是二者所关注的内容维度是不同的,例如理想状态下的前者并不需要人们关注服务器等底层资源。
但是在当今的 Serverless 发展阶段,Serverless 架构下的应用开发真的不需要人们对服务器等额外关注吗?其实不是的,虽然 Serverless 架构强调的是 Noserver 心智,但是在实际生产中,有很多依赖等是无法跨平台使用的,例如 Python 语言中的某些依赖需要进行二进制编译,和操作系统、软件环境等有比较大的关系,所以项目中如果引入这类依赖,需要在和函数计算平台线上环境一致的环境中进行依赖的安装、代码的打包或项目的部署。
阿里云函数计算 FC 对自身的线上函数环境有比较细致的描述,提供了相应的文档,例如使用 C、C++ 、Go 编译的可执行文件,需要与函数计算的运行环境兼容。函数计算的 Python 运行环境如下:
Linux 内核版本:Linux 4.4.24-2.al7.x86_64。 Docker 基础镜像:docker pull python:2.7 ; docker pull python:3.6。
但是,在实际应用开发过程中,依赖的打包依旧是让一众开发者头疼的事情。他们在很多 Serverless 应用开发过程中都会面临类似的挑战:项目在本地可以正常运行,一发布到线上就找不到某个依赖,但是实际上依赖是存在的,此时问题定位就成了非常困难的事情。
目前来看,为 Serverless 应用安装依赖或者项目构建的方法通常有 3 种:
1)在本地创建项目之后,自行根据云厂商提供的环境数据进行线上环境搭建,进而进行依赖的安装。这种方法相对来说自主可控,但是难度非常大,操作较为繁琐。
2)用已有的开发者工具进行依赖的安装,如图所示:
开发源代码; 执行 s build –use-docker 命令之后,自动根据 requirements.txt 文件下载对应的依赖到本地,并且和源码一起组成交付物; 执行 s deploy 命令将整个交付物打包,创建函数,同时设置好依赖包的环境变量,让函数可以直接输入对应的代码依赖包。
新书推荐