caoz的心得与分享,只此一家,别无分号.

出了bug怎么办

发布日期:2016-11-25 15:15:00 +0000

我其实真的是后知后觉的一个人,随着岁数增加,越来越跟不上时代,很多新东西的尝试都比同行要晚很多,这是最近几天,才第一次注册airbnb,第一次通过airbnb预订房间,然后,就遇到了问题,在注册邮件验证的环节,系统报503错误, pc,手机均无法通过验证,于是,第一次尝试失败。


当然,我今天不是要吐槽airbnb的技术,但作为老程序员,我总会有个代入感,设身处地的想,如果我们遇到了,会怎样。


今天说说这个问题,一个正在线上运营的系统,如果遇到有反馈说,产品出现了bug,作为运维,作为研发,正确的应对策略和步骤,应该是怎样的。


那很多人会说,出bug第一步就去检查代码呗。


但代码哪是那么容易检查的。


一个程序员水平高低,写代码的时候你很可能看不出来,但出bug的时候,分析代码的时候,有经验有思路的,其处理效率往往比缺乏经验没思路的高一个数量级。


一般而言,一个大公司,已经上线的系统,bug应该不是说那种非常表露的,往往可能需要一定条件才会触发。


我一般的思路和建议是


第一步,评估影响范围


这个问题究竟是影响了多大范围的用户,以及什么范围的用户。这是作为线上运营人员需要非常明确的,而且对问题的解决优先级也有重要的意义。


同时,基于影响范围的判断,也对问题的可能性做了初步的排查。


那么,怎么评估影响范围?


两个方向,一是通过统计数据,二是通过日志分析。


用户反映网站或APP打开慢,打开卡,或者打开报错无法登陆。


这种属于全局问题,这种问题建议 看统计数据来评估,比如当前活跃用户,日活跃用户及活跃用户的时间分布,与,比如说上周同期对比。


一个简单的实时在线对比, 可以快速定位出故障的严重程度和影响用户规模。 那么,如何进一步排查呢?


这要看你平时记录的数据全不全,比如,在当前在线或最新访问记录里,是否有地区分布,用户上网环境分布,用户客户端浏览器分布,用户手机类型和操作系统型号分布,这样可以快速做一个排查。


那么,如果不是全局性问题,比如我这次遇到的问题,是邮件验证出错,这种问题去看同时在线或访问数据就没有意义了,可以通过日志数据做快速分析,比如,最近用户邮件验证的成功率是多少,以前是多少,如果有历史数据对比,就可以知道大概是不是有较多用户出现了问题,然后,继续细分,比如说,不同邮件服务商的验证成功率多少,不同账号注册方式的邮件验证成功率多少,(比如FB注册,微信注册,或者微博注册等) 以及不同网络环境,或者客户端版本下的邮件验证成功率多少。


这样,这个问题的影响范围,就可以快速确认了。


如果以上数据全都正常,那么说明这个问题属于极个别用户在极个别环境下才会触发的问题,当然问题依然需要解决,但至少不用太焦虑。


很多人一看日志就会默认认为是错误日志,但是很多时候,用户反馈的代码逻辑问题很可能并没有体现在错误日志里,不过在airbnb这个案例里,系统反馈的是503,应该是可以从日志里看到的。


有人可能会说日志审计系统会不会很复杂,或者要不要推荐好用的日志审计系统,我个人的经验,如果我们只是针对我们的业务定制开发,这个工作其实并不复杂,而且针对性强。当然,如果有好用的日志审计系统,可以快速搭建并且能够完整的体现出业务诉求,那自然也值得推荐,但我一直都反对简单问题复杂化,有时候很简单的诉求,弄一套很复杂的日志审计系统,然后研发和运维都需要很长的学习时间和繁琐的配置流程,并且每次修改调整都需要大动干戈,那就得不偿失了,还不如自己针对业务简单写写。


第二步,试图重现问题


评估完影响范围后,根据评估的的范围特征,试图用同样的方式重现问题。


通常,问题都会在特定条件下触发,而问题就在于,你无法明确知道,这个特定条件究竟包含了哪些因素。


如果根据用户反馈的信息,以及如上基于数据分析的结论,能够明确该问题的触发条件,并实现完整的问题重现,那么对解决问题,就会非常有帮助,研发和运维就可以在测试环境里逐步调试问题。


但如果,用户反馈信息有限,以及基于数据分析的结论并不能重现问题,也就是存在不明确的触发条件,这个重现就比较困难。


