天天看點

忽視分布式日志運維,微服務架構算是白搭了……

導讀:

我們做軟體開發時,或多或少的會記錄日志。由于日志不是系統的核心功能,常常被忽視,定位問題的時候才想起它。本文由淺入深的探讨不起眼的日志是否重要,以及分布式架構下的日志運維工具應該具備哪些能力,希望感興趣的讀者能從本文獲得一些啟發,有所幫助。

一、什麼是日志

日志是一種按照時間順序存儲記錄的資料,它記錄了什麼時間發生了什麼事情,提供精确的系統記錄,根據日志資訊可以定位到錯誤詳情和根源。按照APM概念的定義,日志的特點是描述一些離散的(不連續的)事件。

日志是按照錯誤級别分級的,常見的錯誤級别有 FATAL / WARNING / NOTICE / DEBUG / TRACE 5種類型。通常我們會在項目裡面定義一個日志列印級别,高于這個級别的錯誤日志會資料落盤。

忽視分布式日志運維,微服務架構算是白搭了……

二、什麼時候記錄日志

在大型網站系統架構裡面,日志是其中的重要功能組成部分。它可以記錄下系統所産生的所有行為,并按照某種規範表達出來。我們可以使用日志系統所記錄的資訊為系統進行排錯,優化性能。通過統計使用者行為日志,幫助産品營運同學做業務決策。在安全領域,日志可以反應出很多的安全攻擊行為,比如登入錯誤,異常通路等。日志能告訴你很多關于網絡中所發生事件的資訊,包括性能資訊、故障檢測和入侵檢測。還可以為審計進行審計跟蹤,日志的價值是顯而易見的。

三、日志的價值

在大型網站系統架構裡面,日志是其中的重要功能組成部分。它可以記錄下系統所産生的所有行為,并按照某種規範表達出來。我們可以使用日志系統所記錄的資訊為系統進行排錯,優化性能。通過統計使用者行為日志,幫助産品營運同學做業務決策。在安全領域,日志可以反應出很多的安全攻擊行為,比如登入錯誤,異常通路等。日志能告訴你很多關于網絡中所發生事件的資訊,包括性能資訊、故障檢測和入侵檢測。還可以為審計進行審計跟蹤,日志的價值是顯而易見的。

四、分布式架構的日志運維

1、為什麼要有運維工具

微服務發展迅猛的今天,松耦合的設計層出不窮,為簡化服務服務帶來了極大的便利。業務方向分工明确,研發同學隻需要關心自己子產品的版本疊代上線就好。随着整個業務架構的擴大,服務執行個體的數量迎來了爆炸性的增長,往往帶來以下問題:

由不同團隊開發,使用不同的程式設計語言,日志格式不規範統一;

微服務疊代速度快,日志漏記、級别使用錯誤、難以提取有效資訊;

容器執行個體分布在成千上萬台伺服器上,橫跨多個資料中心,異構部署,難以串聯請求鍊路。

沒有工具的情況下,需要登入服務執行個體,檢視原始日志,在日志檔案中通過grep、awk方式獲得自己想要的資訊。但在規模較大的場景中,此方法效率低下,面臨問題包括日志量太大不易歸檔、文本搜尋太慢、不友善多元度查詢。這時候需要更加高效的運維工具來代替人工通路日志。常見解決思路是建立集中式日志收集系統,将所有節點上的日志統一收集,管理,通路。

2、運維工具建設

我們希望通過原始日志可以了解系統行為,這需要建設具備性能分析,問題定位的能力的工具平台。它能夠支援:

  • 在故障發生前,分析風險和系統瓶頸;
  • 在故障發生時,及時通知,快速定位解決問題;
  • 在故障發生後,有曆史資料迅速複盤。

