稳定性 问题定位[基于此监控系统] 系统优化[内部调用异常数据流量,基于此系统上的压测瓶颈发现]

自己的另外一篇:稳定性 耗时 gc 过长问题排查 和工具 http://www.cnblogs.com/fei33423/p/7800395.html

老的思考:稳定性 监控 业务后期 - 架构师 https://www.cnblogs.com/fei33423/p/7169590.html

总结:

     新的指标概念: 1. cpu 节区间 2. 耗时*请求量 3. 耗时 diff*请求量/平均耗时*总>1/5 provider 请求量 4.对方 provider (rpc 或者是)耗时统计 5.provider 线程池满拒绝异常 5. consumer- provider 耗时- ping 耗时(这样雪崩时,本系统不会报错) 6. 类似 traceId,有个全局的traceMethod. 这样就能知道是谁调用过来的.

       层级概念:

     去除报警指标: 1. provider 耗时,errno异常 2. consumer errno [下游系统provider_errno=consumer_errno] 3.consumer 耗时异常 4.割裂 traceId 的统计是无效的. 丢弃小米监控系统. 还要根据分位, 正态分布叠加还确立定位合适的traceId.

   

     动静,统计和 case 结合.

     指标: 耗时,请求量,错误量

     静: 绝对值.

     动: 环比,同比

     报警因果推断. 1. 只要有 trace 分段了. 耗时因果推断就简单了. 2.请求量 只要有了 traceMethod 就知道diff来源了. 3.  有个 traceError 就知道 appName_errCode

背景介绍:

      一次雪崩时: 查问题毫无头绪,到处都是抛错. 查来查去可能都是某个系统的问题. 那个系统呢,抽样查很多 flag ,很多都是调用外部的问题.

      原因: 下游系统从1ms 变成2ms, 就引发雪崩了. 说明该接口调用占比占整个入口占比的60%了.  调用该接口又用了一个无限队列线程池,快饱和了, 2倍后饱和,排队, 最终导致 dubbo provider 的线程池满. 导致其他接口无法调用该核心系统.

     后期防范: 系统占比较高的耗时节区间,需要特别注意. 排名: 耗时段的耗时 diff*次数/总 provider 耗时. [耗时节区间段概念见下文]

 问题梳理+案例说明:

    核心问题(梳理完知识体系后想到的): 带有 flag 的监控数据缺失.现有监控数据擦除了大量信息.

 新方案知识体系:

节区间:

      zipkin 监控中的节区间.

      复合节区间: 是指包含多个原子节区间的节点. 例如dubbo provider . 注意复合节区间的监控统计是宏观上考察用的,对问题分析排查无太大的意义.还有就是 consumer 的耗时. 这个耗时首先要关注provider 提供方的耗时,对方也是高的,那就是对方的责任.如果对方低,我方高,那么就应该好好研究研究了.

    对于 consumer 还有外部 io 节点: 1. 耗时增加异常 2. 耗时不增加但是非 success 调用.(fast-failure)

 节区间上承载的的信息种类(zipkin只有耗时信息):

1.  耗时

2. 接口调用量.

3. error code .

其他为用于分析原因的异常:

     1. 数量. cpu 占比 . 磁盘 io 数量. 网络 io 数量. 当时 swap 次数.

异常比较方式:

  1. 同比

            耗时多用同比,

      2. 环比

            数量多用环比.

3. 绝对值

  调用量远超过业务量,耗时也是远超正常值. cpu : 10ms consumer: 5000ms

统计层级:

1. 接口层级

      模块交互时的相关问题

两个 rpc 调用之间包含中间件代码,网络io.

  常规日志手段无法检测的

  1.1 隐匿在接口层,但是你获取不到时间的.例如: dubbo单连接复用 dubbo 连接池分发耗时. 可以通过代码注入改造. 现有的 java 性能耗时分析工具已经很多.

  接口监控可能需要改造的点,获得更多的节区间数据:

    1.  中间件间切面flag 日志
    2.  系统级切面 flag
    3.  中间件和系统级日志查看. 如果未收到监控系统中,就需要专家主动查看. 监控 list check表单.
    4.  gc日志监控

2. 比接口层级还低的层级. 只能通过非业务系统来调用监控了.

    比如通过ping,得到网络耗时情况. route .

    低层级的影响的是全局. 如果有这些数据,就可以反证全局影响不是这些因素照成的.有些"节区间"包含了 网络传输 和 中间件等无法监控统计的点.

       2.1 基于 byte 的 传输. 通过纯净无影响的ping来确定网络耗时. jvm 内,jvm 外. 2种. jvm 外的统计都有运维自己搞定.

       2.2 基于 byte 的 cpu 执行. 通过一段每隔10毫秒执行一次的纯净. jvm 内,jvm 外. 2种.

       2.2 基于 byte 的文件 io. 通过一段定时写入磁盘的 logger + file 操作.来统计纯洁的 io耗时表现. jvm 内,jvm 外. 4种.

       2.3 基于 byte的netty 的粘包,拆包.

