中拔出溜的公司如何落地监控体系

本文探讨了在业务需求驱动下,如何在中拔出溜公司这样的传统软件企业中建立低成本、易实施的监控体系,重点关注日志、traceId接入、Loki+Promtail+Grafana组合以及基础设施监控的选择。作者强调了监控工具应符合实际需求,易于部署和运维,并提倡持续评估和优化的过程。
摘要由CSDN通过智能技术生成

又一项看似技术需求驱动,最终发现还是业务需求驱动的体系化建设。

1. 中拔出溜公司的特点

传统软件行业中技术团队的发展(现状篇)中我专门针对中拔出溜公司特点进行过系统阐述。但就今天的主题,我再针对性补充一下:

  1. 业务场景要求低。 这个是根因,之后介绍的一系列特点最终都能落回这一视角上。
    1.1 业务停止,系统重启,这些都不是事;而且系统基本就工作时间使用,其他时间还得被研发吐槽: 都下班了积极个毛线。
    1.2 出现了问题之后:都
    不要用系统了,我这日志翻看不过来(是的,研发人员都是登录服务器之后使用文本工具打开日志文件翻找原因的) —— 你想想, 只有其他操作都停止,我这边重放报错接口,错误日志的最后几条才会是我想要关注的。
    1.3 功能做出来就行,诸如系统稳定性,易操作性等非功能性需求无所谓啦。
  2. CRUD研发。上述背景下,对于相应研发的要求自然不会高,技术方面会CRUD堆代码就完事了,重点是业务知识和经验。至于什么微服务化那更多是业务/标书需求,别太认真。
  3. 无专业运维。就上面这个要求还要毛线的专业运维,研发和售后你们自己内部把相应职责分一下就完了。

以上背景之下,对于监控这种收益滞后的纯成本支出,肯定是能省就省:

  1. 优先级严重滞后,叠加上人员认知不足,一般情况下除了日志之外没有其他系统运行时的常驻监控手段。
  2. 即使日志这东西,也是"写的时候嫌麻烦,用到的那一刻才嫌少";当时赌咒发誓,事后就是"事情都过去了,你还纠缠有意思吗"
  3. 除此之外,其它的监控手段基本都被用成了事后监控,也就是接到用户反馈的问题(别问我为什么不是接到系统告警),三板斧用完发现还是没有头绪,才会病急乱投医地临时找一堆监控软件给装上。但往往是此刻问题已经发生,而最关键的"问题出现前后的监控数据"无法获取,这导致在面对一些偶发性问题时非常被动

2. 达成共识

传统软件公司对于监控的推进,其实最重要的是取得均衡,找到那个动态变化的平衡点

  1. 一开始各方对于监控毫无概念,只是限于当前出现的棘手问题迫切希望能够通过纳入某些新鲜事物(例如监控)来缓解困境。
  2. 这个时候你需要借助前期的大量积累和预演,能够在短期内帮助它们解决/至少让各方相信你的这步推进是让问题在向好的方向变化,如此在之后的合作中让对方愿意遵从你的建议做出一些改变,最终进入一个改进计划稳定迭代优化的良性发展中。(这一点不仅仅针对监控体系的落地)
  3. 而这里面非常重要的一点就是你的方案不能要求对方对自身现状做出过多的调整和适应 —— 直接给出一个粗略的标准就是:这样的要求每多一条,推进成功率下降30%,起步阶段最好是对方不需要任何改动。毕竟对方直到现在都对监控投入不多,那说这一块并没有那么痛。在他们目前的认知里,当前属于极端情况,偶尔一两次可以接受。

我们的终极目标是在尽量少的团队阻力之下,以尽量低的成本,维持一个能够长期运行的监控体系,加快问题排查效率,增强系统稳定性,最终增加研发人员的工作价值感,幸福感。而这需要多方面努力,除了技术本身,团队现状,业务场景需求等等的考量更重要。

3. 推荐落地路线

3.1 理论解析

