mirror of
https://github.com/zhwei820/learn.lianglianglee.com.git
synced 2025-09-17 08:46:40 +08:00
721 lines
24 KiB
HTML
721 lines
24 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>11 黑白盒监控:系统功能与结构稳定的根基.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 分布式链路追踪实战.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/分布式链路追踪实战-完/01 数据观测:数据追踪的基石从哪里来?.md.html">01 数据观测:数据追踪的基石从哪里来?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/分布式链路追踪实战-完/02 系统日志:何以成为保障稳定性的关键?.md.html">02 系统日志:何以成为保障稳定性的关键?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/分布式链路追踪实战-完/03 日志编写:怎样才能编写“可观测”的系统日志?.md.html">03 日志编写:怎样才能编写“可观测”的系统日志?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/分布式链路追踪实战-完/04 统计指标:“五个九”对系统稳定的真正意义.md.html">04 统计指标:“五个九”对系统稳定的真正意义.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/分布式链路追踪实战-完/05 监控指标:如何通过分析数据快速定位系统隐患?(上).md.html">05 监控指标:如何通过分析数据快速定位系统隐患?(上).md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/分布式链路追踪实战-完/06 监控指标:如何通过分析数据快速定位系统隐患?(下).md.html">06 监控指标:如何通过分析数据快速定位系统隐患?(下).md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/分布式链路追踪实战-完/07 指标编写:如何编写出更加了解系统的指标?.md.html">07 指标编写:如何编写出更加了解系统的指标?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/分布式链路追踪实战-完/08 链路监控:为什么对于系统而言必不可少?.md.html">08 链路监控:为什么对于系统而言必不可少?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/分布式链路追踪实战-完/09 性能剖析:如何补足分布式追踪短板?.md.html">09 性能剖析:如何补足分布式追踪短板?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/分布式链路追踪实战-完/10 链路分析:除了观测链路,还能做什么?.md.html">10 链路分析:除了观测链路,还能做什么?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
<a class="current-tab" href="/专栏/分布式链路追踪实战-完/11 黑白盒监控:系统功能与结构稳定的根基.md.html">11 黑白盒监控:系统功能与结构稳定的根基.md.html</a>
|
||
|
||
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/分布式链路追踪实战-完/12 系统告警:快速感知业务隐藏问题.md.html">12 系统告警:快速感知业务隐藏问题.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/分布式链路追踪实战-完/13 告警质量:如何更好地创建告警规则和质量?.md.html">13 告警质量:如何更好地创建告警规则和质量?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/分布式链路追踪实战-完/14 告警处理:怎样才能更好地解决问题?.md.html">14 告警处理:怎样才能更好地解决问题?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/分布式链路追踪实战-完/15 日志收集:ELK 如何更高效地收集日志?.md.html">15 日志收集:ELK 如何更高效地收集日志?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/分布式链路追踪实战-完/16 指标体系:Prometheus 如何更完美地显示指标体系?.md.html">16 指标体系:Prometheus 如何更完美地显示指标体系?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/分布式链路追踪实战-完/17 链路追踪:Zipkin 如何进行分布式追踪?.md.html">17 链路追踪:Zipkin 如何进行分布式追踪?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/分布式链路追踪实战-完/18 观测分析:SkyWalking 如何把观测和分析结合起来?.md.html">18 观测分析:SkyWalking 如何把观测和分析结合起来?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/分布式链路追踪实战-完/19 云端观测:ARMS 如何进行云观测?.md.html">19 云端观测:ARMS 如何进行云观测?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/分布式链路追踪实战-完/20 运维集成:内部的 OSS 系统如何与观测相结合?.md.html">20 运维集成:内部的 OSS 系统如何与观测相结合?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/分布式链路追踪实战-完/21 结束语 未来的监控是什么样子?.md.html">21 结束语 未来的监控是什么样子?.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>11 黑白盒监控:系统功能与结构稳定的根基</h1>
|
||
|
||
<p>上一节,我介绍了链路追踪除了观测链路,还可以聚合指标、绘制拓扑图、自定义链路和数据。前 10 节课我所讲的内容以白盒为主,这里我会对黑盒和白盒这两个概念做更系统的讲解,带你了解什么是黑/白盒监控,为什么它是系统功能与结构稳定的根基。</p>
|
||
|
||
<h3>什么是黑/白盒监控</h3>
|
||
|
||
<p><strong>黑盒监控指的是监控外部用户可见的系统行为</strong>,<strong>白盒监控指的是监控内部暴露出来的指标信息</strong>。它们一个对外,一个对内。二者在功能上有 2 点区别。</p>
|
||
|
||
<ol>
|
||
|
||
<li><strong>监控角度不同</strong>:<strong>黑盒更偏向于外侧</strong>,你可以理解为是通过某个功能或者具体的某个接口来观察,它并不清楚内部是如何实现的;<strong>而白盒则更倾向于从内侧监控</strong>,它是代码层面的,从内部的视角来解读整个系统。</li>
|
||
|
||
<li><strong>面向对象不同</strong>:<strong>黑盒更倾向于看到这个问题的现象</strong>,比如某个端口挂掉了无法再提供服务,它面向的是当下所发生的故障;<strong>白盒则更加倾向于面向产生问题的原因</strong>,比如我们在日志中可以通过堆栈信息分析出故障的根源。</li>
|
||
|
||
</ol>
|
||
|
||
<p>这里有一点我需要说明一下:<strong>白盒监控有时是面向问题,有时是面向问题的原因的,它的监控对象会根据监控的内容改变</strong>。假设白盒在接口层反映接口耗时比较长,此时可以认定白盒面向的是“耗时长”这一问题。但同时,白盒监控也会监控到与这个接口相关联的数据库出现了严重的慢查询。慢查询是接口耗时较长的原因,这时候我们就可以认定白盒是面向原因的。</p>
|
||
|
||
<h3>监控数据</h3>
|
||
|
||
<p>通过上面对黑/白盒监控概念的基本讲解,我相信你对它们已经有了一个基本的认识。下面我们再来讲讲它们监控的内容分别有哪些。</p>
|
||
|
||
<h4>黑盒监控</h4>
|
||
|
||
<p>黑盒中的监控一般可以细分为如下的 4 类内容。</p>
|
||
|
||
<ol>
|
||
|
||
<li><strong>端口状态</strong>:<strong>通过程序检测具体业务的端口是否存活</strong>。可以简单确定程序是否有在提供服务,如果端口都无法连接,那么肯定是系统出现了问题。通常我们也会结合进程检测使用,如果进程存活,但是端口不存在,则说明可能程序存在某些问题,没有将服务暴露出来。</li>
|
||
|
||
<li><strong>证书检测</strong>:<strong>通过检测证书是否有效,确认用户是否可以正常访问</strong>。现在的网站服务基本都是使用的 HTTPS,如果证书出现了问题,则可能是浏览器认定为不安全,阻止了用户访问。</li>
|
||
|
||
<li><strong>探活</strong>:<strong>通过心跳检测来判定服务是否存活</strong>,比如定期通过具体的某个接口检测我们的服务是否运行正常。如果在这里出现异常,则说明我们的系统存在问题。在 Dubbo 中就有心跳机制来保证双方的链接,这也算是一种探活。</li>
|
||
|
||
<li><strong>端到端功能检测</strong>:这个就相对复杂一些。<strong>通常是通过定期进行端到端的测试,结合业务流程感知业务是否在执行正常</strong>,比如我们可以通过 UI 或者接口自动化测试工具,来确认页面中返回的数据或者数据是否是正确的。</li>
|
||
|
||
</ol>
|
||
|
||
<p>了解了黑盒监控的内容后,不难看出,它其实更偏向确认功能是否可用。黑盒监控的理解门槛相对较低,即便是一个从来没参与过这个项目的开发人员,都可以对这些数据进行验证、确认。</p>
|
||
|
||
<h4>白盒监控</h4>
|
||
|
||
<p>白盒监控的范围其实我在 01 课时中就已经讲过了,01 课时中所学的 3 个环就是白盒监控中重要的数据维度:</p>
|
||
|
||
<ul>
|
||
|
||
<li><strong>日志</strong>:通过日志记录可以了解到程序的运行状态,程序中是否存在异常。</li>
|
||
|
||
<li><strong>指标</strong>:数值形式的指标可以帮助我们了解到系统中的数据走向、流量情况等。</li>
|
||
|
||
<li><strong>链路追踪</strong>:我们可以细粒度到程序的代码行级别来将链路可视化,这可以帮助我们了解程序的执行流程。</li>
|
||
|
||
</ul>
|
||
|
||
<p>在系统中,我们会大量运用白盒监控来查看问题或是分析问题产生的原因。那这样一来,是不是说黑盒就没什么用了呢?其实不是的。黑盒所监控的内容更偏向用户。比如当系统出现问题时,我们可以通过白盒查看到问题的原因,但是并不一定能够知道这个问题在用户那里是怎么表现的。如果由我们去想象,可能和真实的情况会有一定的出入,此时黑盒就可以展现出在用户端的真实表现形式。所以,黑盒和白盒之间并没有优劣的对比,它们各自有各自偏向的重点,将两者结合起来使用才是在监控中最有效的方式。</p>
|
||
|
||
<h3>黄金指标</h3>
|
||
|
||
<p>下面我要引入一个 <em><strong>Google SRE</strong></em> 中提出的一个概念:<strong>黄金指标</strong>。<strong>黄金指标是 Google 针对大量分布式监控的经验总结,它可以在服务级别帮助衡量终端用户体验、服务中断、业务影响等层面的问题</strong>,有 4 类指标信息,分为<strong>错误</strong>、<strong>延迟</strong>、<strong>流量</strong>和<strong>饱和度</strong>。无论你监控的数据再复杂、再令人眼花缭乱,都可以套用在这 4 类上。</p>
|
||
|
||
<p>下面我会把每个指标信息按</p>
|
||
|
||
<p>照<strong>基础监控</strong>和<strong>业务监控</strong>这两个维度来讲解。</p>
|
||
|
||
<ul>
|
||
|
||
<li><strong>基础监控,多指监控云主机、进程等机器信息,一般不代表服务的真实运行状况</strong>。比如在以集群方式部署的服务中,某台服务器中出现了一些问题,基础监控会报告这一台服务器的故障,但仅一台服务器的故障并不代表这个服务无法运行。</li>
|
||
|
||
<li><strong>业务监控,指的是监控业务系统内部的执行状态</strong>。通过业务监控,我们可以更多地了解到程序内部或者组件内部的执行情况。通常,我们会将基础和业务结合起来看,这样才能更全面地了解系统执行情况。</li>
|
||
|
||
</ul>
|
||
|
||
<p>下面,我会对这 4 类依次说明。</p>
|
||
|
||
<h3>错误</h3>
|
||
|
||
<p><strong>错误指的是当前系统所有发生过的错误请求</strong>,我们可以通过错误请求个数计算出相应的错误率。这个我想应该很容易理解,只要是程序运行,就肯定会因为某些原因而导致错误,可能是其他系统的组件导致的,也有可能是程序代码中自身的问题。</p>
|
||
|
||
<p>有 3 种比较常见的错误类型,我们这里以 HTTP 的接口举例:</p>
|
||
|
||
<ol>
|
||
|
||
<li><strong>显示错误</strong>:指<strong>可以立即看出来的错误</strong>。比如在 HTTP 请求中,响应状态码出现 500,则可以认定为是显示错误。</li>
|
||
|
||
<li><strong>隐式错误</strong>:指<strong>表面上显示完全正确,但是在数据中已经出现异常的错误</strong>。我在<strong>04 课时</strong>讲解 SLA 时提到,响应状态码为 200 可以认定为成功,但如果业务在返回的数据结构中被认定为是错误,那这个错误就是隐式的。</li>
|
||
|
||
<li><strong>策略导致错误</strong>:与第二种类似,都是<strong>在表面上显示正确,但是可能因为某种策略被认定为错误</strong>。比如某个接口在 1s 时返回,因为已经接收到了数据,所以被认定为成功。但我们的策略限制 500ms 内才算完成,因此这个数据会被记录为错误,这就是策略导致的。在 RPC 的提供者消费者模式中这个情况也很常见。</li>
|
||
|
||
</ol>
|
||
|
||
<p>那么从基础和业务的两个维度,我们如何来监控错误呢?<strong>在基础层中</strong>,我们可以把系统宕机、进程或者端口挂掉、网络丢包这样的情况认定为是故障。<strong>在业务层中</strong>,监控的内容也就相对比较多了,比如 Dubbo 调用出错、日志中出现的错误,都是可以被认定为“错误”的指标。具体的内容我在介绍日志、统计指标和链路追踪时都有介绍过。</p>
|
||
|
||
<h4>延迟</h4>
|
||
|
||
<p>**延迟指的是服务在处理请求时花费的时间。**我们经常说的接口耗时、响应时长指的就是延迟。在这里需要注意一点:<strong>一般在统计延迟时,并不会把成功或者错误的信息分开统计</strong>。这样的统计方式会使我们更难了解到真实的情况,所以在统计时常常需要把它们区分开。以一个 HTTP 接口为例,响应状态码正确的(200)和错误的(500)请求,它们的耗时一定会有差别,因为正确的请求走完了全流程,而错误的可能只进行了某一部分流程,我们就需要把这两个请求的耗时在统计时分别记录。</p>
|
||
|
||
<p><strong>在基础层中</strong>,我们可以监控 I/O 等待、网络延迟等信息。<strong>在业务层中</strong>,则可以监控接口调用的耗时、MySQL 查询的耗时等信息。</p>
|
||
|
||
<p>延迟在系统中是一个十分关键的指标,很多时候我们的服务并不会产生错误,但很可能会有延迟,延迟在 HTTP 层会影响用户体验,在数据库中出现高延迟会导致请求错误,这是我们需要着重关注的。</p>
|
||
|
||
<h4>流量</h4>
|
||
|
||
<p><strong>流量是表现系统负载情况的数据</strong>,比如我们常见的 QPS、UV。通过这个指标我们能确切了解到服务当前承受了多大的压力,请求量和处理量有多大。<strong>我们常说的容量规划,其实是流量规划</strong>。通过流量,我们可以得知当前系统运行的状况,是否到达了它的负荷上限。</p>
|
||
|
||
<p><strong>在基础层中</strong>,常见的监控指标有磁盘的读写速度、网络 I/O 情况等。<strong>在业务层中</strong>则有请求量、MySQL 查询次数等等。</p>
|
||
|
||
<p>通过观察流量相关的指标,可以了解到是否存在突增突降的情况,从而判断是否遭受到了攻击或者是否在进行某些活动。</p>
|
||
|
||
<h4>饱和度</h4>
|
||
|
||
<p><strong>饱和度通常是指某个资源的使用率</strong>。通常指的是我们通过容量的最大值和现在的使用量,来判断这个容量是否“满”了。某些程序,如果资源饱和度过高,可能会导致执行缓慢,甚至无法使用。比如 CPU 使用率如果达到 100%,会出现执行缓慢;Dubbo 进行 RPC 调用时,如果线程池没有可用的线程数,则会使业务受到阻碍。</p>
|
||
|
||
<p><strong>饱和度一般也会配合其他指标一起使用</strong>,比如在使用网络 I/O 时,网卡都是有流量上限的,我们通过流量上限值和当前网络 I/O 的使用情况,可以得知相应的饱和度。<strong>饱和度是衡量我们这个系统是否到达瓶颈的关键</strong>。如饱和度过高,这时候就需要考虑扩容、减少数据量或是其他降低饱和度的操作了。</p>
|
||
|
||
<p><strong>在基础层中</strong>,需要监控的指标有 CPU 使用率、I/O 使用率、句柄使用情况等。<strong>在业务层中</strong>则会有线程池的线程使用数、JVM 中的堆内存使用率等信息。</p>
|
||
|
||
<h3>结语</h3>
|
||
|
||
<p>在这一节中,我带你了解了什么是黑/白盒监控,并且了解了监控中的 4 大黄金指标。你在监控这些指标的时候发生过什么问题或是故事吗?欢迎在留言区分享。</p>
|
||
|
||
<p>可观测性原理我就讲到这里了。从下一节开始,我将带你了解告警体系与可观测性,把原理同告警体系相结合。</p>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<div>
|
||
|
||
<div style="float: left">
|
||
|
||
<a href="/专栏/分布式链路追踪实战-完/10 链路分析:除了观测链路,还能做什么?.md.html">上一页</a>
|
||
|
||
</div>
|
||
|
||
<div style="float: right">
|
||
|
||
<a href="/专栏/分布式链路追踪实战-完/12 系统告警:快速感知业务隐藏问题.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":"7099772a4d293cfa","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>
|
||
|