监控展现:

   报警展现(有最小流量限制,统计样本有限不报警):

             两种展现类型 1.耗时异常展现 2.数量异常展现:

展现方式

拓扑图展现法:

整体拓扑图节区间( 可以用TWaver实现 )展现. 有节区间报警就显示在某个应用上,点击进去进入下一层级拓扑图. 如果是 consumser 的调用发起节区间. 那么就展现对应的机器连 接拓扑图.

          任何zipkin节区间都能属于最终整体拓扑图的点或者线.

列表展现法: 从大到小. 可以层层点入( 如果拓扑图有难度的话 ):

       接口级的展现: 如果节区间报警,把对应的 provider 的整体节区间展现出来. [对应拓扑图方式的是你得知道这个报警是属于哪个拓扑节点的]

           从面到点展现报警图. 点击某个最细粒度监控节后,

  1. 纵向对比,和自己比, 展现与之相关的各种统计数据,同比,环比量.

  2. 横向对比 和别人比, 同level 的其他节区间情况. 即同一个节点的其他 cpu 区间. [可能有些流量变化不大,但已经到了边界点, 要看具体代码来理解思考. 是否有阻塞,排队等.]

 note: 拓扑报警切记对复合节区间报警. 这是目前现有报警系统的大坑.

如何打印 zipkin 日志:

  1. 如果接口种不同的参数导致的耗时差别很大. 那么就需要根据不同的 type 来打印不同的日志,区分 consumer 接口.

  2.

 

Q&A

1. 如果遇到某个接口本身不同的分支导致耗时差别很大怎么办?

   1.1 可以通过接口参数区分出来

   1.2 无法通过接口参数区分. 不同的 userId 有不同的参数. 这种就没办法了. 不过问题也不是很大,只要数据量够大,平均值就比较稳定. 一旦异常,也会影响相关问题.

2.如何确定两个节区间是相同的节区间?

    例如 a b c c d 和 a c d . 这种需要技术处理内在子序列的概念.  其中 cd 就是重叠的. 或者大序列严格相等,子节区间从认为是相同的子节区间.这个不太好. 特别是在 service 层也打上 zipkin 标记的时候.

监控衍生产品:

  1. 通过现有数据库

  2. 通过状态变更时的日志

 

        

 (日志,采集,展示)监控,参照系异常抽取,关联清洗,优化,报警,报警关联清洗,定位五部曲. [目前监控系统,在日志,关联清洗上是缺失的]

 从表到里的分析过程.

 

 

 

何为异常:

     前提: 大流量下,稳定性才显得重要.否则不用关心. 这种业务平台也要有机会遇到.

     作用: 现有数据收集,展示,再有智能数据处理,最终告警,形成告警时间轴,并分析同时间内[分钟级]的告警点在整体监控点下的关系,排除非因告警点.

        1. 业务异常.  - 简单.

        2. 稳定性因素导致的异常.特别是雪崩时,很难排查.

2.1  耗时对比增加. 同比增加, 环比增加, 同期平均值增加,小流量平台对比.  [ ]

2.2  耗时超时变成 error

     按严重程度:

1. 大量error异常 [这个是老的监控平台优点,通过error查看flag,太迟了]

2. 无error异常 [ 接口耗时增加,io总量增加提前暴露性能问题,新监控平台小米优点. 通过报警时间轴去定位问题,最好报警阈值时时可调 ] 有时候只有几台机器异常. 

              这种极有可能 1. 某些 io 调用耗时增加(未监控) 2. 线程池满等待 3. dubbo tcp 复用等待 4.swap 耗时等待 5.gc 耗时 6. 线程加锁等待

      参照系: 大流量自身同期, 大流量自身环期. 正常的小流量平台下自身同期,自身环期. 两个比例. 1.平均放大比 放大比异常的.                   

    2.1 同比环比对比

同平台: 同比,环比;

             大小平台: 先取个平均放大值,然后放大值异常的报警]

           如果本身就抖动,那就先把抖动问题解决掉,  0.有些内部没有问题,来源于外部不同输入,数据库响应抖动,偶发性的请求冷数据. 1. 根据业务场景的业务配置 例如gc 2. 例如更换引擎 , 随机读太多,改用ssd 硬件架构. 3. 有些是外部系统导致的, 那就没办法了. 比如外部支付网络 只能取值40-60%这部分统计值作为平均考量. 或者换用供应商,多渠道控制. 也可以辅助外部人员本质上也要查,要看对应提供方的代码和日志,点问题,面问题, 可能需要服务提供方提供对应的数据,对应的 flag 的接收和返回的时间点.  并且要保证机器时钟的准确性.

所以好的设计是不依赖外部方,让外部放依赖我们. 限制调用量. 通知总是需要的,限制timeOut 时间.

            即使同一个接口,也要比对参数是否相同. 不同的人属性不同,走的逻辑和外部 io 路径不同. 可以对有限值的参数和耗时进行聚类,聚类完之后进行监控,然后进行监控.这就没法监控了. 这个 type 值最好是结构化的,有业务来确定,通过注解等方式,而不是从文本来解析出来.这种解析太多了.

