乐趣区

关于运维:百度工程师浅谈分布式日志

作者 | 文库基础架构

导读

咱们做软件开发时,或多或少的会记录日志。因为日志不是零碎的外围性能,经常被忽视,定位问题的时候才想起它。本文由浅入深的探讨不起眼的日志是否重要,以及分布式架构下的日志运维工具应该具备哪些能力,心愿感兴趣的读者能从本文取得一些启发,有所帮忙。

全文 8832 字,预计浏览工夫 23 分钟。

01 什么是日志

日志是一种依照工夫顺序存储记录的数据,它记录了什么工夫产生了什么事件,提供准确的零碎记录,依据日志信息能够定位到谬误详情和本源。依照 APM 概念的定义,日志的特点是形容一些离散的(不间断的)事件。

日志是依照谬误级别分级的,常见的谬误级别有 FATAL / WARNING / NOTICE / DEBUG / TRACE 5 种类型。通常咱们会在我的项目外面定义一个日志打印级别,高于这个级别的谬误日志会数据落盘。

02 什么时候记录日志

在大型网站零碎架构外面,日志是其中的重要性能组成部分。它能够记录下零碎所产生的所有行为,并依照某种标准表达出来。咱们能够应用日志零碎所记录的信息为零碎进行排错,优化性能。通过统计用户行为日志,帮忙产品经营同学做业务决策。在平安畛域,日志能够反馈出很多的平安攻击行为,比方登录谬误,异样拜访等。日志能通知你很多对于网络中所产生事件的信息,包含性能信息、故障检测和入侵检测。还能够为审计进行审计跟踪,日志的价值是不言而喻的。

03 日志的价值

在大型网站零碎架构外面,日志是其中的重要性能组成部分。它能够记录下零碎所产生的所有行为,并依照某种标准表达出来。咱们能够应用日志零碎所记录的信息为零碎进行排错,优化性能。通过统计用户行为日志,帮忙产品经营同学做业务决策。在平安畛域,日志能够反馈出很多的平安攻击行为,比方登录谬误,异样拜访等。日志能通知你很多对于网络中所产生事件的信息,包含性能信息、故障检测和入侵检测。还能够为审计进行审计跟踪,日志的价值是不言而喻的。

04 分布式架构的日志运维

4.1 为什么要有运维工具

微服务倒退迅猛的明天,松耦合的设计层出不穷,为简化服务服务带来了极大的便当。业务方向分工明确,研发同学只须要关怀本人模块的版本迭代上线就好。随着整个业务架构的扩充,服务实例的数量迎来了爆炸性的增长,往往带来以下问题:

  • 由不同团队开发,应用不同的编程语言,日志格局不标准对立;
  • 微服务迭代速度快,日志漏记、级别应用谬误、难以提取无效信息;
  • 容器实例散布在成千上万台服务器上,横跨多个数据中心,异构部署,难以串联申请链路。

没有工具的状况下,须要登录服务实例,查看原始日志,在日志文件中通过 grep、awk 形式取得本人想要的信息。但在规模较大的场景中,此办法效率低下,面临问题包含日志量太大不易归档、文本搜寻太慢、不不便多维度查问。这时候须要更加高效的运维工具来代替人工拜访日志。常见解决思路是建设集中式日志收集零碎,将所有节点上的日志对立收集,治理,拜访。

4.2 运维工具建设

咱们心愿通过原始日志能够了解零碎行为,这须要建设具备性能剖析,问题定位的能力的工具平台。它可能反对:

  • 在故障产生前,剖析危险和零碎瓶颈;
  • 在故障产生时,及时告诉,疾速定位解决问题;
  • 在故障产生后,有历史数据迅速复盘。

通过建设具备日志即时收集、剖析、存储等能力的工具平台。用户能够疾速高效地进行问题诊断、零碎运维、流量稳定性监控、业务数据分析等操作。比方搭建链路追踪零碎,能追踪并记录申请在零碎中的调用程序,调用工夫等一系列要害信息,从而帮忙咱们定位异样服务和发现性能瓶颈,晋升了零碎的『可观测性』。后面提到日志在 APM 规范的定义下日志的特点是形容一些离散的(不间断的)事件。这里说下 APM 是什么,不便更好的构建监控方面的常识体系。

05 APM 和可观测性

