转眼间,距离Jerry最近一篇文章推送已经过去了一个多月的时间了。
公众号更新的频率降低,不是因为Jerry偷懒,而是由于从春节过后,我所在的SAP成都研究院数字创新空间整个团队,一直在忙一个5月份需要交付的项目上。
Jerry每天的工作量像下面这张图这样:
这个项目里Jerry负责的是后台开发工作,我用nodejs开发了若干微服务,每个微服务实现一个特定的业务逻辑。这些微服务由Jerry另外开发的一个编排器(Orchestra)统一调度。整套后台实现部署在亚马逊云平台(Amazon Web Service,以下简称AWS)上。
离交付日期越来越近了,我们的功能也赶得差不多了。本地测试运行得很好的场景,部署到AWS上运行后出现了一些bug。比如昨天就遇到一个棘手的bug,因此有了今天这篇文章。
2014年五一节的前一天,当时Jerry还在SAP CRM开发团队工作,负责处理SAP CRM中间件的一个bug。这个bug和代码执行时序有关,每执行一次只有40%的几率能重现,花了我整整一天(8个小时)的时间调试。因为重现bug的场景太复杂,需要调试的ABAP代码量太大,所以让我印象深刻。那个bug处理完之后,我也对自己花了8小时才搞定该bug的效率很不满意,因此写了一篇博客总结这次排错的经验教训:
My Tips about how to handle complex and tricky issues
https://blogs.sap.com/2014/05/01/my-tips-about-how-to-handle-complex-and-tricky-issues/
回到昨天我遇到的在AWS上出现的bug,根据问题的表象,一开始我和负责前端开发的同事,连这个问题出在前端还是后端都没办法判断。当微服务部署在本地并进行测试时一切正常,只有部署在AWS上进行集成测试时才会暴露,而运行在AWS上的nodejs应用,我昨天还不知道如何调试,因此只好采用我大二刚学C语言编程时用过的最笨的排查办法:打日志。
2001年,在结束了一年的计算机专业基础课学习后,Jerry开始了Unix环境下C语言编程的学习。当时我对gdb这种以命令提示行方式进行的调试风格很不适应,大多数时候的排错采用的还是在代码里添加printf语句打印变量内容的方式来进行,被寝室的同学鄙视了好久。
于是昨天我继续采用了这种自己18年前就曾经用过的排错方式:
1. 在可能引起bug的相关代码处逐一加上日志输出语句
2. 执行会出现bug的用户操作
3. 阅读AWS上生成的日志语句
上述三个步骤是一个不断迭代的过程。最开始我加了若干日志输出语句,执行操作后阅读生成的日志,发现没有任何异常。于是不断地增加新的日志打印代码,最后导致了执行一次操作,会生成1200行的日志输出。
我和负责前端开发的同事两人坐在显示器前,一行行检查这海量的日志输出。由于问题是用户第二次操作后才会暴露,每次操作会生成不同的会话,我们被迫不断的上下滑动屏幕来比较这两次会话的uuid和相关的WebSocket uuid等变量。Jerry很快发现,眼睛一眨不眨地盯着显示器逐条检查日志,时间一长眼睛就痛得受不了。无奈之下,只得把这些日志用打印机打印出来,用不同颜色的笔标注出两个会话对应的各种变量,在纸上来回比对。于是就有了下面这些纸张:
虽然最后用这种办法,成功排除了后台出错的可能性,使我们得以把精力花在前台代码的审查上,但是像我一个同事评价的,“这种方式太不环保了”,并且我自己也觉得,效率太低了。
后来好几位热心的同事告诉Jerry,就算运行在SAP Cloud Platform或者AWS这些云平台上的nodejs应用,也是可以单步调试的,Jerry Google了一下,发现远程调试确实很简单,就两条命令而已。
Jerry用我们创新空间团队另外一位同事Haytham开发并部署在AWS上的一个nodejs应用为例来尝试如何在我的本地电脑上对其进行调试。
Haytham虽然是一个大四本科生,但是已经在SAP成都研究院Jerry所在团队实习将近十个月的时间了,最近三个月一直在SAP德国总部参与一个项目的开发。
等Haytham回到成都后,会将自己这十个月的工作感悟,从一个SAP新人的视角给大家分享出来,敬请期待。
Haytham之前写过的文章:
SAP成都研究院许聚龙:Hello, Coresystems!
Haytham写的这个nodejs应用实际上是Github Webhook的一部分。我们在本地进行微服务nodejs开发,本地git客户端推送代码到远端github仓库。然后需要在AWS上手动git pull把最新的代码拉下来,再用一个开源工具pm2进行微服务部署。Haytham写的这个nodejs应用,能实现本地git推送完毕后一切后续流程的完全自动化,节省了我们大量的部署时间。
下面就来对Haytham这个运行在AWS上的nodejs应用进行远程调试。
1. 用node --inspect-brk在AWS上以调试模式启动应用。
之后控制台上的输出表明有一个nodejs进程以WebSocket协议在127.0.0.1:9229这个地址上监听调试客户端的连接。
2. 我在我的本地电脑上,用如下命令行将我本地电脑的端口9221映射到AWS调试进程监听的9229端口上:
ssh -i C:甥敳獲i042416.sshKOI.pem -L 9221:localhost:9229 ubuntu@ec2-us-east-2.compute.amazonaws.com
现在,本地电脑上Chrome浏览器地址栏chrome://inspect里指定监听地址为localhost:9221,
通过第二步建立的SSH tunnel,
我就可以用本地电脑连接到AWS上的nodejs应用并进行调试了。
现在终于可以在Chrome开发者工具里进行愉快的调试了:
因为我平时本地做nodejs开发和调试时,更喜欢用Visual Studio Code,所以下一步我准备试试用Visual Studio Code进行远程调试。
说到Visual Studio Code,Jerry突然想起今天在网上看到的一个关于这个IDE的有意思的扩展,名为"超越鼓励师"。
Jerry试着在自己的Visual Studio Code扩展安装栏里搜索了一下,这个扩展还真的可以下载。不过扩展里出现的"杨超越",Jerry又孤陋寡闻了,咨询了老婆后才知道她是谁。
至于实际效果如何,Jerry不做评价,欢迎Visual Studio Code爱好者自行下载体验。
最后,祝各位程序猿/程序媛们每天即使没有程序员鼓励师的陪伴,仍然可以愉快地编程。感谢阅读。