通過建設具備日志即時收集、分析、存儲等能力的工具平台。使用者可以快速高效地進行問題診斷、系統運維、流量穩定性監控、業務資料分析等操作。比如搭建鍊路追蹤系統,能追蹤并記錄請求在系統中的調用順序,調用時間等一系列關鍵資訊,進而幫助我們定位異常服務和發現性能瓶頸,提升了系統的『可觀測性』。前面提到日志在APM标準的定義下日志的特點是描述一些離散的(不連續的)事件。這裡說下APM是什麼,友善更好的建構監控方面的知識體系。

五、APM和可觀測性

APM 是Application Performance Managment的縮寫,即:“應用性能管理”。可以把它了解成一種對分布式架構進行觀測分析優化的理念和方法論。監控系統(包括告警)作為SLA體系的一個重要組成部分,不僅在業務和系統中充當保镖發現問題、排查問題的作用。

随着系統不斷演進完善,我們可以獲得越多幫助于了解業務和系統的資料和資訊,這些資訊可以更進一步的幫助我們進行系統上的優化,由于可以梳理請求鍊路得出使用者的浏覽偏好,甚至可以影響業務上的關鍵決策。

整體來說,整個APM體系就是将大三類資料(logs、metrics、trace)應用到四大子產品中(收集、加工、存儲、展示),并在四個難點(程式異構,元件多樣,鍊路完整,時效采樣)上不斷優化。

可觀測性是APM的一大特征,主要由以下三大支柱構成,分别是Logging(日志),Metrics(名額),以及Tracing(應用跟蹤)。

Logging:自動埋點/手動埋點,展現的是應用運作而産生的事件或者程式在執行的過程中間産生的一些日志,可以詳細解釋系統的運作狀态,但是存儲和查詢需要消耗大量的資源。

Metrics:服務、端點、執行個體的各項名額,是一種聚合數值,存儲空間很小,可以觀察系統的狀态和趨勢,對于問題定位缺乏細節展示,最節省存儲資源。

Tracing:同一TraceId的調用序列,面向的是請求,可以輕松分析出請求中異常點,資源可能消耗較大,不過依據具體功能實作相對可控。

忽視分布式日志運維,微服務架構算是白搭了……

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把資料以圖形化形式展示給使用者。

忽視分布式日志運維,微服務架構算是白搭了……

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平台,在保證關鍵日志資訊入庫的同時,有針對性的對所需日志檔案進行采集和過濾是必不可少的。

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層串聯, 幫助我們更好的了解系統的行為、輔助調試和排查性能問題。它的基本概念如下兩點:

Trace(調用鍊):OpenTracing中的Trace(調用鍊)通過歸屬于此調用鍊的Span來隐性的定義。一條Trace(調用鍊)可以被認為是一個由多個Span組成的有向無環圖(DAG圖),可以簡單了解成一次事務;

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作為主要的日志運維平台。

4、Metrics、Logging和Tracing結合

名額、日志、鍊路在監控中是相輔相成的。現在再來看上圖中,兩兩相交的部分:

通過名額和日志次元,我們可以做一些事件的聚合統計,例如,繪制流量趨勢圖,某應用每分鐘的錯誤日志數

通過鍊路和日志系統,我們可以得到某個請求詳細的請求資訊,例如請求的入參、出參、鍊路中途方法列印出的日志資訊;

通過名額和鍊路系統,我們可以查到請求調用資訊,例如 SQL執行總時長、各依賴服務調用總次數;

可見,通過這三種類型資料互相作用,可以得到很多在某種類型資料中無法呈現的資訊。例如下圖是一個故障排查的示例,首先,我們從消息通知中發現告警,進入metrics名額面闆,定位到有問題的資料圖表,再通過名額系統查詢到詳細的資料,在logging日志系統查詢到對應的錯誤,通過tracing鍊路追蹤系統檢視鍊路中的位置和問題(當然也可以先用鍊路追蹤系統進行故障的定位,再查詢詳細日志),最後修複故障。這是一個典型的将三個系統串聯起來應用的示例。

忽視分布式日志運維,微服務架構算是白搭了……

六、文庫在日志運維上的實踐

1、彙聚監控

