前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >我的系统有bug?你可得有证据!

我的系统有bug?你可得有证据!

作者头像
xjjdog
发布2021-09-17 10:43:56
2790
发布2021-09-17 10:43:56
举报
文章被收录于专栏:架构专题架构专题

原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处。

我在以前,分析过很多实际运行的故障,并把它做成了专辑,有十几篇文章,点击下面链接即可查看。

《故障看人性》

你要知道,在线下、在测试开发环境能够发现的bug,都是些小儿科。只有到了线上才发生的bug,你才会知道它的凶残。数据错乱,逻辑中断,进程死亡。处在如此问题场景下的你,are you ok?

问题频繁发生,故障难以定位,cto怒而呵斥,“你们难道不能在线上调试一下问题的发生根本么?要形成一套可行的方法论!”

从这种训话可以看出,cto的技术水准一般,但太极修养十分了得。在平常的表达中,在一篇报告中,不要出现技术术语,不要把话说的太死,是一个cto基本的素养。

但是活儿总是要有人干的,公司所有人都打太极,最后将形成一个虚幻的世界,不利于整个组织的健康发展。今天,我们就简单的聊一下线上程序,要留下哪些证据。

1. 证据

问题之所以成为问题,是因为它留下了证据。没有证据的问题,你虽然看到了影响结果,但是你无法找到元凶。比如,某个同学在办公室的饮水机里放了巴豆,让所有同事都畅快淋漓的发泄了一下。但由于没有安装监控,你也就无法找到这个可恶的同学。

而且问题通常都具有人性化,当它发现无法发现它的时候,它总会再次出现。就如同罪犯发现了漏洞,还会再次尝试利用它。

所以,要想处理线上问题,你需要留下问题发生的证据,这是重中之重。如果没有这些东西,你的公司,绝对会陷入无尽的扯皮之中。

1.1 日志证据

日志是最常见的作法。通过在程序逻辑中进行打点,配合Logback等日志框架,可以快速定位到发生问题的代码行。我们需要看一下bug的详细发生过程,对可能发生问题的逻辑进行详细的日志记录,进行更加细致的日志输出,在发生问题的时候,就可以切换到debug进行调试。

在SpringBoot中,可以通过actuator来动态调整相应类的日志级别。在下面的路径中,可以看到日志级别的具体信息。

代码语言:javascript
复制
localhost:8080/actuator/{loggers}

通过发送POST请求到具体的日志控制器,就可以实现动态更改。

代码语言:javascript
复制
curl -X POST \
  http://localhost:8080/actuator/loggers/<Package/Class> \
  -d '{"configuredLevel":"<LEVEL>"}'

但bug的发生频率可能很小,我们开启了debug后,可能等了好几天,同样的问题也没有再次复现,这是最让人头疼的事情。

接入一些APM平台是非常有必要的。最新的opentelemetry,同时记录了Traces, Metrics, Logs等三种格式的数据,对问题的分析支持非常大。

记录详细的监控信息也是非常有必要的,可以看到监控指标的历史时序,辅助我们查找排查问题。

1.2 JVM证据

在事故出现的时候,通常并不是那么温柔。你可能在半夜里就能接到报警电话,这是因为很多定时任务都设定在夜深人静的时候执行。

这个时候,再去看 jstat 已经来不及了,我们需要保留现场。这个便是看门狗的工作,看门狗可以通过设置一些 JVM 参数进行配置。

Java8的gc日志配置和8以后的版本差异很大,下面直接给出相应的配置示例。

java8:

代码语言:javascript
复制
-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps 
-XX:+PrintGCApplicationStoppedTime -XX:+PrintTenuringDistribution 
-Xloggc:/tmp/logs/gc_%p.log -XX:+HeapDumpOnOutOfMemoryError 
-XX:HeapDumpPath=/tmp/logs -XX:ErrorFile=/tmp/logs/hs_error_pid%p.log 
-XX:-OmitStackTraceInFastThrow

java8+:

