对于后端服务来说
指标最重要的就是
延迟 流量 错误 饱和度
我们把它叫黄金监控四个指标
延迟其实就是要通过延迟感知到这个服务的
比方我们可能会告诉业务方
我的接口大概95分位大概是多少耗时
这个之前在讲超时的时候也提到过
我们做延迟的监控
不要只看平均 我们要看看它的95分位 80分位
这个其实可以自己去定义
我们有时候也会把一个时间段的min max（最小值和最大值）
以及它的95分位的延迟给上报上
当然有些95分位
甚至可能是在Prometheus的服务当中去计算的
所以这个是第一
第二 流量
我要知道一个服务的QPS大概是多少
可能是一个时间窗口内
它的流量的变化情况
还有就是错误
我要知道每一个接口它到底是成功还是失败
如果我只有流量
虽然我知道它的整体的一个流量
以及知道它的延迟情况
但是其实还要关注它
内部业务码的报错情况
可能它是报A错误还是B错误
为什么突然A错误突然报得非常多
可能也对于分析也是非常有用的
最后是描述一个服务
它到底是否是满载 或者叫饱和度
这四个指标组成了一个微服务的黄金监控四个指标
我觉得非常重要的一定要考虑长尾问题
也就是我们经常提到的
你一定要看99线 95线
去找你的长尾的接口耗时是什么
因为这个有可能就会
成为你系统瓶颈的root cause（根本原因）
除此之外 我当时也遇到过问题
我们采集指标
它采集的就是我们刚才讲链路追踪的时候
它采集的是服务的foo方法的执行时间
它不代表网络的传输情况
所以我们指标口径要对齐
这个地方是有难度的
我们怎么做
我们上报的时候使用Prometheus来做指标收集
从服务端的视角看它的耗时
同时一定有很多人会漏掉
从客户端视角看到的某一个RPC的耗时情况
所以我叫它为Client/Server's view
就两个视角去看
一个是你作为服务提供者
你去看你的接口耗时是什么情况
对于一个服务的调用者
它的耗时情况是什么样
所以这几个相互的一结合
它才是一个完整的
我去PK的时候就可以看
我的服务端这个耗时是10毫秒
但是我的客户端看起来好像是30毫秒
所以是不是你的网络有问题
是不是因为你的client有GC
导致你的这种调用都会耗时变高
所以这个其实讲不清楚
但是你有两个维度的视角去对比的话
可以排除掉一些问题
我觉得是很重要的一个点
我们前面除了把这些指标给采集起来
但是还有一个很重要的事情
指标它应该是统一命名 有个统一规范的
因为有统一的规范 意味着你们公司内
各个部门 各个事业部C++ Java Go Python
各种语言上报的指标的名称都是一致的
那指标名称一致
然后口径一致
比方说30秒平均QPS是怎么算的
大家都是一样的
有了这些一致性之后
我就有办法做一个统一的监控的大盘
针对每一个微服务都是用这一套大盘
用这个仪表盘
为什么要这样做
因为我们在排查问题的时候
假设你是A部门的人
你如果切到B部门
又或者B部门On Call他不在或者找不着
你想通过运维去看他的监控的面板
或者你自己去看他监控面板的时候
发现他画的图 他的指标
跟你完全不一样 口径也不一致
有学习的成本和门槛
（需要）去了解他的监控到底是怎么画的
可以想象一下
如果都是后端服务
大家都是都是有一个基础的面板 基础的模板
那么这样的话 我去迁移看别的业务的时候
（对于）仪表盘 我们学习理解的难度
就变得非常低了
迁移到另外一个系统去看监控的时候
就不需要太有学习的一个门槛
所以这两个事情非常重要
我相信行业内一定也会出类似的
一些指标的命名规范
然后一些口径的命名规范 都会有
但我们当时其实是
按照Prometheus官方的给的一些建议
按照它的规范把这些指标
无论是C++ Go什么都是统一的
最后做了一个统一的大盘 就是这个
这个大盘里面其实还有几层含义
再想象一下
我们看一个仪表盘的时候
其实看一个服务
除了看我们刚才说的 延迟 流量 错误 和饱和度
其实你还会去看你服务所处的运行环境是什么样的
具体来说它的runtime的情况是什么样的
它所处的Docker 它的物理机是什么情况
所以我们最后把这些东西综合考虑
包含了一些什么呢
运行时的runtime的
Linux内核的kernel的一些监控
包含的就是我们服务层面的刚才说的
延迟 流量 错误 和饱和度
以及依赖资源的 我们叫Client/Server's view
就是client看到的调某一个RPC
我们也叫HTTP依赖服务 或者是RPC依赖服务
依赖的一些组件
能把这些东西全部关联起来 是非常重要的
在一个面板里面你可以全搞定所有事情
甚至你可以通过你用的Redis的IP和端口
就是比方说你查某一个Redis
你的服务查某个Redis
如果你能把这个IP或者这个DNS的名称
跟Redis的复杂的监控
因为你Redis肯定有单独的一个监控的仪表盘 对吧
你能在这个界面上把这个链接加上去
那么你点一下就可以跳转
其实也可以节省大量时间
对于Grafana放大的整个仪表盘的制作我就不展开讲了
但是我告诉你 尽可能把一个微服务
它关联的一些东西做到一个仪表盘
但是不要全部展开
你可以自己手动去找 手动自己去点
然后可能把依赖这些中间件
它丰富的监控面板的链接可以带上去
自动的关联起来
然后可以点一下跳转
这个是我要讲监控体系的最重要的一步
我们目前内部主要还是使用的Prometheus做指标的采集
使用Grafana来做仪表盘的制作和查询和展示
然后使用PromQL来做指标的计算
基本上还是围绕Prometheus加Grafana的体系去搭建的
我们刚刚说的微服务要采集类似的指标
其实对于所有涉及到网络
比方说cache DB 消息队列
我们都会把这些 延迟 流量 错误 饱和度
从server维度和从client维度两个维度
都会把它们的这些指标给收集起来
有个对照的话 其实看起来会非常方便
我们刚才讲的系统层面
我们系统层面一般来说对Linux内核
我们主要是看哪些
按照host就是把那些实例的一些
节点名字都会放进去 做一个这样的图
我们会出两种视图
一种是出每个hostname
每个hostname的CPU的一个情况
看看是不是有某一些离群的节点 CPU特别高之类的
这个是一个维度
另外我们还会做个汇总的CPU的维度
我看CPU的趋势也是非常方便的
所以这个是一个
然后还有内存 IO的情况 网络的情况
网络其实就是包含发包 收包
它的TCP的一些状态
CLOSE_WAIT TIME_WAIT有多少个
TCP/IP的一些状态
还有打开的文件 fd（文件描述符）
那么内核还有像上下文切换这些
都会做到内核和这个视图里面
但是它都是在一个面板里面的
还有runtime的话其实就是
各类GC的一些指标 内存的一些指标
这些可能包括blocking的一些指标
这些都会放到一块
对于Prometheus来说 我为什么会比较喜欢用
其实我们内部当时一开始是用的StatsD
我们是逐渐演进到Prometheus
StatsD我们当时遇到几个问题
第一它是push 就是来一个指标push一个
然后它好像是基于UDP的
所以当时有好多数据会丢失
另外它基于push的做法
对我们下游的压力
就是接收push的网关压力比较大
因为节点规模越来越大以后
push的性能是比较差的
Prometheus既支持push也支持pull
我们目前微服务的都基本上是pull
pull有什么好处呢
我们在内存里面
可以预计算或者是暂存一段时间
一拖的话其实是拖走一波指标
它不是一个一个地推出去的
这样的话性能可能会好一些
它虽然可能有一些延迟
但是它的的确确性能会更好一些
目前我们主要是用pull的方式
当然我们像物理机的一些状态
就是在上面去部署node exporter
比方说Redis也可能会部署node exporter
MySQL也可能会部署node exporter
可能会部署相应的中间件的exporter
然后它是通过push或者pull可能都有
来采集这些指标的
这是第一个
第二个 我们要做指标
其实还要关注它的监控
要做指标其实为了看指标
基于指标可能还要做报警
还有我们Go本身是有一些监控体系的
比方说我们的go tool pprof
go tool pprof其实很方便使用的
我们登到机器上敲一个go tool pprof
然后贴一个地址
贴一个HTTP接口
立刻可以采到一些采样的数据
形成一些火焰图
比方说内存调用的火焰图
可能是CPU调用的火焰图
去诊断内存的瓶颈或者是CPU的瓶颈的时候
都是非常方便的
但是我想给大家说的是
这些手动操作 尽可能把它变成自动化的
我们当时就做了一个后台
只要找到这个节点的IP或者hostname
然后点一下这个按钮 生成性能图或者火焰图
那么它过30秒以后自动就会把SVG的图给下载下来
或者说在Web浏览器上直接展示
其实可以节省大量的时间
你不需要自己手动再去搞
所以这些工作我建议你们在微服务的治理框架
或者治理平台里面去把这些功能做掉
这个是第一个
第二个是什么
我们刚说可以收集火焰图
所以我们线上其实都是把Profiling端口打开的
但是Profiling端口因为有风险 有一定危险性
所以我们是不对外网去路由可以转发进来的
我们都是只对外开放
同时提供一个很好用的UI 可以快速生成刚刚那些图
那么最后一个其实叫watchdog
这个其实也是很容易遗漏的
我们是不是曾经出现过
你的线上服务突然出问题了
还来不及让你各种去花时间排查
我们一般线上出问题第一反应是什么
尽快止损
不管你是重启也好 还是扩缩容也好
你一定要想办法保留一个现场 把流量摘掉
然后用一系列的工具去诊断它 发现它的问题
这是我们常见的操作
但是有时候的确它的一瞬间的现象转瞬即逝
有可能你没抓到
所以我们有一个叫watchdog的想法 叫看门狗
使用内存CPU作为信号量
比方说突然触发了load shedding
或者是内存可能飙得非常快 飙得非常高
它的整个斜率 增长率非常高
我们的watchdog进程内发现这个异常情况之后
它会自动自动去触发一个profiling
然后把这个数据dump保存到一个地方去
有时候这种转瞬即逝的现象
可能就被你的watchdog发现感知到
因为有时候现场是来不及把流量摘掉再去分析的
所以watchdog一定程度上能够减缓这个问题
就避免说你找不到这个问题
我觉得这个也是很好用的
当然我也见过有同学说每隔两分钟
干一个这样的事情 不断的去采
直到出这个问题的时候最终可以采到
这个成本就会高很多
我们其实是基于信号量
比方说高位的CPU高增长率的内存 自动去触发
这个其实是非常有用的一个点
关于指标这块我们基本上就讲完了
现在回过头来总结一下
日志解决的是明细的查询
链路追踪是解决性能问题 以及易故障点 热点
还有利用Trace ID和Span ID跟日志系统进行一些结合
指标其实是汇总的 我是看趋势的
这三个不同的维度
组成了微服务的可观察性
所以这三套系统在你运行中
在你发布后
或者是日常check list
巡检的时候都应该去关注
所以一旦发布一个系统
比如我灰度发布 预发布 加流量
有灰度发布加流量
这三个地方都要去关注 去check
有没有出现一些异常的情况
然后基于这三个 又可以分别去做报警和监控
做它的监控体系 这个其实非常重要的
因为你有了可观测性
基于它们去设计一些报警的阈值 再来做监控体系
所以这个是非常重要的
发版前 发版中 发版后 以及运行中
还有出事故的时候
这三个手段都能大大减少
我们出现问题的时候 它的故障恢复时间
所以这块请大家认真阅读
包括reference也提到了引用的一些文章
好 今天第10周我们就到这里了