百度工程师浅谈分布式日志

作者 | 文库基础架构

导读

咱们做软件开发时,或多或少的会记载日志。因为日志不是体系的中心功用,常常被忽视,定位问题的时候才想起它。本文由浅入深的讨论不起眼的日志是否重要,以及散布式架构下的日志运维东西应该具有哪些才能,期望感兴趣的读者能从本文取得一些启示,有所协助。

全文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密钥协商算法探究

贴吧低代码高功用规矩引擎规划

浅谈权限体系在多利熊事务运用