代码语言:javascript
复制
-verbose:gc -Xlog:gc,gc+ref=debug,gc+heap=debug,gc+age=trace:file
=/tmp/logs/gc_%p.log:tags,uptime,time,level -Xlog:safepoint:file=/tmp
/logs/safepoint_%p.log:tags,uptime,time,level -XX:+HeapDumpOnOutOfMemoryError 
-XX:HeapDumpPath=/tmp/logs -XX:ErrorFile=/tmp/logs/hs_error_pid%p.log 
-XX:-OmitStackTraceInFastThrow

2. 分析

问题分析是最困难的一环。有了证据环节,我们就避免了靠猜去找问题的现状,但如何在这些分散的信息和复杂的路径中,找到问题的根本原因,是非常有挑战的。

如果是大范围的bug,那么强烈建议直接在线上进行调试。不太推荐使用Arthas等工具动态的修改字节码进行测试,当然也不推荐IDEA的远程调试。相反,推荐使用类似金丝雀发布的方式,导出非常小的一部分流量,构造一个新的版本进行测试。如果你没有金丝雀发布平台,类似Nginx的负载均衡工具也可以通过权重做到类似的事情。

在这个新的小版本中,你可以尽情的输出日志,把所有的输入输出都打印到日志里。大多数情况下,你能够通过日志很快发现这个问题。

缓存会是bug产生非常重要的一个影响因素。因为缓存和db通常不在一个基础设施中,通常会存在一致性问题。即使选用了cache aside pattern,实现了延时双删,在某些情况下,数据仍然会发生一致性问题。这种偶发的不一致问题,因为发生频率低,触发条件苛刻,一点发生会非常难以发现。所以一些非常关键的业务,通常会提供一键删除缓存的功能。如果清掉缓存之后,问题消失,那大可不必浪费时间花费在这种小概率事件上。

多线程是另外一个容易出现问题的地方,每个逻辑都必须仔细的进行评估。因为多线程是异步的,有些逻辑只能通过手工去推理,灰度的线上程序可能永远没有条件走到这一步。这个时候,给线程起一个合适的名字,是非常有必要的,这通常是由ThreadFactory去做的。

比如,有些同学,喜欢将字符串拼接起来直接打印成日志。

代码语言:javascript
复制
logger.debug("the request info: userId:{} tel:{},role:{},timeCost:{}")

这二种方式不是说不好,但在你处理问题的时候,就会遇到很多障碍,日志的输出不应该太随意。

代码语言:javascript
复制
logger.debug("the request info$ userId{}|tel:{}|role:{}|timeCost:{}")

通过这种方式,我们可以很容易的利用各种Linux工具,比如sed、awk、grep进行分析。在日志输出的时候,要有一定的技巧,否则你就只能使用肉眼去分析。

3. 总结

要想解决问题,就得通过不断的试错。试错并不是盲目的,我们必须要有各种证据的支持。手机证据最有效的是通过日志,尤其是有一定规律的日志信息。除了分析正常的业务逻辑,数据问题或者多线程问题,同样是常见的bug引起原因。

日志系统与监控系统,对硬件的需求是比较大的,尤其是你的请求体和返回体比较大的情况下,对存储和计算资源的额要求更是高。它的硬件成本,在整个基础设施中,占比也是比较高的。但这些证据信息,对分析问题来说,是非常有必要的。所以即使比较贵,很多公司依然会有很大的投入在这上面,包括硬件投入和人力投入。

如果你想要这样的功能但是没钱也没人?其实那也没关系,雇一个会扯皮的CTO,你的这些问题和bug,都会在你面前消失不见的。

作者简介:小姐姐味道 (xjjdog),一个不允许程序员走弯路的公众号。聚焦基础架构和Linux。十年架构,日百亿流量,与你探讨高并发世界,给你不一样的味道。我的个人微信xjjdog0,欢迎添加好友,进一步交流。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-09-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小姐姐味道 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 证据
    • 1.1 日志证据
      • 1.2 JVM证据
      • 2. 分析
      • 3. 总结
      相关产品与服务
      负载均衡
      负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档