这时候,我常用的方法是,在与问题有关的代码中,增加非常多的记录节点,加入更具体的追踪代码,将更具体的信息获取,并输出到日志。通过定期对这些日志的分析,找到出问题用户的日志,并基于日志深入分析问题。也就是,基于用户的真实行为的数据记录,重现和回放问题。


这里一个很重要的方法就是,跟踪定位中间数据。


我发现一些程序员修bug很没有效率,往往是缺乏一个概念,你如果得到的结果与预期不一致,你应该把程序流转中每个节点的中间数据,中间变量都拿出来看看,是不是和预期一致,才能更容易定位问题。这是定位很多程序逻辑bug的重要手段。


在校园里,我们编写程序的逻辑相对简单,输入输出之间的数据流转相对直接,中间过程相对较少。但在工作环境里,数据流转,中间过程,往往复杂的要命,所以一旦中间出错,调试的复杂度就非常高。现在流行说面向对象编程,很多数据逻辑和操作逻辑被对象封装,简化了程序员的思考复杂度,同时也提升了团队协同作战能力,以及代码的可维护性,但这里的问题是,一旦代码逻辑出错,你可能需要深入到每个对象中寻找潜在问题点,或者,在没有bug的情况下,涉及优化的问题,也需要深入到每个对象去分析性能的瓶颈点和潜在优化点。


所以,这里总结就是


尽量明确问题的触发条件,实现问题重现,在不能明确问题触发条件的情况下,在代码中增加节点跟踪,通过线上用户实际操作中的数据反馈,获得bug可能的触发条件和代码的逻辑漏洞。


一个大规模的网站和应用app,如果bug问题的影响范围并非是极个别情况,那么在实际用户操作中,就会有一定的重现率。


隔一段时间,你应该有一定的判断条件,知道日志中,哪些日志记录的是重现问题的用户,然后通过对这些日志的分析,相当于重现了问题并锁定问题所发生的具体节点。


第三,临时方案和终极方案。


这也是一个运营中常见的技术策略,如果问题符合以下两个条件


影响范围较大

难以定位,或者可以定位但解决成本很高


那么,需要尽快提供临时替代方案,或补丁方案。


比较常见的思路


临时替代方案,通过功能降级或者一定程度的减少易用性或其他产品特性,保证基本业务逻辑的顺畅,保证用户可以完整完成基本的业务诉求。这个方案与原有系统的功能模块是替换关系。 当问题影响范围非常大的时候,适合这样,但对用户的体验伤害也是很大的。


补丁方案,不替代现有方案,但针对现有遇到问题和障碍的用户,额外提供第二种选择,以功能降级或一定程度减少易用性或其他产品特性,保证基本业务逻辑的顺畅及用户完整完成业务诉求的能力。 当问题影响范围不能被忽视,但大多数用户并不受影响的时候,建议使用这样的方案,保证大部分用户的体验毫无损害,并尽可能让少部分遇到问题的用户可以平稳过渡。


但以上都是过渡方案,但有时候,有些过渡方案可以用好几年,甚至很久很久,甚至在系统已经彻底完成升级和修补后,为避免其他潜在的未知问题,补丁方案仍然静悄悄的躲在代码库的角落里,等待哪个不走运的用户去触发。


这里强调一点,我们在做解决方案的时候,要尽可能多留一个心眼,就是,永远要考虑系统异常该怎么办。


降级方案,补丁方案,事故跳转方案,类似这样的策略,也是系统设计,系统架构中需要认真思考的,这种策略也许永远不会生效,当然这样最好,但一旦生效,有可能就是救命的策略。否则,产品用户群断崖式下跌可能随时都会发生。


第四步,风险评估及持续优化


实际上很多公司都会遇到一个尴尬的问题,解决一个旧问题,带来几个新问题,这是技术演进中经常遇到的障碍,我们看这么多互联网巨头,这么多成熟的线上产品,哪个产品说,成熟度很高,不需要程序员继续维护,继续修补了?几乎没有。


而且就算是当前状态下没有问题的产品,谁敢说随着使用频次,使用人群,使用场景的增加,后面就没有问题。


修补问题的时候,不要头疼医头,脚疼医脚,不要只是为了解决当前问题而思考,也要从综合层面思考。


对系统的整体是否有影响,对其他相关的功能和特性是否有影响,修补是否带来额外的负载和性能开销。


此外,对业务逻辑的梳理,如果这个业务已经属于打满了各种目的的补丁,很多补丁各种影响,那么就应该从全局思考,是否可以有更优雅,逻辑上更加顺畅的解决方案,而不是一个补丁接着一个补丁的去应付,当然,短期靠一个补丁去应对是必要的,但长期呢?