APM 是 Application Performance Managment 的缩写,即:“利用性能治理”。能够把它了解成一种对分布式架构进行观测剖析优化的理念和方法论。监控零碎(包含告警)作为 SLA 体系的一个重要组成部分,不仅在业务和零碎中充当保镖发现问题、排查问题的作用。

随着零碎一直演进欠缺,咱们能够取得越多帮忙于理解业务和零碎的数据和信息,这些信息能够更进一步的帮忙咱们进行零碎上的优化,因为能够梳理申请链路得出用户的浏览偏好,甚至能够影响业务上的要害决策。

整体来说,整个 APM 体系就是将大三类数据(logs、metrics、trace)利用到四大模块中(收集、加工、存储、展现),并在四个难点(程序异构,组件多样,链路残缺,时效采样)上一直优化。

可观测性 是 APM 的一大特色,次要由以下三大支柱形成,别离是 Logging(日志),Metrics(指标),以及 Tracing(利用跟踪)。

  • Logging:主动埋点 / 手动埋点,展示的是利用运行而产生的事件或者程序在执行的过程两头产生的一些日志,能够具体解释零碎的运行状态,然而存储和查问须要耗费大量的资源。
  • Metrics:服务、端点、实例的各项指标,是一种聚合数值,存储空间很小,能够察看零碎的状态和趋势,对于问题定位不足细节展现,最节俭存储资源。
  • Tracing:同一 TraceId 的调用序列,面向的是申请,能够轻松剖析出申请中异样点,资源可能耗费较大,不过根据具体性能实现绝对可控。

5.1 Metrics 和 Prometheus

Metrics:指标。

I think that the defining characteristic of metrics is that they are aggregatable: they are the atoms that compose into a single logical gauge, counter, or histogram over a span of time.

大抵上可了解为一些可进行聚合计算的原子型数据。举些例子:cpu 占用状况、零碎内存占用、接口响应工夫、接口响应 QPS、服务 gc 次数、订单量等。这些都是依据工夫序列存储的数据值,能够在一段时间内进行一些求和、求均匀、百分位等聚合计算。指标在监控零碎中不可或缺,咱们都须要收集每种指标在工夫线上的变动,并作同比、环比上的剖析。metrics 的存储模式为有工夫戳标记的数据流,通常存储在 TSDB(工夫序列数据库)中。

Metrics 侧重于各种报表数据的收集和展现,罕用在大规模业务的可用性建设、性能优化、容量治理等场景,通过可视化仪表盘可高效地进行日常零碎巡检、疾速查看利用健康状况,能够精准感知可用性和性能问题,为产品的稳固运行保驾护航。

Prometheus 是一个开源的监控解决方案,它可能提供监控指标数据的采集、存储、查问以及监控告警等性能。作为云原生基金会 (CNCF) 的毕业我的项目,Prometheus 曾经在云原生畛域失去了大范畴的利用,并逐步成为了业界最风行的监控解决方案之一。

下图为 Prometheus 的工作流程,能够简略了解为:Prometheus server 定期拉取指标实例的采集数据,工夫序列存储,一方面通过配置报警规定,把触发的报警发送给接管方,一方面通过组件 Grafana 把数据以图形化模式展现给用户。

5.2 Logging 和 ELK

Logging:日志。

I think that the defining characteristic of logging is that it deals with discrete events.

日志是零碎运行时产生的一个个事件的记录。Logging 的典型特色就是它和孤立的事件(Event)强关联,一个事件的产生所以导致了一条日志的产生。举个例子就是一个网络申请是一个事件,它被云端接到后 Nginx 产生了一个拜访 log。大量的不同内部事件间根本是离散的,比方多个用户拜访云端业务时产生的 5 个事件间没有必然的关系,所以在一个服务节点的角度上看这些事件产生的日志间也是离散的。

对于日志治理平台,置信很多同学据说过最多的就是 ELK(elastic stack),ELK 是三款软件的简称,别离是 Elasticsearch、Logstash、Kibana 组成。在 APM 体系中,它能够实现关键字的分布式搜寻和日志剖析,可能疾速定位到咱们想要的日志,通过可视化平台的展现,可能从多个维度来对日志进行细化跟踪。