3. 压测异常. 压测突破边界点, 耗时边界点,导致增加的请求流量,全部变成了 error 异常, 故流量增加,但是正常返回反而下降.

     那么zipkin整个时间轴上的统计纬度有多少.

        说耗时: A -->  B 接口名.  from纬度比较 其他参数相同, to纬度比较, time纬度比较(同比,环比) 大流量和小流量比较.

     不同的接口名比较没意义,不同的 内存执行区间比较也没意义(而且重构了,有可能变化很大. 只能同一时间点比较,前后比较)

     同期比异常:  流量异常, 耗时异常,请求数量异常

              原因: gc导致偶发[和swap一起时耗时更长, 大内存耗时也长], 营销活动导致偶发.

                      边界: 1. 内部线程池边界[订单因为下游耗时增加,导致线程池耗尽,新的请求排队 fastError ],  2.有效耗时边界[ timeOut , 直接fastError], 3. io边界[dubbo 连接共用,导致定时任务时,突然导致连接满额, 导致无法可用] 4. mysql线程池耗满 [ 有慢查,就挂了. ]

     环比异常: 定时任务,gc,定点营销,催款短信

 

方法论: 

     监控+及早报警:

    • 通过zipkin耗时优化问题. 及早发现及早优化.
    • 通过调用数量优化问题
    • 通过压测发现问题.
      • 压测能突破边际,本来只是耗时增加的,后来演变成 exception 抛出
      • bean 数量也能极大放大,便于定位

    最细粒度报警. fromIp 接口 toIp. 内存执行报警. 对gc监控有用. 外部都不变,但是内部变化了. 有时候监控报警不全,需要自己在去排查.

    1. 大面积报警

          报警顺序排放.

    2. 少部分报警

场景 :

      1.  观察线上耗时统计, 发现间歇性耗时抖动? [之前写的例子,犯了 复合节区间的大忌. ]

      2.  更甚至直接导致oom

      雪崩分析时要看异常报警时间轴, 和平时抖动性分析 需要看 异常报警时间轴,异常同比/环比抖动超过20%的图.

    压测,稳定性建设分析看整个链路耗时情况. 特别是异常抖动点的耗时情况,流量情况,io 情况.

分析:

   * 报警信息

         报警计算方式:

                同比(雪崩等),环比(抖动,毛刺,斜率超过多少就算毛刺. 何为毛刺?,稳定性排查  )

   报警计算阈值动态配置:

                这些信息可以时时调整报警额度值,动态计算一遍,然后展现) 按同粒度+上下游的时间轴展现

      * 报警信息分类:

    * 耗时抖动报警

            * 流量抖动报警

             * io 超量报警

             * 异常码 error 报警

     * 点

    接口维度: 流量大小,耗时,次数. 且要有流量入口 type,这个最好有前缀是app_入口_app 名_接口名[].

         zipkin 时间轴,能够很快的识别出 网络耗时, 内部执行耗时,外部 io 耗时 这些都是关键的 耗时 key.  [所以一定要把 mysql, dubbo, 文件操作都监控起来. 不然有些耗时 key 可能是混合了 内存执行+外部io执行]

         内部的内存耗时如何统计?

        通过 zipkin 的sr (server 接受) 和 cs(客户端发送)的时间差来定义.  cs-cr (两个流量中间)这个需要有框架来完成. 特别是内部出现多线程的情况.

   一个大系统由 N 个小业务系统组成, 虽然大系统找原因,拆解到各个小业务系统上. 雪崩时定位出各个系统的初始异常原因. 然后切换到下游系统或者面原因定位. ( 所以不如整体定位, 不对粗粒度的分析.)

       优点:  以往只有系统级的监控(), 有了接口级的以后就好定位很多. 但是内存操作怎么定位?

     * 面

          外部网络, 内部gc ,磁盘问题,网络

     * 另外一种是达到耗时边界, 耗时可能只增加了20ms,但是已经超过1s 中. 导致 error 报警.这种需要平时稳定性治理,耗时从高到低排查问题.耗时到底在哪里?

     * 时间点刚好是定时任务执行点

     排查代码,看是否有优化空间

     * 规律性不明显

             查看是否 gc 导致? gc 耗时过长原因是 swap http://lovesoo.org/linux-sar-command-detailed.html sar -W  https://blog.csdn.net/rlhua/article/details/24669037

相关工具和命令:

    可视化 gc 和耗时时间轴.

效果 :

1. jmap -histo 46454 | head -n 20

要判断系统瓶颈问题,有时需几个 sar 命令选项结合起来

怀疑CPU存在瓶颈,可用 sar -u 和 sar -q 等来查看

怀疑内存存在瓶颈,可用 sar -B、sar -r 和 sar -W 等来查看

怀疑I/O存在瓶颈,可用 sar -b、sar -u 和 sar -d 等来查看

 

posted @ 2017-11-08 17:29  fei33423  阅读(899)  评论(0编辑  收藏  举报