线上故障分析
- 1 生产故障分级规范概要
-
- 1.1 开篇
- 1.2 事故等级定义
-
- 1.2.1 故障等级定义
- 1.2.2 故障 告模板示例
- 1.2.3 故障响应处理机制
- 1.2.4 思考
- 2 生产故障原因和分类
-
- 2.1 故障分类
- 2.2 bug是可以完全避免的么了解
- 2.3 经典故障示例-了解
- 2.4 混沌工程简介
- 3 生产故障定位和解决流程
-
- 3.1 影响服务质量的因素
-
- 3.1.1我们常常面对如下的业务场景
- 3.1.2 资源依赖
- 3.1.3 流量
- 3.2 故障发现
-
- 3.2.1 监控体系汇总
- 3.3 线上排除故障
-
- 3.3.1故障排除方法
- 3.3.2 故障排除一般需要掌握的技能-工具篇
-
- 3.3.2.1 IDEA 断点高阶
-
- 1.window快捷键:
- 2.断点类型与设置
- 3.断点控制
- 4.断点属性配置
- 5.断点状态
- 6.断点窗口操作
- 7.stream流调试
- 8.远程调试
- 9.生产力建议
1 生产故障分级规范概要
1.1 开篇
计算机是当今世界的命脉,你能看到的任何地方,计算机都在改变着世界,不论是传统的制造生产,医疗通讯。还是新兴的虚拟现实,无人驾驶汽车 等领域。过去的几十年,计算机硬件飞速发展,软件领域也是不断刷新着人们的想象。可以说,计算机学科复杂而且庞大,甚至有人说,不亚于物理学。
今天我们讨论的话题,线上事故分析,只是其中的一部分,一小部分,为了说清楚这一点,我们简单了解一下软件工程学科。
玛格丽特·希菲尔德·汉密尔顿(英语:Margaret Heafield Hamilton,1936年8月17日-[ 1])被认为发明了软件工程一词。
她帮助了NASA在阿波罗计划中避免了严重问题。她曾这样说:“有点像牙根管治疗:你总是拖到最后才做,但有些事可以预先做好,有点像预防性体验,只不过是预防软件出错”。
我们不妨简单总结如何开发一个大型的软件项目下:
1-基于面向对象的编程语言
2-容易使用的集成开发环境
3-文档和注释(程序员最讨厌的两件事,写注释给别人读,阅读别人没有写注释的代码??)
4-构建管理和版本控制
5-质量保证测试(QUALITY ASSURANCE-QA)
每个软件从业者从写下第一行代码开始,就一刻不停地 和软件中的错误做斗争 开发和维护(修复缺
陷、确保资源充 足等保障软件运行的活动)是一对伴随软件运行而产生的双 热爱从零到一开发软件是
开发者的天性 看着自己编写的 软件完美运行,为其他 提供服务,一直是驱动开发者前进的动力。为了
更快更好地开发软件,我们不断改进开发方法和软件架构,但是开发者在使用新的方法和更复杂的架构
时,往往也会低估潜在的风险。
本课程话题,主要讨论质量测试上线后,运营环节期间的一些问题,当然,我们暂时并不界定事故的产
生到底是因为测试覆盖不全还是操作不当等,这某种程度体现着管理的方式问题。
1.2 事故等级定义
业务和产品的线上质量、是研发团队的生命线,也是支撑业务快速是错,小步跑的前置条件。
1.2.1 故障等级定义
故障等级定义,不同的业务形态,不同的公司团队,有不一样的划分标准,下表列举了一般常见的维度和标准
1.2.2 故障 告模板示例
模板参考
1.2.4 思考
- 为什么会发生这个问题/li>
- 为什么测试阶段没有发现/li>
- 为什么系统不能容错/li>
- 能不能更早发现问题/li>
- 解决过程能不能更快/li>
- 怎样防止类似的事情发现/li>
2 生产故障原因和分类
2.1 故障分类
- 代码bug:上线代码逻辑有问题,遇到特殊情况下,导致故障的情况
- 操作不当:线上配置或资源配置错误,操作不当,比如启动顺序不合理,初始化脚本不对,语法生产数据隔离混用等
- 系统级别软件bug:技术架构中使用到的任何OS,第三方类库,软件在特殊场景下,bug被处罚导致故障的情况。
- 突发流量:热点或突发事件,引发的瞬时流量超过日常峰值或成倍增长,造成性能下降或功能不可用问题
- 资源使用不均:整体产品线利用率不达标,但有些业务冗余度不足,导致资源不能正确合理使用容量预估不足:对个别业务核心池预估不足
- 络类:公 拥堵、丢包、专线、 络设备故障、ip被攻击(包括DNS被攻击)、IP被封、域名被封、 络软件BUG、业务部门使用不当、未及时扩容等
- 安全类:被攻击,漏洞被利用等问题,均归为此类
- 局方故障:ISP,根域名服务,电力,空调,光缆等外部单位故障导致的问题。
- 硬件故障:任何硬件非人为原因损坏导致的故障均归为此类
- 第三方合作公司或接口故障:项目依赖的第三方公司或接口故障
2.2 bug是可以完全避免的么了解
日常项目里中,站在开发者的角度:
- 大多数程序员会花费70%-80%时间调试,而不是在写代码,虽然现在有很好的工具能极大帮助程 序员防止和解决错误
- 另一个重要部分 给代码写文档
由于现在的需求越来越复杂,依赖的外部条件,技术组件也是越来越多,很多bug在所难免。但也有一些bug是不能被原谅的,所以养成良好的开发习惯,很重要。
【bug起源】:1945年9月9日,格蕾丝·赫柏(Grace Murray Hopper) 使用的Mark Ⅱ出现故障,导致工作无法进行。经过了近一天的检查,格蕾丝找到了故障的原因:继电器中有一只死掉的蛾子。蛾子被夹了出来。后来,”bug” (小虫) 和”debug” (除虫) 这两个本来普普通通的词汇成了计算机领域中特指莫明其妙的“错误”和“排除错误”的专用词汇而流传至今,而格蕾丝·赫柏也因此成了第一个发现“bug”的人。
另一方面,大名鼎鼎的 “千年虫”bug,也是由她带来的。当然,这也不全完全算作bug。
2.3 经典故障示例-了解
由软件Bug引发的18次重大事故 | 程序师 – 程序员、编程语言、软件开发、编程技术 (techug.com)
近年的CSDN600万用户信息泄露事件:CSDN 站六百万用户信息外泄-月光博客 (williamlong.info)
2018年github服务中断24小时11分钟事件:GitHub服务中断24小时11分钟事故分析 告 (qq.com)
2.4 混沌工程简介
混沌工程解决的问题:
要设计良好的系统需要考虑很多因素,比如可靠性、安全 性、可扩展性、可定制化、可伸缩性、可维护性、用户体验等。 为了更高效地支撑业务发展,越来越多的企业选择基于云服务 或云原生理念来构建平台。采用新思路和新技术必然会带来系统架构和组织结构的变革,引入风险因素。
如何通过实验证明生产环境下的分布式系统在面对失控条件的时候依然具备较强的“可观测性”和故障恢复能力呢就是混沌工程要解决的问题。
混沌工程和测试的区别:
混沌工程故障注入和故障测试在侧重点和工具集的使用上有些重叠 举个例子, Netflix 的很多混沌工程实验的研究对象都是基于故障注入来引入的。
混沌工程和其他测试方法的主要区别在于,混沌工程是发现新信息的实践过程,而故障注 入则是基于一个特定的条件、变址的验证方法。
混沌工程和故障注人本质上是思维方式上的不同 。故障 注人首先要知道会发生什么故障,然后一个一个地注人, 而在 复杂分布式系统中,想要穷举所有可能的故障,本身就是奢望 混沌工程的思维方式是主动去找故障,是探索性的,你不知道摘 掉一个节点、关掉一个服务会发生什么故障,虽然按计划做好了 降级预案,但是关闭节点时却引发了上游服务异常,进而引发雪崩,这不是靠故障注人或预先计划能发现的
一些混沌实验的输入样例:
模拟整个云服务区域或整个数据中心的故障
部分删除各种实例上的Kafka主题。
重新创建生产中发生的问题。
针对特定百分比的交易服务之间注入一段预期的访问延迟。
基于函数的混乱(运行时注入):随机导致抛出异常的函数。
代码插入:向目标程序添加指令和允许在某些指令之前进行故障注入。
时间旅行:强制系统时钟彼此不同步。
在模拟I/O错误的驱动程序代码中执行例程。
在 Elasticsearch 集群上最大化CPU核心。
混沌工程实验的机会是无限的,可能会根据分布式系统的架构和组织的核心业务价值而有所不同
混沌工程实现的四个步骤:
1.定义并测量系统的“稳定状态”。
首先精确定义指标,表明您的系统按照应有的方式运行。 Netflix使用客户点击视频流设备上播放按钮的速率作为指标,称为“每秒流量”。请注意,这更像是商业指标而非技术指标;事实上,在混沌工程中,业务指标通常比技术指标更有用,因为它们更适合衡量用户体验或运营。
2.创建假设。与任何实验一样,您需要一个假设来进行测试。
因为你试图破坏系统正常运行时的稳定状态,你的假设将是这样的,“当我们做X时,这个系统的稳定状态应该没有变化。”为什么用这种方式表达果你的期望是你的动作会破坏系统的稳定状态,那么你会做的第一件事会是修复问题。混沌工程应该包括真正的实验,涉及真正的未知数。
3.模拟现实世界中可能发生的事情,目前有如下混沌工程实践方法:模拟数据中心的故障、强制系统时钟不同步、在驱动程序代码中模拟I/O异常、模拟服务之间的延迟、随机引发函数抛异常。通常,您希望模拟可能导致系统不可用或导致其性能降低的场景。首先考虑可能出现什么问题,然后进行模拟。一定要优先考虑潜在的错误。 “当你拥有非常复杂的系统时,很容易引起出乎意料的下游效应,这是混沌工程寻找的结果之一,”
“因此,系统越复杂,越重要,它就越有可能成为混沌工程的候选对象。”
4.证明或反驳你的假设。将稳态指标与干扰注入系统后收集的指标进行比较。如果您发现测量结果存在差异,那么您的混沌工程实验已经成功 – 您现在可以继续加固系统,以便现实世界中的类似事件不会导致大问题。或者,如果您发现稳定状态可以保持,那么你对该系统的稳定性大可放心。
3 生产故障定位和解决流程
3.1 影响服务质量的因素
3.1.1我们常常面对如下的业务场景
- 大量无用业务逻辑
- sleep
- 循环里写查询
- 磁盘满了、影响到有磁盘写操作的接口
- 慢查询的SQL
- Redis中存在大key,带宽打满不知是哪些接口影响与被影响
- 队列堆积却不知哪些接口影响
- 流量放大系数评估全靠经验和看代码
3.1.2 资源依赖
- 接口依赖(内部服务、外部服务)
无法整体查看服务、接口、资源之间的依赖关系
没有很好的外部服务监控机制、无法统计依赖的服务质量 - 数据资源依赖(DB、Redis、Memcached、队列)
无法整体查看服务、接口、资源之间的依赖关系
容量评估及扩容标准全靠经验
出问题后仅能凭经验逐一排查、无法迅速定位到代码层面
完全依赖dba帮忙排查 - 服务器资源依赖 (负载、内存、 络 ······)
资源指标上升后、无法判断数值是常规上升还是资源异常
3.1.3 流量
- 大流量来袭时、无法整体感知流量状况
流量多大算大br> 核心业务是否收到影响br> 单一接口流量增加却未达到整体的告警线、导致无法感知
可视化是否实时 - 无法直观统计流量分布、无法查看具体每个接口的流量情况
- 容量评估时、流量放大系数全靠人为判断、对服务整体的放大系数无感知
3.2 故障发现
一个高可用的业务系统除了技术架构支撑之外,监控系统作为事中决策支撑和事后决策止损是必不可少的一部分
工具:Prometheus、Zabbix、Nagios、Open-Falcon、Pageduty等
3.2.1 监控体系汇总
监控体系分类:一般可分为:业务监控,系统级别监控, 络监控,程序代码监控,日志监控,用户行为分析监控,其他种类监控等
- 系统级别监控:主要跟操作系统相关的基本监控项
物理监控(对物理机或者容器的监控):存活、内存、cpu、load、硬盘(速率、使用率)、 络
活性检测:进程、端口
应用服务监控:jvm、gc、线程数
服务监控:rpc和http接口的qps、rt、错误码等
IDC,对 络状态的监控(交换机、路由器、防火墙,vpn)对于一个互联 公司必不可少,但是有很多时候又被忽略:例如:内 之间(物理内 ,逻辑内 ),外 ,丢包率, 络重传,延迟等等
- 日志监控
日志监控比较重要,所以一般单独管理和分类,日志不仅限于服务系统日志,对于很多专业化的运维工程师来说,需要采集的包括系统日志,设备日志,用户行为日志等等,后续可加工处理,(splunk,ELK)
常用监控图示
-
3.3.2 故障排除一般需要掌握的技能-工具篇
1-一般情况下,需要了解业务场景,千万不要第一时间着急解决bug,应先评断是否可以回滚,影响面大小,是否为上层提供服务,是否有数据异常。
2-应熟悉项目依赖的监控,学会看监控。
3-应熟练开发环境的断点排查与诊断,熟悉git,maven,idea的使用,分析如何复现线上故障。
4-线上排查故障的工具链(仅供参考)-随着课程慢慢补齐3.3.2.1 IDEA 断点高阶
1.window快捷键:
2.断点类型与设置
行断点(line breakpoints)
- 鼠标右键点击该断点图标 ,弹出该断点配置,会有Emulated、Method entry、Method exit选项,此选项是方法类型断点特有的。Emulated勾选中,会将方法断点优化成方法中第一条和最后一条语句的行断点,这样会优化调试的性能,因此在IDE中会默认选中,
- 异常断点分为两种,一种是Any Exception,任意Throwable异常被捕获或未被捕获就会触发断点,另一种是指定类型的异常及其该异常子类被捕获或未被捕获会触发断点,该类型断点图标
4.断点属性配置
鼠标操作:右键断点:More(Ctrl+Shift+F8)
- 表示是否启用该断点,选中表示启用,取消选中表示不启用。
Supend
- 当断点的 Suppend 属性被勾选,触发该断点时,会触发程序挂起,当该属性未选中时,程序触发该断点时,程序不会挂起,常用于输出一些表达式结果日志。
- 当断点的 All 属性被勾选,触发该断点时,会挂起所有线程
- 当断点的 Thead 属性被勾选,触发该断点时,只会挂起触发该断点的那个线程,不影响其他线程
- 当需要在不暂停程序的情况下记录一些表达式时(例如,需要知道一个方法被调用了多少次时),或者需要创建一个主断点,在击中后启用附属断点时,非暂停性断点是非常有用的。
实际生产实践中,可用于调试多线程并发的问题
Condition
- 可以输入一段能获得true或false的表达式,程序运行到断点处,且表达式条件为true才会触发断点
Log
- 下面三个属性选项经常配合 Suppend 属性一起使用,用于在不挂起的情况下,输出一些想要的日志信 息
- Breakpint hit message :控制台输出触发端点的日志信息,类似如: Breakpoint reached at
ocean.Whale.main(Whale.java:5) - Stack trace :输出触发断点时的堆栈信息
3-idea启动remote,并打断点调试
9.生产力建议
使用断点进行 “printf “调试
使用非暂停的日志断点,而不是在代码中插入打印语句。这为处理调试日志信息提供了一种更灵活和集中的方式。
场景:
所有需要打印的地方,生产上禁止 System.out.print();
调试无响应的应用程序
如果你的应用程序挂起,暂停会话,让调试器获得关于其当前状态的信息。然后你可以检查程序的状态并找出问题的原因。
场景:
项目启动卡死等处理
测试你的程序是否有并发性问题
发现多线程程序在并发方面是否健壮的一个好方法是使用断点,在碰到时只暂停一个线程。停止一个线程可能会揭示出应用程序设计中的问题,否则这些问题就不会显现出来。
计算保留的大小
对于每个类的实例,你可以计算它的保留大小。保留大小是指对象本身和它所引用的所有对象以及没有被其他对象引用的对象所占据的内存量。
这在估算重型单体或从磁盘上读取的数据(例如,复杂的JSON)的内存占用时,可能很有用。另外,在决定使用哪种数据结构时(例如,ArrayList与LinkedList),这也很有用。
在运行应用程序之前,确保在设置/首选项|构建、执行、部署|调试器中启用附加内存代理选项。
在查看类的实例时,右键单击一个实例并单击计算保留大小。
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!