文庫App對于域名、中間件、依賴服務等流量穩定性,機器資源的監控,基于廠内現有的解決方案(Bns+Argus監控系統+Sia可視化平台)實作。工作流程可以了解為:

在日志采集平台(Argus)配置資料采集規則,異常判斷規則和報警配置規則;

通過服務執行個體映射配置(Bns)擷取到要采集日志的執行個體清單,執行個體服務的log format要符合采集規則的正規表達式;

Agent上報日志分析資料給MQ消化,MQ存入TSDB;

日志彙聚後的分析計算結果符合異常判斷規則,則觸發對應配置的報警規則;

報警規則可以配置多元度分級分時間和不同方式提醒到接收人。同時,通過配置群聊機器人對包括資源,接入層,運作層,服務及底層依賴的等服務,依據閥值進行基本實時的監控報警;

可視化平台(Sia)通過 metric 配置從 TSDB 中讀出相應資料,進行圖形化展示。

忽視分布式日志運維,微服務架構算是白搭了……

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指令,并發度控制,優化輸出等功能。

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的日志,節點背景色會以紅色,黃色展示。

忽視分布式日志運維,微服務架構算是白搭了……

七、日志的壞味道

  • 資訊不明确。後果:執行效率降低;
  • 格式不規範。後果:不可讀,無法采集;
  • 日志過少,缺乏關鍵資訊。後果:降低定位問題效率;
  • 參雜了臨時、備援、無意義的日志。後果:生産列印大量日志消耗性能;
  • 日志錯誤級别使用混亂。後果:導緻監控誤報;
  • 使用字元串拼接方式,而非占位符。後果:可維護性較低;
  • 代碼循環體打非必要的日志。後果:有當機風險;
  • 敏感資料未脫敏。後果:有隐私資訊洩露風險;
  • 日志檔案未按小時分割轉儲。後果:不易磁盤空間回收;
  • 服務調用間沒有全局透傳trace資訊。後果:不能建構全鍊路日志跟蹤。

八、日志good case

能快速的定位問題;

能提取有效資訊,了解原因;

了解線上系統的運作狀态;

彙聚日志關鍵資訊,可以發現系統的瓶頸;

日志随着項目疊代,同步疊代;

日志的列印和采集、上報服務,不能影響系統的正常運作。

九、結語

在萬物上雲的時代,通過搭建合适的日志運維平台來賦予資料搜尋、分析和監控預警的能力,讓沉寂在伺服器的日志"動"起來,可以幫助我們在資料分析,問題診斷,系統改進的工作中更加順利的進行,希望本文的内容對大家的實踐有所幫助。

作者丨文庫基礎架構

來源丨公衆号:百度Geek說(ID:baidugeektalk)

dbaplus社群歡迎廣大技術人員投稿,投稿郵箱:[email protected]

活動推薦

第八屆DAMS-中國資料智能管理峰會将于2023年3月31日在上海舉辦,與大家一起探索大資料與雲原生強強聯合的方式、挖掘由此激發的軟體發展和技術進步。

報名連結:

https://www.bagevent.com/event/8100960?bag_track=TT

演講嘉賓所在機關:阿裡、騰訊、京東、美團、華為雲、位元組、螞蟻、網易、新浪、攜程、哔哩哔哩、小紅書、vivo、快狗打車、貨拉拉、工商銀行、建設銀行、中國銀行、平安銀行、光大銀行、彙豐銀行、微衆銀行、複旦大學等産學研界技術領跑機關。

演講議題聚焦:

  • 大資料&資料資産管理:資料治理丨存算分離丨雲原生OLAP丨湖倉一體丨智能分析
  • 資料庫:雲原生分布式丨時間序列丨服務自治丨中間件丨跨雲多活
  • 運維:AIOps丨故障分析丨性能優化丨離線上混部丨高可用建設
  • 金融科技:規模化監控丨實時數倉丨分布式改造丨國産化替代丨數字化轉型丨混沌工程
忽視分布式日志運維,微服務架構算是白搭了……

繼續閱讀