硬核调试实操 | 手把手带你实现 Serverless 断点调试
作者:千风 (阿里云函数计算研发工程师)
在应用开发过程中,或者开发完成后,若出现执行结果不符合我们的预期时,通常需要进行一定的调试工作。但是在 Serverless 架构下,调试工作往往会受到一些环境因素限制,如所开发的应用在本地是比较健康的、且符合预期的运行,但是在 FaaS (Functions as a Service) 平台上,出现了一些问题;或者是在某些特殊的环境下,本地没有办法模拟线上环境,难以进行项目的开发和调试怎么办?
概述
本文将借助 Serverless Devs 工具,对函数计算 (FC) 应用的断点调试步骤进行详细指导,手把手带你实现 Serverless 的断点调试,并从以下四个方面为你厘清 “硬核调试” 的脉络步骤,干货满满:
在 Serverless 应用架构下,调试能力往往是应用开发者所十分关注的问题,它决定着程序的开发效率。Hackernoon 在关于 Serverless (无服务器) 的业界调研报告指出:迄今为止,Debugging (调试) 仍旧是 Serverless 落地最大的痛点与挑战。
报告《Top 5 Serverless Trends》:https://hackernoon.com/top-5-serverless-trends-in-2020-wd1m3t8g
调试能力主要包含两种,一是运行程序的能力;二是断点调试能力。前者是调试的基础能力,可以判帮助开发者判断程序能否正常运行,验证程序运行结果的正确性;后者是调试的高级能力,能够帮助用户方便定位到导致程序运行出错或者不符合预期的位置。
为了能够克服这些缺陷,将 Serverless 应用调试做到开箱即用,阿里云函数计算团队经过一番探索,开发出了一套业界创新的调试工具,全方位提供本地调试以及端云联调能力。
详情可点击阅读:创新推出 | Serverless 调试大杀器:端云联调
本地调试:基于本地环境以及网络,依赖容器化技术,对 Serverless 应用进行拟运行,从而达到调试的目的,具体操作文档可参考。
https://github.com/devsapp/fc/blob/main/docs/zh/command/local.md
端云联调:基于本地环境,突破网络限制,依赖容器化技术,对 Serverless 应用进行拟运行,运行时打通本地与云端网络的壁垒,保证与云端资源的交互,使用文档请参考。
https://github.com/devsapp/fc/blob/main/docs/zh/command/proxied.md
本文所提到的本地调试工具,均提供断点调试能力,且与 Serverless 应用程序开发规范完全兼容,下面我们一起看一下关于断点调试的具体操作步骤。
调试之旅
- 启动 Serverless 应用
- 启动断点调试器
- 开始断点调试
- 结束断点调试
「01」
前置操作
在开始进行调试之前,需要进行一些前置操作,本文将前置操作分为通用前置操作以及端云联调附加的前置操作:
1)通用前置操作:
安装调试 IDE:可选的 IDE 有 VSCode、Pycharm 以及 Intellij 三种;
随后在开始使用这些功能之前,请安装好调试工具: 这里我们需要安装一下 Serverless Devs,具体的安装方式参考文档:
https://help.aliyun.com/document_detail/195474.html;
熟悉新一代函数计算工具链的使用方式,可参考:
https://github.com/devsapp/fc
下载安装 Docker:调试能力都需要依赖 Docker,因此需要本地环境中有 Docker 工具,安装方式请参考这里:
https://docs.docker.com/get-docker/
最后还需要注册一个阿里云账号,使用 Serverless Devs 配置阿里云账号,具体配置方式可以参考这里。
https://help.aliyun.com/document_detail/295894.html
2)端云联调附加的前置操作:
我们需要准备一个阿里云账号,由于端云联调涉及到辅助资源的部署和删除,如果账号为子账号,需要为该子账号添加指定的一些权限,具体权限集合可参考:
https://github.com/devsapp/fc/blob/main/docs/zh/command/proxied.md#%E6%9D%83%E9%99%90%E4%B8%8E%E7%AD%96%E7%95%A5%E8%AF%B4%E6%98%8E
「02」
参数引入
完成以上前置条件的准备后,我们先了解一下调试指令中与断点调试所相关的具体参数(可滑动):
-c, --config [vscode/pycharm/intellij] [Required] Select which IDE to use when
debugging and output related debug
config tips for the IDE. value:
vscode/pycharm/intellij
-d, --debug-port number [Required] Specify the local function
container starting in debug mode, and
exposing this port on localhost
--debug-args string [Optional] Additional parameters that
will be passed to the debugger
--debugger-path string [Optional] The path of the debugger on
the host
--tmp-dir string [Optional] The temp directory mounted to
'/tmp' , default:
'./.s/tmp/invoke/serviceName/functionName/'
使用断点调试时,--config 参数以及 --debug-port 参数是必要的:
--config 会指定断点调试的 IDE 环境,目前支持 VSCode、Pycharm 、Intellij 三种。
--debug-port 会指定调试的监听端口。
另外,其余三种参数是可选的:
--debug-args 会自定义程序启动时的调试参数,不指定时默认的调试参数可以参考文末附录部分。
--debugger-path 会将本地指定路径挂载到程序运行环境的 /tmp/debugger_file 之中。
--tmp-dir 会将本地指定路径挂载到程序运行环境中的 /tmp 目录上,在调试时,程序写入 /tmp 的结果文件则会在映射到本地目录,用于验证结果是否符合预期。
「03」
实操演练
1)VSCode
- 调试 Event 函数:
# 本地调试
$ s local invoke --config vscode --debug-port 3000
# 端云联调
$ s proxied setup --config vscode --debug-port 3000
启动指令执行后,本地的函数计算执行环境会有一定阻塞,我们需要等待调用;与此同时当前项目会生成 .vscode/launch.json 文件,该文件是基于 VSCode 进行调试的配置文件,若该文件已经存在,那么启动指令会打印相应配置文本,如下图所示,需要利用这部分内容覆盖已有 .vscode/launch.json 中的内容。
对于本地调试而言,启动调试器后,程序便已经启动,此时就可以开始进行我们的断点调试工作了。如果是端云联调的话,启动调试器后,在启动指令终端页面,会出现 "Debugger attached." 字段,这时说明调试器也已启动成功,正在等待被调用,接下来我们继续进行如下步骤即可。
调试 php7.2 Event 函数
php7.2 runtime 的本地调试 IDE 建议使用 VSCode,其断点调试步骤与其他语言有一定差异性,因此单独进行介绍。目前 php7.2 runtime 不支持端云联调断点调试。
step1:首先启动 Serverless 应用,打开终端,进入目标项目下,输入启动指令 s local invoke --config vscode --debug-port 3000。
与之前不同的是,Event 函数启动指令执行完成后,并不会出现阻塞的情况,而是会直接执行成功,同时在当前项目下会生成 .vscode/launch.json 文件,如前文所述。
step2:启动断点调试器,打开 VSCode 界面,然后打开 s.yml 中 codeUri 所存放的源代码,为其打上断点,接着点击开始调试按钮,具体执行如下图所示。
step3:开始断点调试:打开一个新的终端页面,再次输入启动指令 s local invoke --config vscode --debug-port 3000 后,程序启动,断点调试开始。
- 调试 Http 函数
VSCode 启动调试器示意图
调试 php7.2 Http 函数
php7.2 runtime 的本地调试 IDE 建议使用 VSCode,其断点调试步骤与其他语言有一定差异性,因此单独进行介绍。目前 php7.2 runtime 不支持端云联调断点调试。
step1:首先启动 Serverless 应用,打开终端,进入目标项目下,输入启动指令 s local start --config vscode --debug-port 3000,启动指令执行后,会在当前项目下会生成 .vscode/launch.json 文件,如前文所述,同时项目会阻塞住,此时需要执行 Ctrl+C 退出。
step2:启动断点调试器,打开 VSCode 界面,然后打开 s.yml 中 codeUri 所存放的源代码,为其打上断点,接着点击开始调试按钮,具体执行如下图所示。
step3:开始断点调试:打开一个新的终端页面,再次输入启动指令 s local start --config vscode --debug-port 3000 后,本地的函数计算执行环境会阻塞等待调用,并打印访问 http 函数的 url 字段,可以通过 curl 指令、浏览器等方式访问 Http 函数的 URL,此时程序启动,断点调试开始。
step4:结束断点调试:调试完成后,主动关闭断点调试器,然后在启动指令终端页面,执行 Ctrl+C 即可退出调试进程。
2)Intellij
基于 Intellij 进行断点调试时,针对不同语言需要手动在 IDE 中配置相应地断点调试器,由于使用 Intellij 开发最多的语言是 Java,同时更换 IDE 后,唯一不同的步骤只有“启动断点调试器”,因此接下来我们将以本地调试 Java Event 函数为例,对“启动断点调试器”步骤进行详细说明。
step1:启动 Serverless 应用:由于 Java 是编译型语言,因此在开始前需要对程序进行打包,本文示例会使用 mvn package 对函数打包,然后执行启动指令 s local invoke --config intellij --debug-port 3000。
step2:启动断点调试器:
打开 Intellij 界面,在菜单栏依次选择 Run -> Edit Configurations。
随后如下图所示,新建一个 Remote JVM Debug。
新建 Remote JVM Debug
接着,自定义调试器名称,并将端口设置为 3000,如下图所示。
Intellij 调试器配置
最后,打开 s.yml 中 codeUri 存放的源代码,为其打上断点,接着点击开始调试按钮,如图所示。
Intellij 启动断点调试器
3)Pycharm
当前只有本地调试能够在 Pycharm 中进行断点调试操作,支持的运行时有 python2.7 和 python3两个版本。在 Pycharm 中进行断点调试时,不仅需要在 IDE 中配置断点调试器,还需要对使用者的源码进行侵入式修改,由于操作步骤内容与常规内容有所不同,接下来我们详解一下这部分的调试步骤。
step1:启动 Serverless 应用:首先,打开终端,进入目标项目下,输入启动指令:
# event 函数
$ s local invoke --config pycharm --debug-port 3000
# http 函数
$ s local start --config pycharm --debug-port 3000
与之前不同的是,Event 函数启动指令执行完成后,并不会出现阻塞的情况,而是会直接执行成功。此时就需要记录 "Tips for PyCharm remote debug" 内容,具体内容示例如图所示,记录完成后,如果是 Http 函数,则输入 Ctrl+C 退出启动程序。
Tips for PyCharm remote debug 内容示例
step2:接下来启动断点调试器:启动断点调试器主要包含 IDE 断点调试器配置和源码更新两部分。
随后设置自定义调试器名称,并基于图五中获取的内容配置 IDE host name、Port 以及 Path mappings 这三个调试器配置的详情,如图中所示。
pycharm 调试器配置
随后打开 s.yml 中 codeUri 存放的源代码,将例图中(Tips for PyCharm remote debug 内容示例)的代码内容粘贴到代码开头,然后按需在源码指定位置打上断点,接着点击开始调试按钮,具体操作如图 (pycharm 启动断点调试器)所示。
Tips for PyCharm remote debug 内容示例
pycharm 启动断点调试器
step3:开始断点调试:打开终端,并进入目标项目,执行启动指令,p.S.此时可以不用带上断点调试的相关参数。
# event 函数
$ s local invoke
# http 函数
$ s local start
Event 函数启动指令执行后会直接进入断点调试阶段;Http 函数启动指令执行后,可以先通过 curl 指令、浏览器等方式访问 Http 函数的 URL,此时程序会启动,断点调试就开始了。
step4:结束断点调试:调试完成后,主动关闭断点调试器,对于 Http 函数而言,在启动指令终端页面,需执行 Ctrl+C 方可退出调试进程。
结语
Serverless 应用的调试虽然备受诟病,但是各个云厂商并没有因此放弃在调试方向的不断深入探索。以阿里云函数计算为例,目前支持提供在线调试、本地调试、端云联调等多种调试方案。而 Serverless Devs 工具所提供的应用调试能力也十分全面了。
上文是我所分享的一些实操经验,但是在过程中也发现了一些待改进的点,如:
断点调试步骤繁琐,需要在多个页面来回切换,如果能将工具集成到 IDE,以插件化形态供所用户使用,简化流程,那么体验感会大幅提升。
断点调试模式下的热更能力:Http 函数的断点调试过程中,并不支持代码热更新,每次修改完代码后,都需要重新执行一遍断点调试流程,体验不太流畅。
断点调试能力目前还未全面覆盖所有 Runtime,例如 custom runtime 不支持断点调试,php runtime 不支持端云联调断点调试等。
希望本文对你有些帮助。同时也欢迎大家钉钉扫码加入 Serverless 开发者技术群,一起学习交流。
Serverless 开发者技术学习群
附录
「01」
默认调试参数
「02」
断点调试实操视频
下面的动图教程均已提前完成文中提到的 “前置操作” 步骤,若要参考具体动图进行实践,请先完成上文 “前置操作” 的相关流程。
1)VSCode
本地调试 Event 函数
本地调试 php7.2 event 函数
端云联调 Event 函数
本地调试 Http 函数
本地调试 php7.2 Http 函数
端云联调 Http 函数
2)Intellij
本地调试 Event 函数
端云联调 Event 函数
3)Pycharm
本地调试 Event 函数
本地调试 Http 函数
社区网址一览(可滑动):
社区官网:http://www.serverless-devs.com/
ServerlessDesktop桌面客户端:https://serverlessdevs.resume.net.cn/zh-cn/desktop/index.html
Serverless应用开发者套件:http://serverless-dk.oss.devsapp.net/docs/tutorial-dk/intro/react
Serverless Devs CLI:https://serverlessdevs.resume.net.cn/zh-cn/cli/index.html
Serverless Hub应用中心:https://serverlesshub.resume.net.cn/#/hubs/special-view
RECRUITMENT
极速上手 Serverless
随着 Serverless 热度不断升高,越来越多人期望在实际工作中能快速上手。为了让更多 Serverless 初学者真正学会 Serverless 理论知识,在工作中根据需要灵活应用 Serverless 技术,阿里云 Serverless 团队推出技术图谱,本课程包含机频、动手实验、电子书、直播、开源项目多种形式内容,让各位开发者即学即用,跑步入场享受 Serverless 技术红利!