Elasticsearch基于 java,是个开源分布式搜索引擎,它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful web 接口。是以后风行的企业级搜索引擎。设计用于云计算中,可能达到实时搜寻,稳固,牢靠,疾速,装置使用方便。它的特点有:分布式,零配置,主动发现,索引主动分片,索引正本机制,restful 格调接口,多数据源,主动搜寻负载等。

Kibana基于 nodejs,是一款开源的数据分析和可视化平台,它是 Elastic Stack 成员之一,设计用于和 Elasticsearch 合作。您能够应用 Kibana 对 Elasticsearch 索引中的数据进行搜寻、查看、交互操作。您能够很不便的利用图表、表格及地图对数据进行多元化的剖析和出现。

Logstash基于 java,是一个开源的用于收集, 剖析和存储日志的工具,可能同时从多个起源采集数据,转换数据,而后将数据发送到最喜爱的存储库中(咱们的存储库当然是 ElasticSearch)。

上面是 ELK 的工作原理:

ELK 中的 L 了解成 Logging Agent 比拟适合。Elasticsearch 和 Kibana 是存储、检索和剖析 log 的规范计划。在高负载的 ELK 平台迭代实际中,经常采纳一些优化策略。比方:ElasticSearch 做冷热数据拆散,历史索引数据敞开;Filebeat 更加轻量,对资源耗费更少,代替 Logstash 作为数据收集引擎;减少音讯队列做数据缓冲,通过解耦处理过程实现削峰平谷,帮忙平台顶住突发的拜访压力。

ELK 的毛病也是显著的,部署这样一套日志剖析零碎,不论是存储还是剖析所须要占用的机器老本是挺大的。业务日志是时时打印的,大规模的在线服务一天日志量可能达到 TB 级别,如果采纳 ELK 平台,在保障要害日志信息入库的同时,有针对性的对所需日志文件进行采集和过滤是必不可少的。

5.3 Tracing、OpenTracing 和 Apache SkyWalking

.Tracing:链路。

I think that the single defining characteristic of tracing , then, is that it deals with information that is request-scoped.

链路可了解为某个最外层申请下的所有调用信息。在微服务中个别有多个调用信息,如从最外层的网关开始,A 服务调用 B 服务,调用数据库、缓存等。在链路零碎中,须要分明展示某条调用链中从主调方到被调方外部所有的调用信息。这不仅有利于梳理接口及服务间调用的关系,还有助于排查慢申请产生的起因或异样产生的起因。

Tracing 最早提出是来自 Google 的论文《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》,它让 Tracing 流行起来。而 Twitter 基于这篇论文开发了 Zipkin 并开源了这个我的项目。再之后业界百花齐放,诞生了一大批开源和商业 Tracing 零碎。

Tracing 以申请的维度,串联服务间的调用关系并记录调用耗时,即保留了必要的信息,又将扩散的日志事件通过 Span 层串联,帮忙咱们更好的了解零碎的行为、辅助调试和排查性能问题。它的基本概念如下两点:

  1. Trace(调用链):OpenTracing 中的 Trace(调用链)通过归属于此调用链的 Span 来隐性的定义。一条 Trace(调用链)能够被认为是一个由多个 Span 组成的有向无环图(DAG 图),能够简略了解成一次事务;
  2. Span(跨度):能够被翻译为跨度,能够被了解为一次办法调用,一个程序块的调用,或者一次 RPC/ 数据库拜访,只有是一个具备残缺工夫周期的程序拜访,都能够被认为是一个 Span。

对于一个组件来说,一次处理过程产生一个 Span,这个 Span 的生命周期是从接管到申请到返回响应这段过程,在单个 Trace 中,存在多个 Span。

举个例子,比方一个申请用户订单信息的接口,流量散发到了应用层实例(Span A)来解决申请,应用层实例(Span A)须要申请订单核心服务实例(Span B)来获取订单数据,同时申请用户核心服务实例(Span C)来获取用户数据。根底服务 B、C 可能还有其余依赖服务链路,则如下图所示构造,Span 间的因果关系如下:

        [Span A]  ←←←(the root span)
            |
     +------+------+
     |             |
 [Span B]      [Span C] ←←←(Span C 是 Span A 的孩子节点, ChildOf)
     |             |
 [Span D]      +---+-------+
               |           |
           [Span E]    [Span F] >>> [Span G] >>> [Span H]
                                       ↑
                                       ↑
                                       ↑
                         (Span G 在 Span F 后被调用, FollowsFrom)

