在应用开发过程中,或者应用开发完成,当所执行结果不符合预期时,我们通常要进行一定的调试工作。但是在Serverless加架构下,调试往往会受到极大的环境因素限制,通常情况下会出现的情况是,所开发的应用在本地是可以比较健康的、符合预期的运行,但是在FaaS平台上,则会出现一些不可预测的问题;或者是在一些特殊的环境下,本地没有办法模拟线上环境,难以进行项目的开发和调试。
Serverless应用的调试,一直都是都是备受诟病的,但是各个云厂商并没有因此放弃在调试方向的不断深入探索。以阿里云函数计算为例,其提供了在线调试、本地调试等多种调试方案。
在线调试
简单调试
所谓的简单的调试,就是在控制台来进行调试,以阿里云函数计算为例,我们可以在控制台通过执行按钮,进行基本的调试:
必要时候,我们也可以通过设置Event来模拟一些事件:
在线进行调试的好处是,可以使用线上的一些环境进行代码的测试。否则当我们线上环境拥有VPC等资源时,在本地环境是很难进行调试,例如数据库需要通过VPC来进行访问时,或者有对象存储触发器的业务逻辑等。
断点调试
在线进行函数计算的代码调试,除了简单的调试之外,部分云厂商也是支持断点调试的,例如阿里云函数计算的远程调试、腾讯云云函数的远程调试等。以阿里云函数计算远程调试为例,我们可以通过控制台进行函数的在线调试。当我们创建好函数之后,可以选择远程调试,并点击开启调试:
开启调试之后,稍等片刻,系统将会进入远程调试界面:
此时我们可以进行一些断点调试:
本地调试
命令行工具
就目前来看,大部分FaaS平台都会为用户提供相对完备的命令行工具,包括AWS的SAM CLI,阿里云的Funcruft,同时也有一些开源项目例如Serverless Framework、Serverless Devs等对多云厂商的支持等。通过命令行工具进行代码调试的方法很简单,以Serverless Devs为例,本地调试阿里云函数计算:
首先确保,我们本地拥有一个函数计算的项目:
然后在项目下执行调试指令,例如在Docker中进行调试:
编辑器插件
以VScode插件为例,当我们下载好阿里云函数计算的VSCode插件,并且配置好账号信息之后,我们可以在本地新建函数,并且在进行打点,之后可以进行断点调试:
当我们的函数调试完成之后,可以进行部署等操作。
其他调试方案
Web框架的本地调试
在阿里云FaaS平台开发传统Web框架,以Python语言Bottle框架为例,可以增加:
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)
这样,我们可以在本地开发的同时,和传统开发思路一样,在本地进行调试。当我们部署到线上时,只需要在入口方法处填写ndex.app,即可实现平滑的部署。
本地模拟事件调试
针对非Web框架,可以在本地构建一个方法,例如要调试一下对象存储触发器,可以是:
import json
def 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())
这样通过构造一个event对象,即可实现模拟事件触发