不过这事也不绝对,对于即将放弃,或者属于下坡路,只在维持状态的产品,可能打个补丁就够了,不会再考虑架构优化的事情了,对一些价值明显偏低的项目投入太多技术资源也是不合理的。所以,技术人员看这个事情的时候,也要理解公司业务层面的考量。


以上总结一下,以前也提到过,数据记录,统计数据,日志数据,越详尽,越完整,对问题分析越有帮助。


遇到难以定位的bug,如果本地难以重现,增加线上的数据日志,通过分析线上重现问题的用户的相关代码日志记录,来重现和定位问题。


懂技术之外,也要懂业务,这样在处理过程中,才能充分体现出抓大放小,优先级和技术资源的投入才能有的放矢,一些临时方案,补丁方案的选择,也必须从业务的优先级出发,用低成本高效率的方式来保障在问题结局前满足基本的用户体验。


到这里必须说一下,我反馈了airbnb的这个问题,第二天晚些时候,这个故障消失了,我也终于第一次用airbnb完成了订房。但我并不知道这个问题的影响范围是多大,触发条件是什么,也不知道他们的分析和处理逻辑是什么。 也许比我说的高明很多,也许只是上了个临时方案,谁知道呢。



吐槽时间


我个人认为,我还是尽量容忍和聆听不同的声音,但我必须承认,我很难做到完全的平和,从我这边的留言反馈,第一,反对和反面的声音我不会遮掩,一般而言,对留言的策略,只要不是太空洞,我会尽量放出来,此外,按时间来,超过100篇就对不起了,所以有些激烈的评论没有放出来,是因为微信的评论数限制和发表的时间比较靠后,我个人基本不会因为好恶决定放谁不放谁。 第二,我不会去对负面的声音做言论上的攻击。


但我讲句实话,我其实挺理解那些对评论说脏话的大V,真的,某些评论者的素质真的让人忍不住想爆粗口。


其实我觉得,如果有专业人士,提供非常好的案例或数据,来批驳我,我还是很欢迎的,毕竟,正如我常说的,分享即学习,我讲错了,有人来打脸,其实我赚到了,真的赚到了。


我这里举个例子,有个评论限于100篇我最终没放出来,但我很感谢对方提供的数据,讲双11的那篇,有个用户提到了一个数据,阿里的财报收入,和公开的淘宝+天猫营业额相比,只有不到3个百分点,是否可以理解为,流量成本并没有那么高。这其实是在反驳我所说的关于流量成本的问题。


坦白说,这个数据以前我没在意过,开始对方提到的时候我也没理解明白,但是后来想想非常有道理,虽然这里存在一些可以解释的理由,比如淘宝卖家的外部流量采购,比如虚假交易在交易额中的占比等等,但这些理由对这个数据的影响比例会有多大呢,所以一边很多商家反映流量成本过高,另一边这个数据显示其实远低于线下门店的流量成本。(店租,商场分成等)。所以这个问题我现在还在思考,但也非常感谢类似这样的反对声音。


比较烦的是那种,什么料都没有,居高临下甩几句话恶心你的。


典型类似言论如,


建议作者不要写不擅长的领域。

外行,鉴定完毕。

你不懂就不要乱写。


我也不知道对方有多专业,反正他们爽一句就跑了,好像当年我写e租宝的时候也跳出来一批,结果后来这些人也不知道跳哪里去了。


此外,还有逻辑混乱,或者完全不知道逻辑为何物的。


其实,我觉得吧,如果您想点拨我,纠正我,您只要讲的有道理,我会感谢您;如果您就是瞧不起我,看我SB,很简单,我也没求着您天天赞我赏我捧我,说的现实一点,我也没指着靠这个吃饭。


我信箱里压着一堆各种商务合作的邮件一单都不敢接我图什么呢我。


最后的最后,公开回答一个评论,云舒童鞋昨天提到了哥德尔不完备定理,这个定理表达的意思大概是,世界上存在这样的命题,不可证明,亦不可证伪。


那么这种东西我是不懂的,所以请教了一个数学学霸女粉丝。


对方表示,哥德尔不完备定理,这个描述的内容,本身是可以证明的,(补充一句,我查了一下,在百科里都有简单到证明案例)。 但描述中提到的不可证明的命题,是不可以被称作数学定理。所以数学,科学中存在很多假设,猜想。这也是科学严谨性的体现之一。


这个逻辑,不知道读者能否体会。


然后我觉得我也是自己作,学学咪蒙搞搞鸡汤,学学占豪扯扯强国梦,又吸粉又吸钱,整这跟读者折腾逻辑,回个评论都要去搜很多新名词,我特么的是不是自作自受。