OpenTracing 是一个中立的(厂商无关、平台无关)分布式追踪的API 标准,提供对立接口,可不便开发者在本人的服务中集成一种或多种分布式追踪的实现。因为近年来各种链路监控产品层出不穷,以后市面上支流的工具既有像 Datadog 这样的一揽子商业监控计划,也有 AWS X-Ray 和 Google Stackdriver Trace 这样的云厂商产品,还有像 Zipkin、Jaeger 这样的开源产品。

云原生基金会(CNCF) 推出了 OpenTracing 规范,推动 Tracing 协定和工具的标准化,对立 Trace 数据结构和格局。OpenTracing 通过提供平台无关、厂商无关的 API,使得开发人员可能不便增加(或更换)追踪零碎的实现。比方从 Zipkin 替换成 Jaeger/Skywalking 等后端。

在泛滥 Tracing 产品中,值得一提的是国人自研开源的产品 Skywalking。它是一款优良的 APM 工具,专为微服务、云原生架构和基于容器架构而设计,反对 Java、.Net、NodeJs 等探针形式接入我的项目,数据存储反对 Mysql、Elasticsearch 等。性能包含了分布式链路追踪,性能指标剖析和服务依赖剖析等。2017 年退出 Apache 孵化器,2019 年 4 月 17 日 Apache 董事会批准 SkyWalking 成为顶级我的项目,目前百度厂内有一些业务线采纳 skywalking 作为次要的日志运维平台。

5.4 Metrics,Logging 和 Tracing 联合

指标、日志、链路在监控中是相辅相成的。当初再来看上图中,两两相交的局部:

  1. 通过指标和日志维度,咱们能够做一些事件的聚合统计,例如,绘制流量趋势图,某利用每分钟的谬误日志数
  2. 通过链路和日志零碎,咱们能够失去某个申请具体的申请信息,例如申请的入参、出参、链路中途办法打印出的日志信息;
  3. 通过指标和链路零碎,咱们能够查到申请调用信息,例如 SQL 执行总时长、各依赖服务调用总次数;

可见,通过这三种类型数据相互作用,能够失去很多在某种类型数据中无奈出现的信息。例如下图是一个故障排查的示例,首先,咱们从音讯告诉中发现告警,进入 metrics 指标面板,定位到有问题的数据图表,再通过指标零碎查问到具体的数据,在 logging 日志零碎查问到对应的谬误,通过 tracing 链路追踪零碎查看链路中的地位和问题(当然也能够先用链路追踪零碎进行故障的定位,再查问具体日志),最初修复故障。这是一个典型的将三个零碎串联起来利用的示例。

06 文库在日志运维上的实际

6.1 汇聚监控

文库 App 对于域名、中间件、依赖服务等流量稳定性,机器资源的监控,基于厂内现有的解决方案(Bns+Argus 监控零碎 +Sia 可视化平台)实现。工作流程能够了解为:

  1. 在日志采集平台(Argus)配置数据采集规定,异样判断规定和报警配置规定;
  2. 通过服务实例映射配置(Bns)获取到要采集日志的实例列表,实例服务的 log format 要合乎采集规定的正则表达式;
  3. Agent 上报日志剖析数据给 MQ 消化,MQ 存入 TSDB;
  4. 日志汇聚后的剖析计算结果合乎异样判断规定,则触发对应配置的报警规定;
  5. 报警规定能够配置多维度分级分工夫和不同形式揭示到接管人。同时,通过配置群聊机器人对包含资源,接入层,运行层,服务及底层依赖的等服务,根据阀值进行根本实时的监控报警;
  6. 可视化平台(Sia)通过 metric 配置从 TSDB 中读出相应数据,进行图形化展现。

6.2 批量查问

即时日志捞取工具在咱们业务开发中也是比拟常见的,通常通过批量并发执行近程服务器指令来实现,解决顺次执行的繁锁,让运维操作更平安便捷。

这种工具不依赖 agent,只通过 ssh 就能够工作,个别通过中控机或者账户明码等形式做 ssh 访问控制,执行 grep,tail 等命令获取日志,而后对 logs 进行剖析,能够解决日常中很多的需要。简化代码如下。

package main

import (
  "fmt"
  "log"
  "os/exec"
  "runtime"
  "sync"
)

