mirror of
https://github.com/zhwei820/learn.lianglianglee.com.git
synced 2025-09-30 07:06:42 +08:00
413 lines
32 KiB
HTML
413 lines
32 KiB
HTML
<!DOCTYPE html>
|
||
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
|
||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||
<head>
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
|
||
<link rel="icon" href="/static/favicon.png">
|
||
<title>37 遇到线上故障,你和高手的差距在哪里?.md.html</title>
|
||
<!-- Spectre.css framework -->
|
||
<link rel="stylesheet" href="/static/index.css">
|
||
<!-- theme css & js -->
|
||
<meta name="generator" content="Hexo 4.2.0">
|
||
</head>
|
||
<body>
|
||
<div class="book-container">
|
||
<div class="book-sidebar">
|
||
<div class="book-brand">
|
||
<a href="/">
|
||
<img src="/static/favicon.png">
|
||
<span>技术文章摘抄</span>
|
||
</a>
|
||
</div>
|
||
<div class="book-menu uncollapsible">
|
||
<ul class="uncollapsible">
|
||
<li><a href="/" class="current-tab">首页</a></li>
|
||
</ul>
|
||
<ul class="uncollapsible">
|
||
<li><a href="../">上一级</a></li>
|
||
</ul>
|
||
<ul class="uncollapsible">
|
||
<li>
|
||
<a href="/专栏/软件工程之美/00 开篇词 你为什么应该学好软件工程?.md.html">00 开篇词 你为什么应该学好软件工程?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/01 到底应该怎样理解软件工程?.md.html">01 到底应该怎样理解软件工程?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/02 工程思维:把每件事都当作一个项目来推进.md.html">02 工程思维:把每件事都当作一个项目来推进</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/03 瀑布模型:像工厂流水线一样把软件开发分层化.md.html">03 瀑布模型:像工厂流水线一样把软件开发分层化</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/04 瀑布模型之外,还有哪些开发模型?.md.html">04 瀑布模型之外,还有哪些开发模型?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/05 敏捷开发到底是想解决什么问题?.md.html">05 敏捷开发到底是想解决什么问题?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/06 大厂都在用哪些敏捷方法?(上).md.html">06 大厂都在用哪些敏捷方法?(上)</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/07 大厂都在用哪些敏捷方法?(下).md.html">07 大厂都在用哪些敏捷方法?(下)</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/08 怎样平衡软件质量与时间成本范围的关系?.md.html">08 怎样平衡软件质量与时间成本范围的关系?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/09 为什么软件工程项目普遍不重视可行性分析?.md.html">09 为什么软件工程项目普遍不重视可行性分析?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/10 如果你想技术转管理,先来试试管好一个项目.md.html">10 如果你想技术转管理,先来试试管好一个项目</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/11 项目计划:代码未动,计划先行.md.html">11 项目计划:代码未动,计划先行</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/12 流程和规范:红绿灯不是约束,而是用来提高效率.md.html">12 流程和规范:红绿灯不是约束,而是用来提高效率</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/13 白天开会,加班写代码的节奏怎么破?.md.html">13 白天开会,加班写代码的节奏怎么破?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/14 项目管理工具:一切管理问题,都应思考能否通过工具解决.md.html">14 项目管理工具:一切管理问题,都应思考能否通过工具解决</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/15 风险管理:不能盲目乐观,凡事都应该有B计划.md.html">15 风险管理:不能盲目乐观,凡事都应该有B计划</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/16 怎样才能写好项目文档?.md.html">16 怎样才能写好项目文档?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/17 需求分析到底要分析什么?怎么分析?.md.html">17 需求分析到底要分析什么?怎么分析?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/18 原型设计:如何用最小的代价完成产品特性?.md.html">18 原型设计:如何用最小的代价完成产品特性?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/19 作为程序员,你应该有产品意识.md.html">19 作为程序员,你应该有产品意识</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/20 如何应对让人头疼的需求变更问题?.md.html">20 如何应对让人头疼的需求变更问题?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/21 架构设计:普通程序员也能实现复杂系统?.md.html">21 架构设计:普通程序员也能实现复杂系统?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/22 如何为项目做好技术选型?.md.html">22 如何为项目做好技术选型?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/23 架构师:不想当架构师的程序员不是好程序员.md.html">23 架构师:不想当架构师的程序员不是好程序员</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/24 技术债务:是继续修修补补凑合着用,还是推翻重来?.md.html">24 技术债务:是继续修修补补凑合着用,还是推翻重来?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/25 有哪些方法可以提高开发效率?.md.html">25 有哪些方法可以提高开发效率?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/26 持续交付:如何做到随时发布新版本到生产环境?.md.html">26 持续交付:如何做到随时发布新版本到生产环境?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/27 软件工程师的核心竞争力是什么?(上).md.html">27 软件工程师的核心竞争力是什么?(上)</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/28 软件工程师的核心竞争力是什么?(下).md.html">28 软件工程师的核心竞争力是什么?(下)</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/29 自动化测试:如何把Bug杀死在摇篮里?.md.html">29 自动化测试:如何把Bug杀死在摇篮里?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/30 用好源代码管理工具,让你的协作更高效.md.html">30 用好源代码管理工具,让你的协作更高效</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/31 软件测试要为产品质量负责吗?.md.html">31 软件测试要为产品质量负责吗?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/32 软件测试:什么样的公司需要专职测试?.md.html">32 软件测试:什么样的公司需要专职测试?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/33 测试工具:为什么不应该通过QQ微信邮件报Bug?.md.html">33 测试工具:为什么不应该通过QQ微信邮件报Bug?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/34 账号密码泄露成灾,应该怎样预防?.md.html">34 账号密码泄露成灾,应该怎样预防?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/35 版本发布:软件上线只是新的开始.md.html">35 版本发布:软件上线只是新的开始</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/36 DevOps工程师到底要做什么事情?.md.html">36 DevOps工程师到底要做什么事情?</a>
|
||
</li>
|
||
<li>
|
||
<a class="current-tab" href="/专栏/软件工程之美/37 遇到线上故障,你和高手的差距在哪里?.md.html">37 遇到线上故障,你和高手的差距在哪里?</a>
|
||
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/38 日志管理:如何借助工具快速发现和定位产品问题 ?.md.html">38 日志管理:如何借助工具快速发现和定位产品问题 ?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/39 项目总结:做好项目复盘,把经验变成能力.md.html">39 项目总结:做好项目复盘,把经验变成能力</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/40 最佳实践:小团队如何应用软件工程?.md.html">40 最佳实践:小团队如何应用软件工程?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/41 为什么程序员的业余项目大多都死了?.md.html">41 为什么程序员的业余项目大多都死了?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/42 反面案例:盘点那些失败的软件项目.md.html">42 反面案例:盘点那些失败的软件项目</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/43 以VS Code为例,看大型开源项目是如何应用软件工程的?.md.html">43 以VS Code为例,看大型开源项目是如何应用软件工程的?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/44 微软、谷歌、阿里巴巴等大厂是怎样应用软件工程的?.md.html">44 微软、谷歌、阿里巴巴等大厂是怎样应用软件工程的?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/45 从软件工程的角度看微服务、云计算、人工智能这些新技术.md.html">45 从软件工程的角度看微服务、云计算、人工智能这些新技术</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/一问一答第1期 30个软件开发常见问题解决策略.md.html">一问一答第1期 30个软件开发常见问题解决策略</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/一问一答第2期 30个软件开发常见问题解决策略.md.html">一问一答第2期 30个软件开发常见问题解决策略</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/一问一答第3期 18个软件开发常见问题解决策略.md.html">一问一答第3期 18个软件开发常见问题解决策略</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/一问一答第4期 14个软件开发常见问题解决策略.md.html">一问一答第4期 14个软件开发常见问题解决策略</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/一问一答第5期 22个软件开发常见问题解决策略.md.html">一问一答第5期 22个软件开发常见问题解决策略</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/学习攻略 怎样学好软件工程?.md.html">学习攻略 怎样学好软件工程?</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/特别放送 从软件工程的角度解读任正非的新年公开信.md.html">特别放送 从软件工程的角度解读任正非的新年公开信</a>
|
||
</li>
|
||
<li>
|
||
<a href="/专栏/软件工程之美/结束语 万事皆项目,软件工程无处不在.md.html">结束语 万事皆项目,软件工程无处不在</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
|
||
<div class="sidebar-toggle-inner"></div>
|
||
</div>
|
||
<script>
|
||
function add_inner() {
|
||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||
inner.classList.add('show')
|
||
}
|
||
function remove_inner() {
|
||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||
inner.classList.remove('show')
|
||
}
|
||
function sidebar_toggle() {
|
||
let sidebar_toggle = document.querySelector('.sidebar-toggle')
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
let content = document.querySelector('.off-canvas-content')
|
||
if (sidebar_toggle.classList.contains('extend')) { // show
|
||
sidebar_toggle.classList.remove('extend')
|
||
sidebar.classList.remove('hide')
|
||
content.classList.remove('extend')
|
||
} else { // hide
|
||
sidebar_toggle.classList.add('extend')
|
||
sidebar.classList.add('hide')
|
||
content.classList.add('extend')
|
||
}
|
||
}
|
||
function open_sidebar() {
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
let overlay = document.querySelector('.off-canvas-overlay')
|
||
sidebar.classList.add('show')
|
||
overlay.classList.add('show')
|
||
}
|
||
function hide_canvas() {
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
let overlay = document.querySelector('.off-canvas-overlay')
|
||
sidebar.classList.remove('show')
|
||
overlay.classList.remove('show')
|
||
}
|
||
</script>
|
||
<div class="off-canvas-content">
|
||
<div class="columns">
|
||
<div class="column col-12 col-lg-12">
|
||
<div class="book-navbar">
|
||
<!-- For Responsive Layout -->
|
||
<header class="navbar">
|
||
<section class="navbar-section">
|
||
<a onclick="open_sidebar()">
|
||
<i class="icon icon-menu"></i>
|
||
</a>
|
||
</section>
|
||
</header>
|
||
</div>
|
||
<div class="book-content" style="max-width: 960px; margin: 0 auto;
|
||
overflow-x: auto;
|
||
overflow-y: hidden;">
|
||
<div class="book-post">
|
||
<p id="tip" align="center"></p>
|
||
<div><h1>37 遇到线上故障,你和高手的差距在哪里?</h1>
|
||
<p>你好,我是宝玉。在软件上线后,发生线上故障是一个常见的问题,但怎样对线上的故障进行处理,却很能反映出新手和高手程序员的差距。对于团队来说,如何应对线上故障,也同样能反映出线上运维水平的高低。</p>
|
||
<p>今天,我将带你一起分析一下,新手和高手在应对故障时有什么不同?大厂在处理线上故障时,有哪些可以学习借鉴的地方。</p>
|
||
<h2>遇到线上故障,新手和高手的差距在哪里?</h2>
|
||
<p>在这里,我把新手在处理线上故障遇到的一些常见问题列一下,同时,我们也一起分析下,高手是怎么处理这些问题的。</p>
|
||
<h4>新手遇到复杂的线上故障,不知道该怎么下手</h4>
|
||
<p>对于线上故障,有的很简单,从界面或者错误日志上可以直观地看到问题在哪,从而也好找到方法去解决。但有的故障,却没办法直观地看出原因,比如说内存一直在涨,CPU 居高不下,遇到这种复杂的故障,通常新手就不知道该怎么下手了。</p>
|
||
<p>而对高手来说,会在实践中总结一套自己解决问题的步骤,遇到问题,会按照解决问题的步骤有条不紊地去分析和解决。(比如说 caoz 的这篇<a href="https://mp.weixin.qq.com/s?__biz=MzI0MjA1Mjg2Ng==&mid=2649867038&idx=1&sn=8924a2a7b51f57f983b24445812f29c5&chksm=f1075973c670d06547a8f7ad6eb687bfd78fb32894321b5519c1e982b4f7d31d23bb3a2e9fbc&scene=0#rd">出了 bug 怎么办</a>,就充分体现了一个高手的水平。)通常通过下面这样的步骤:</p>
|
||
<ul>
|
||
<li>
|
||
<p>第一步,评估影响范围;</p>
|
||
</li>
|
||
<li>
|
||
<p>第二步,试图重现问题;</p>
|
||
</li>
|
||
<li>
|
||
<p>第三步,临时方案和终极方案;</p>
|
||
</li>
|
||
<li>
|
||
<p>第四步,风险评估及持续优化。</p>
|
||
</li>
|
||
</ul>
|
||
<p>如果你还记得专栏文章《28 软件工程师的核心竞争力是什么?(下)》里的内容,就会发现,其实这本质就是一种解决问题的能力。一步步分析、解决和预防问题。</p>
|
||
<p>从新手到高手,可以从借鉴像这样的方法开始,然后在实践中不断总结经验,形成一套自己的分析问题、解决问题的方法。</p>
|
||
<h4>新手遇到线上故障,会想着马上修复 Bug</h4>
|
||
<p>当发现 Bug 后,尤其是自己的 Bug,很多开发人员马上就想到了 Bug 的修复方案,迫不及待就要去写代码打补丁了。然而这样做的问题就是,匆忙之间打补丁,如果没有经过充分的测试,可能会引入新的 Bug,甚至是更严重的 Bug。如果要充分测试,那么意味着时间会比较长,而线上故障的时间越长,可能意味着损失也越大。</p>
|
||
<p>而对于高手来说,会首先对故障进行评级,看对用户的影响范围,如果是核心业务,大面积影响用户,那么当务之急是恢复生产,然后再考虑如何去修复 Bug。</p>
|
||
<p>恢复生产并不一定需要修复 Bug,可以用一些临时性的方案,比如说回滚系统到上一个稳定的版本;重启服务看是否能恢复正常。当然在恢复之前,还要尽可能保留当时的日志、故障场景的截图、内存的 Dump(把当前内存数据保存的静态文件)等信息,用来后续查找故障原因使用。</p>
|
||
<p>遇到线上故障,新手需要时刻牢记:恢复生产、降低损失是第一要务,修复 Bug 是其次的。</p>
|
||
<h4>新手遇到线上故障,不知道如何快速定位到 Bug 在哪</h4>
|
||
<p>在临时恢复业务后,还是需要找到 Bug 在哪,后续才能从根本上解决。对于比较复杂的线上故障,新手通常不知道从哪里下手,看日志看代码都看不出所以然,而高手却总能快速地定位到 Bug 在哪。</p>
|
||
<p>高手快速定位 Bug 在哪,关键在于通过有效的手段,逐步缩小问题范围,直到找到 Bug 在哪里。</p>
|
||
<p>比如说,一种常见手段就是先重现 Bug,因为有了重现的步骤,就等于将问题的范围,缩小到重现 Bug 的这几步操作相关的代码上,就很容易发现问题在哪。</p>
|
||
<p>还有一种手段就是分析错误日志,通过错误日志,可以马上定位到错误在哪里。所以对于平时写程序,无论是客户端还是服务端,注意收集错误日志是非常重要的,可以帮助你在排查问题的时候节约不少时间。</p>
|
||
<p>还有一些不能重现的 Bug,则不是那么容易发现,其实也可以按照缩小问题范围的思路来定位。</p>
|
||
<p>比如说,Bug 是在最近一次部署后发现的,并且回滚部署后就恢复了正常,那么就说明问题很可能是由于这一次部署和上一次部署之间的代码变更导致的,如果代码变更不多,就可以通过分析变更的代码来定位。</p>
|
||
<p>像内存泄漏或者 CPU 高的问题,一般就可以通过分析内存 Dump 文件,分析当前是哪些线程占用资源多,线程运行的代码是什么;哪些变量占用资源多。从而可以缩小范围,快速发现问题在哪。</p>
|
||
<p>排除法也是一种缩小范围的方法,尤其是在架构比较复杂的情况,一次用户请求的操作可能经过多个服务,如果配合日志,那么可以对一个请求经过的每一个服务都进行日志分析,对于正常的服务可以逐一排除,直到找到出问题的环节,从而可以缩小问题范围。</p>
|
||
<p>所以下一次你在遇到难以定位的 Bug 的时候,也可以想想怎么样可以逐步缩小问题的范围,直到发现问题。</p>
|
||
<h4>新手解决完线上故障后,下次可能还会发生类似故障</h4>
|
||
<p>新手在遇到线上故障后,采用一些临时解决方案,比如说重启服务,发现恢复了,然后就把这事忘记了。对于线上的故障,如果不找到产生的原因,那么下一次还会发生类似的故障,甚至比以前还更严重。</p>
|
||
<p>高手对于线上故障,会仔细分析 Bug 产生的原因,从根本上解决,避免类似的故障再次发生。</p>
|
||
<p>比如说,我以前所在的项目组,采用敏捷开发,每周一个 Sprint,每周会部署上线。但上线后经常会出现一些故障,导致在部署后就要回滚,或者再打补丁。</p>
|
||
<p>虽然每一次上线后的故障可能都不一样,但是如果仔细分析背后的深层次原因,还是因为上线前没有充分测试导致的。每周 3~4 天时间开发,1~2 天测试,来不及对程序进行充分的测试。所以我们后来从流程上改进,将一个 Sprint 内开发好的程序,在测试环境测试一周后再上线,这样调整后,极少出现线上故障。</p>
|
||
<p>有关上面案例中流程改进结果,可以参考专栏文章《07 大厂都在用哪些敏捷方法?(下)》中“一周一个迭代怎么保证质量?”的说明。</p>
|
||
<p>对于新手来说,每一次解决线上故障,同时也是一次学习和总结的机会,不仅是学习如何解决一个线上故障,还要学习解决一类的线上故障,避免类似的故障再次发生。</p>
|
||
<h2>大厂都是怎么处理线上故障的?</h2>
|
||
<p>在处理故障方面,可以看到新手和高手的差距。同样,如果你留心观察,会发现各个大厂,也都有一套自己线上故障处理的流程。(比如:<a href="https://book.douban.com/subject/26875239/">SRE:Google 运维解密</a>, <a href="https://yq.aliyun.com/articles/105551">阿里如何应对电商故障?</a>, <a href="">滴滴是如何高效率处理线上故障的?</a>)</p>
|
||
<p><img src="assets/de24d22dfe710baf651af9848ac1589a.png" alt="img" /></p>
|
||
<p>通过看这些大厂的故障处理流程,你会发现,大厂其实是把高手解决故障的方式,变成故障处理的流程和操作手册,并且通过反复地故障演习。不断练习和强化对故障处理的流程,让系统更健壮,让新手也可以快速上手,做到高效处理线上故障。</p>
|
||
<p>至于具体的处理流程,其实大同小异。</p>
|
||
<ul>
|
||
<li>首先,对故障进行评级。</li>
|
||
</ul>
|
||
<p>根据故障影响的范围,对故障进行评级,从而决定后续的处理方案。比如说 P0 是最严重最紧急的,可能是大面积服务瘫痪,影响大量用户,需要紧急处理;如果是 P5,可能只是用户体验相关的,晚一点处理也没关系。</p>
|
||
<ul>
|
||
<li>其次,要马上恢复生产,避免进一步损失。</li>
|
||
</ul>
|
||
<p>使用临时方案,恢复生产减少损失是第一位的。可以采用部署回滚、服务降级等处理手段。</p>
|
||
<ul>
|
||
<li>
|
||
<p>另外,要分析故障原因,修复故障。</p>
|
||
</li>
|
||
<li>
|
||
<p>最后,记录故障发生处理全过程,分析故障原因,提出后续改进方案。</p>
|
||
</li>
|
||
</ul>
|
||
<h2>大厂处理线上故障处理机制有哪些值得借鉴的地方?</h2>
|
||
<p>从流程看,大厂处理线上故障的机制似乎并没有什么特别的,那么有没有值得学习借鉴的地方呢?答案是肯定有的。</p>
|
||
<ul>
|
||
<li>故障报警和轮值机制</li>
|
||
</ul>
|
||
<p>你可以先思考一个问题:如果你所在项目组的系统出现线上故障,要多长时间可以恢复正常?怎么样可以做到最快的速度恢复?</p>
|
||
<p><strong>要做到最快速度处理线上故障,关键就是要让正确的人第一时间就可以去响应。正确的人就是对故障服务最熟悉的人,通常就是这个服务的开发人员。</strong></p>
|
||
<p>但让所有开发人员 7x24 小时随时待命也不现实,所以一般大厂会采用轮值的机制,比如说对于每个服务,每周要安排两个人值班,一个是主要的,出现故障第一时间响应;另一个人准备着,以防万一联系不上主要值班人员时可以顶替值班。</p>
|
||
<p>大厂都有一个报警系统,值班的那一周,值班人员手机要 24 小时开机,笔记本要随身携带,如果负责的服务出现故障,那么会在第一时间被报警系统呼叫。如果 15 分钟没有人响应,就会层层往上传递,值班开发人员没响应就呼叫经理,再是总监,VP,直到 CEO。</p>
|
||
<p>这套机制虽然被很多开发人员诟病良多,毕竟值班期间要随时待命,但确实是一套非常简单有效的机制,让最熟悉服务的开发人员第一时间去处理,可以帮助线上系统以最快的速度恢复服务。</p>
|
||
<ul>
|
||
<li>实战演习</li>
|
||
</ul>
|
||
<p>在我工作经历中,不止一次出现过数据丢失的情况,其实丢失数据前,都有完善的备份恢复方案和日常备份,然而这些备份恢复方案却从来没执行过,等到真正出问题,才发现这个方案完全是不可行的,日常备份也早已被破坏无法恢复,最终导致数据丢失。</p>
|
||
<p>如果日常对这些方案有演习,去实际测试一下,就不至于这么狼狈。实战演习就是频繁地对故障进行演练,来测试平时做的这些方案是不是真的可行,这样遇到真正的故障,才不至于手忙脚乱不知道如何应对。</p>
|
||
<p>其中最有名的就是 Netflix 的混乱猴子军团,Netflix 在亚马逊云上建立了一个叫做 Chaos Monkey(混乱猴子)的系统,这些猴子会在工作日期间随机杀死一些服务,制造混乱,来测试生产环境下的稳定性。</p>
|
||
<p>也有人把这样的实战演习叫“混沌工程”。</p>
|
||
<blockquote>
|
||
<p>混沌工程就像“疫苗”:注射少量潜在有害的异物以预防疾病,这种人为的“破坏”其实是有帮助的。混沌工程通过在技术系统中注入危害 (如延迟、CPU 故障或网络黑洞) 来建立这种免疫力,从而发现和修正潜在的弱点。<a href="https://mp.weixin.qq.com/s/cNI0V0poYX0XR8Zl6Z36fA?">以毒攻毒: Google、Amazon、Netflix 如何用混沌工程控制系统风险</a></p>
|
||
</blockquote>
|
||
<ul>
|
||
<li>日志记录和分析工具</li>
|
||
</ul>
|
||
<p>对于软件来说,线上出现问题,分析日志记录是最简单有效的定位问题方式。这就要求平时在开发的时候,就要注意对关键日志信息的记录,同时还要搭建像 ELK 或 Splunk 这样的日志分析系统,方便查询日志。</p>
|
||
<p>举个例子:一个 API 请求,出现了随机无法访问的故障,而这个 API 可能会经过 5-10 个服务,怎么快速定位是哪一个服务出现问题?</p>
|
||
<p>一个好的实践是这样的:</p>
|
||
<p>对于每一个请求,都会分配一个唯一的请求编号(requestId),在经过每一个服务的时候,都带上这个请求编号,每个服务都把这个请求的输入和输出记录下来,输入的 url 参数是什么?http 的 header 是什么?输出的状态码是什么,输出内容的大小是什么?如果出错,异常信息包括错误堆栈是什么?</p>
|
||
<p>当出现故障的时候,找到一个有问题的 requestId,根据这个 requestId 去日志分析系统查询相关的所有服务的日志,这样马上就可以看出来哪一个服务返回的结果是有问题的。</p>
|
||
<p>当然还有一些其他好的实践,例如说新功能上线时,灰度发布的策略。通过开关控制,先让一小部分用户使用,如果出现故障,马上关闭开关,避免影响。</p>
|
||
<p>大厂的这些线上故障处理预防的实践都是公开的,通过网上的一些文章或者他们技术人员在技术大会上的分享,你也可以从中了解和学习到很多。重要的是看这些实践的好处是什么,哪些是可借鉴到你的项目中的。</p>
|
||
<h2>总结</h2>
|
||
<p>今天带你一起学习了线上故障的处理。对于线上故障的处理,基本原则就是要先尽快恢复生产减少损失,然后再去查找原因,最后不要忘记总结复盘。</p>
|
||
<p>要做到最快速度处理线上故障,关键就是要让正确的人第一时间就可以去响应。正确的人就是对故障服务最熟悉的人,通常就是这个服务的开发人员。</p>
|
||
<p>要让你的故障响应流程在真正遇到故障时能起到作用,需要经常做故障演习,测试你的故障响应流程,测试你的系统在故障下的稳健性。</p>
|
||
<p>线上故障的分析,少不了对日志的记录和分析,平时在开发阶段就应该要注意对日志的记录,同时也可以搭建一套适合你项目的日志分析系统,在遇到故障时,能及时的通过日志定位到问题所在。</p>
|
||
<p>最后,保持学习大厂对这些线上故障处理的好的实践,应用到你的项目中。</p>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<div style="float: left">
|
||
<a href="/专栏/软件工程之美/36 DevOps工程师到底要做什么事情?.md.html">上一页</a>
|
||
</div>
|
||
<div style="float: right">
|
||
<a href="/专栏/软件工程之美/38 日志管理:如何借助工具快速发现和定位产品问题 ?.md.html">下一页</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
|
||
</div>
|
||
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"70997c8eca193cfa","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
|
||
</body>
|
||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
|
||
<script>
|
||
window.dataLayer = window.dataLayer || [];
|
||
function gtag() {
|
||
dataLayer.push(arguments);
|
||
}
|
||
gtag('js', new Date());
|
||
gtag('config', 'G-NPSEEVD756');
|
||
var path = window.location.pathname
|
||
var cookie = getCookie("lastPath");
|
||
console.log(path)
|
||
if (path.replace("/", "") === "") {
|
||
if (cookie.replace("/", "") !== "") {
|
||
console.log(cookie)
|
||
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
|
||
}
|
||
} else {
|
||
setCookie("lastPath", path)
|
||
}
|
||
function setCookie(cname, cvalue) {
|
||
var d = new Date();
|
||
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
|
||
var expires = "expires=" + d.toGMTString();
|
||
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
|
||
}
|
||
function getCookie(cname) {
|
||
var name = cname + "=";
|
||
var ca = document.cookie.split(';');
|
||
for (var i = 0; i < ca.length; i++) {
|
||
var c = ca[i].trim();
|
||
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
|
||
}
|
||
return "";
|
||
}
|
||
</script>
|
||
</html>
|