a. 监控的用途
抛开照本宣科地给出一大段监控或可观测性的基本定义,这里我更愿意给出自己对于"中拔出溜的公司"这个一限定条件下,对于监控功能的理解 —— 主要分两大块:

  1. 尽快解决发现的问题。 被告知问题发生之后能够快速介入、定位、解决,实现高效排错。
    1.1 这个时间越短越好。
    1.2 这个在标准理论体系下意味着一个专有名词: MTTR (Mean Time To Repair,平均修复时间),指系统从发生故障到维修结束之间的时间段的平均值。(这里我们暂时将系统问题发生时间和被发现时间等同)
  2. 借助统计分析和专家知识挖掘系统里隐藏在海面之下的冰山。
    2.1 相较于上面的"排错已知问题",这应该才是监控的更大价值体现。
    2.2 可惜对于业务导向的"中拔出溜公司"而言,因为项目周期等原因,对于这一块的重视基本等同于零。

b. 监控的五个层级

  1. 端监控。 即客户端,例如APP,浏览器等。
  2. 业务层监控。 例如QPS,每日订单量,每日注册用户数量等。
  3. 应用层监控。应用监控。例如JVM,链路追踪等。(本场景下的重点)
  4. 中间件监控。MQ,Mysql,redis等等。(本场景下的次重点)
  5. 系统层监控。CPU,网速,磁盘IO,内存等等。(本场景下的次重点)

c. 可观测性的三支柱

  1. Log。(本场景下的重点)
  2. Trace。(本场景下的次重点)
  3. Metrics 。 “通过查看和分析高维度和高基数数据,发现埋藏在复杂系统架构中的隐藏问题,而且不需要事先预测问题可能发生在哪里,以及问题发生的模式”

本小节接下来的部分我就给出自己多年实践后的思考总结 - 起步三板斧:

  1. 从日志入手,辅助进行问题排查,以及尽力而为的Metrics。
    1.1 因为日志的普及性(相关人员即使再想偷懒,出于自身利益考虑他也得打印一些系统运行日志),所以将日志作为监控落地起步的第一阶段非常合适 —— 在不需要对方调整的情况下,先让对方看到一些好处,这会让之后的继续推进减少很多阻力。
    1.2 作为自下而上推动监控体系落地的起步阶段,你需要尽量做到一鸣惊人,为之后的进一步推进打下基础。
  2. 接入traceId。
    2.1 初期只做到这一步!不要去想什么酷炫的链路图表展示,自下而上的方案推进最忌讳的就是冒进,小步前进并且持续监控改进措施执行时的相关表现。
    2.2 这一步在上一步打下的基础上推进会简单一些,一来你已经获得了基础的信任,二来这一项改动对于相关团队的工作量不高,都不会涉及业务代码的调整。
  3. 纳入基础设施 / 中间件监控。对于无法稳定复现的问题,我们往往需要更多的监控信息来辅助我们的决策,这个时候就需要考虑其他层面的监控了。关于这个选择可就相当多了。在接下来的小节里再作专门介绍。
3.2 Loki + Promtail + Grafana 轻量级零侵入方案

相较于ELK的笨重,Linux-Grep命令的简陋,Loki这一套解决方案正好位于中间位置:

  1. 既足够轻量;(Loki和Promtail都只是一个独立运行的exe应用,无额外依赖,这就意味着相当低的运维成本)
  2. 又有足够的颜值;(Grafana的图表化展示,对领导汇报和效果呈现有奇效)
  3. 操作便捷性、相当低的入门门槛;(LogQL官方文档拢共只有寥寥数页)。