// 并发环境
var wg sync.WaitGroup

func main() {runtime.GOMAXPROCS(runtime.NumCPU())
  instancesHost := getInstances()
  wg.Add(len(instancesHost))
  for _, host := range instancesHost {go sshCmd(host)
  }
  wg.Wait()
  fmt.Println("over!")
}

// 执行查问命令
func sshCmd(host string) {defer wg.Done()
  logPath := "/xx/xx/xx/"
  logShell := "grep'FATAL'xx.log.20230207"
  cmd := exec.Command("ssh", "PasswordAuthentication=no", "ConnectTimeout=1", host, "-l", "root", "cd", logPath, "&&", logShell)
  out, err := cmd.CombinedOutput()
  fmt.Printf("exec: %s\n", cmd)
  if err != nil {fmt.Printf("combined out:\n%s\n", string(out))
    log.Fatalf("cmd.Run() failed with %s\n", err)
  }
  fmt.Printf("combined out:\n%s\n", string(out))
}

// 获取要查问的实例 ip 地址库
func getInstances() []string {return []string{
    "x.x.x.x",
    "x.x.x.x",
    "x.x.x.x",
  }
}

把如上代码部署在中控机上 ssh 免密登录,通过 go run batch.go 或执行 go build 后的二进制文件,能够实现批量查问日志的根底能力。在此基础上减少传参,能够实现指定集群实例,指定 exec 命令,并发度管制,优化输入等性能。

6.3 链路跟踪

文库自研的全链路日志跟踪平台,反对 trace 全链路日志跟踪,指标汇聚,要害信息高亮,搜寻范畴笼罩 nginx,nodejs,php,go 等异构微服务,还反对动静绘制调用链路图。用户能够通过查问 tracid 的形式取得一个申请链路的 http 剖析,调用服务的次数汇聚,日志 list 和拓扑链路图。

透传 trace 的底层流程是在接入层 nginx 扩大生成的一个 20 -26 位长、编码了 nginx 所在机器 ip 和申请工夫的纯数字字符串。这个字符串在申请日志、服务运行日志、rpc 日志中记录,通过 Http Header 向下透传,在服务间调用过程中,在以后层记录调用的下一层实例 ip:port 信息,保障 trace 参数维持。

绿色的节点为链路调用的起始节点,个别是文库接入层。鼠标 hover 到哪个节点会 title 展现详情,并在整个链路中隐去与之不相干的节点链路。如果节点有 fatal,warning 的日志,节点背景色会以红色,黄色展现。

07 日志的坏滋味

  1. 信息不明确。结果:执行效率升高;
  2. 格局不标准。结果:不可读,无奈采集;
  3. 日志过少,不足要害信息。结果:升高定位问题效率;
  4. 参杂了长期、冗余、无意义的日志。结果:生产打印大量日志耗费性能;
  5. 日志谬误级别应用凌乱。结果:导致监控误报;
  6. 应用字符串拼接形式,而非占位符。结果:可维护性较低;
  7. 代码循环体打非必要的日志。结果:有宕机危险;
  8. 敏感数据未脱敏。结果:有隐衷信息泄露危险;
  9. 日志文件未按小时宰割转储。结果:不易磁盘空间回收;
  10. 服务调用间没有全局透传 trace 信息。结果:不能构建全链路日志跟踪。

08 日志 good case

  1. 能疾速的定位问题;
  2. 能提取无效信息,理解起因;
  3. 理解线上零碎的运行状态;
  4. 汇聚日志要害信息,能够发现零碎的瓶颈;
  5. 日志随着我的项目迭代,同步迭代;
  6. 日志的打印和采集、上报服务,不能影响零碎的失常运行。

09 结语

在万物上云的时代,通过搭建适合的日志运维平台来赋予数据搜寻、剖析和监控预警的能力,让寂静在服务器的日志 ” 动 ” 起来,能够帮忙咱们在数据分析,问题诊断,零碎改良的工作中更加顺利的进行,心愿本文的内容对大家的实际有所帮忙。

——END——

举荐浏览:

百度工程师带你理解 Module Federation

巧用 Golang 泛型,简化代码编写

Go 语言 DDD 实战高级篇

Diffie-Hellman 密钥协商算法探索

贴吧低代码高性能规定引擎设计

浅谈权限零碎在多利熊业务利用

退出移动版