这非常适合在对于监控基本概念都缺失的团队打开缺口,为监控的进一步落地开个好头:

  1. 即使"1-3月周期"的项目型团队,他们出于自身利益的考量,也肯定会记录日志。
  2. 这类团队肯定是采取脚手架 + 业务代码的模式,而且日志这一块投入精力绝对是能省则省,属于最开始配置一次之后,职业生涯结束都很可能不会再关注的东西;所以即使是这样的天崩开局的团队里也是可以找到优势的: 只要你编写出一个针对性的Loki + Promtail + Grafana配置,那么可以应用到该团队所接手的每个项目里,而且随着采用你这套方案解决的问题越来越多,整个团队都会因此进入对监控知识的主动了解中。
  3. 即使团队规模/脚手架千差万别,但基本的日志格式可以肯定只有少数几种,甚至对于绝大部分小型团队,都属于是网上直接抄的,你不强制要求他都不会去主动了解其中的含义;这样所造成的意外好处就是 —— 本方法只要做一次,就意味大部分的工作基本完成了,接入的团队数量和需要投入的精力并不是线性关系。实现以点打面的神奇效果。
3.3 接入traceId

上面的这一套Loki方案其实已经满足绝大部分问题排查需求了。不过考虑到ROI,非常推荐在此基础上马上再进一步 —— 推动研发团队实现日志中traceId的注入。

  1. 建议简单项目可以自己写或者借助TLog - 一个轻量级的分布式日志标记追踪神器这类专职的轻量级第三方库,
  2. 复杂的项目推荐Skywalking等。

如此的好处是能够快速从冗杂的日志中,快速筛选出自己真正感兴趣的那部分内容,实现"在大海中精确定位每一滴水滴"。

3.4 基础设施监控

上面的方案对于绝大部分团队其实都已经满足90%以上的监控需求。但是对于少数疑难杂症,你需要结合应用所在的环境(也即是操作系统,容器,虚拟机)等等一并进行考虑,这个时候你就要考虑接入基础设施等的监控,以更全面的监控数据来辅助问题定位和排查。

关于这一块的工具选型,过往我做过很多尝试,但最终落地经验并不多,以下就列出一些用过或者关注时间比较长的:

  1. Prometheus
  2. WGCloud - 极简&高效的主机监控系统
  3. HertzBeat - 无需Agent的实时监控工具
  4. Phoenix - 开源监控平台
  5. Flashcat (这个属于一直在关注,但未投入生产)
3.5 告警Alert

上述方案步骤下来,基本上99%场景都可以满足了。

不过出于基本的"物尽其用"基本思想,加上监控和告警这两个词往往都是同时出现 —— 好不容易收集齐了感兴趣的运行时信息,基于这些信息作进一步的价值挖掘也就顺理成章了。

而Loki本身自带提供了基于日志信息的告警功能。如此针对一些情况严重但是出现频率低的问题,我们可以实现尽早介入,掌握问题的主动权。

本小节之所以单独列出来,主要是想要说明:如何在不增加额外复杂度的情况下(额外部署AlertManager作为告警中心),有效使用Loki提供的Alert功能

关键点其实也是一点就破 —— 将Loki中告警相关配置中的alertmanager_url地址切换为我们自己应用的。

Loki配置:

...

ruler:
  external_url: http://172.4.2.79:3000
  alertmanager_url: http://172.4.2.xxx:801    # 这里切换为我们自己应用的url
  enable_alertmanager_v2: true

...

自主程序提供的接口声明:

@RestController
@RequestMapping("/api/v2")
public class LokiAlertReceiveController {

    // https://prometheus.io/docs/alerting/latest/clients/  【client -alertmanager】
    // https://github.com/prometheus/alertmanager/blob/main/api/v2/openapi.yaml  【openapi --- alertmanager】
    @PostMapping("/alerts")
    public String alert_Success(@RequestBody List<AlertModel> obj) {
        Console.log(JSONUtil.toJsonPrettyStr(obj));
        return "hello";
    }
}

public class AlertModel {

    /**
     * {
     * "annotations": {
     * "summary": "map[filename:/var/log/kqmsctl.2024-01-18.log job:kqmsctlLog module:kqmsctl] ---- map[] --- 3"
     * },
     * "labels": {
     * "severity": "error-log",
     * "alertname": "start_Fail",
     * "module": "kqmsctl",
     * "filename": "/var/log/kqmsctl.2024-01-18.log",
     * "host": "0.0.0.0",
     * "job": "kqmsctlLog"
     * },
     * "generatorURL":
     * "http://172.4.2.79:3000/graph?g0.expr=%28%28count_over_time%28%7Bmodule%3D%22kqmsctl%22%7D+%7C%3D+%22kqmsctl+start+failed%21%22%5B1m%5D%29+%3E+0%29+or+%28count_over_time%28%7Bmodule%3D%22kqmsctl%22%7D+%7C%3D+%22exit+pre+check+port+failed%22%5B1m%5D%29+%3E+0%29%29&g0.tab=1",
     * "startsAt": "2024-08-17T07:05:43.365Z",
     * "endsAt": "2024-08-17T07:06:43.365Z"
     * }
     */

    private Map<String, Object> annotations;
    private Map<String, Object> labels;
    private String generatorURL;
    private Date startsAt;
    private Date endsAt;

    public AlertModel() {
        // MapUtil : hutool工具类
        annotations = MapUtil.newHashMap();
        labels = MapUtil.newHashMap();
    }

    public Map<String, Object> getAnnotations() {
        return annotations;
    }

    public void setAnnotations(Map<String, Object> annotations) {
        this.annotations = annotations;
    }

    public Map<String, Object> getLabels() {
        return labels;
    }

    public void setLabels(Map<String, Object> labels) {
        this.labels = labels;
    }

    public String getGeneratorURL() {
        return generatorURL;
    }

    public void setGeneratorURL(String generatorURL) {
        this.generatorURL = generatorURL;
    }

    public Date getStartsAt() {
        return startsAt;
    }

    public void setStartsAt(Date startsAt) {
        this.startsAt = startsAt;
    }

    public Date getEndsAt() {
        return endsAt;
    }

    public void setEndsAt(Date endsAt) {
        this.endsAt = endsAt;
    }
}

最后简单列举下本方案的优缺点:

  1. 优点:无需额外部署AlertManager组件,杜绝了由此产生的运维成本。
  2. 缺点:需要自主进行告警相关的一系列诸如降噪,静默等等处理,而且上述这个接口往往是定义在业务系统中,以减少部署复杂度,方便运维。如此除了增加系统负担外,也与标准的监控理念不符 —— 业务系统无法提供对外服务时,正是告警功能发挥作用的时候;但在本方案下,很明显这个告警是发送不出去的。

所以本方案的适用场景依然是连专业运维人员,运维工作由研发,测试,技术支持分摊着搞的土八路团队,自然相关的软件规模也大不到哪里去。

后记

以上路线属于最标准的自下而上推进 —— 完全兼容现状,属于"晓之以理,不如诱之以利",先让对方看到效果,然后反向推进改良。

然后我需要特意强调一下,我们对于监控工具的选型,不要陷入"刘姥姥进大观园"困境 —— 觉得这个牛逼、那个更好。选适合你们的,够用就行;最重要的是部署方便,运维成本低;深入进去用好一个工具,而不是狗熊掰棒子。

最后,在落地过程中要进行持续性评估,切勿存在"一劳永逸"的想法。

相关

  1. 【DEVOPS】关于“可观测性“
  2. 【DEVOPS】现状篇
  3. 【DEVOPS】技术团队角色分工
  4. 高级研发的基本素养
  5. 传统软件行业中技术团队的发展(现状篇)
  6. 传统软件行业中技术团队的发展(团队破局篇)
  7. 传统软件行业中技术团队的发展(个人破局篇)
  8. 《极客时间 - 深入浅出可观测性》
  9. 《极客时间 - 运维监控系统实战笔记》
  10. Github - google/mtail - extract internal monitoring data from application logs for collection in a timeseries database
  11. Github - grok_exporter - Export Prometheus metrics from arbitrary unstructured log data.
  12. Loki - Alert配置项
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值