從ELK到EFK演進

来源:http://www.cnblogs.com/tylercao/archive/2017/11/08/7803520.html
-Advertisement-
Play Games

背景 作為中國最大的線上教育站點,目前滬江日誌服務的用戶包含網校,交易,金融,CCTalk 等多個部門的多個產品的日誌搜索分析業務,每日產生的各類日誌有好十幾種,每天處理約10億條(1TB)日誌,熱數據保留最近7天數據,冷數據永久保存。 為什麼做日誌系統 首先,什麼是日誌? 日誌就是程式產生的,遵循 ...


背景

作為中國最大的線上教育站點,目前滬江日誌服務的用戶包含網校,交易,金融,CCTalk 等多個部門的多個產品的日誌搜索分析業務,每日產生的各類日誌有好十幾種,每天處理約10億條(1TB)日誌,熱數據保留最近7天數據,冷數據永久保存。

為什麼做日誌系統

首先,什麼是日誌? 日誌就是程式產生的,遵循一定格式(通常包含時間戳)的文本數據

通常日誌由伺服器生成,輸出到不同的文件中,一般會有系統日誌、 應用日誌、安全日誌。這些日誌分散地存儲在不同的機器上。

通常當系統發生故障時,工程師需要登錄到各個伺服器上,使用 grep / sed / awk 等 Linux 腳本工具去日誌里查找故障原因。在沒有日誌系統的情況下,首先需要定位處理請求的伺服器,如果這台伺服器部署了多個實例,則需要去每個應用實例的日誌目錄下去找日誌文件。每個應用實例還會設置日誌滾動策略(如:每天生成一個文件),還有日誌壓縮歸檔策略等。

這樣一系列流程下來,對於我們排查故障以及及時找到故障原因,造成了比較大的麻煩。因此,如果我們能把這些日誌集中管理,並提供集中檢索功能,不僅可以提高診斷的效率,同時對系統情況有個全面的理解,避免事後救火的被動。

我認為,日誌數據在以下幾方面具有非常重要的作用:

  • 數據查找:通過檢索日誌信息,定位相應的 bug ,找出解決方案
  • 服務診斷:通過對日誌信息進行統計、分析,瞭解伺服器的負荷和服務運行狀態
  • 數據分析:可以做進一步的數據分析,比如根據請求中的課程 id ,找出 TOP10 用戶感興趣課程。

針對這些問題,為了提供分散式的實時日誌搜集和分析的監控系統,我們採用了業界通用的日誌數據管理解決方案 - 它主要包括 Elasticsearch 、 Logstash 和 Kibana 三個系統。通常,業界把這套方案簡稱為ELK,取三個系統的首字母,但是我們實踐之後將其進一步優化為EFK,F代表Filebeat,用以解決Logstash導致的問題。下麵,我們展開詳細介紹。

文中涉及的 ELK stack 版本是:

Elasticsearch 5.2.2
Logstash 5.2.2
Kibana 5.2.2
Filebeat 5.2.2
Kafka 2.10

Logstash :數據收集處理引擎。支持動態的從各種數據源搜集數據,並對數據進行過濾、分析、豐富、統一格式等操作,然後存儲以供後續使用。

Kibana :可視化化平臺。它能夠搜索、展示存儲在 Elasticsearch 中索引數據。使用它可以很方便的用圖表、表格、地圖展示和分析數據。

Elasticsearch :分散式搜索引擎。具有高可伸縮、高可靠、易管理等特點。可以用於全文檢索、結構化檢索和分析,並能將這三者結合起來。Elasticsearch 基於 Lucene 開發,現在使用最廣的開源搜索引擎之一,Wikipedia 、StackOverflow、Github 等都基於它來構建自己的搜索引擎。

Filebeat :輕量級數據收集引擎。基於原先 Logstash-fowarder 的源碼改造出來。換句話說:Filebeat就是新版的 Logstash-fowarder,也會是 ELK Stack 在 shipper 端的第一選擇。

既然要談 ELK 在滬江系統中的應用,那麼 ELK 架構就不得不談。本次分享主要列舉我們曾經用過的 ELK 架構,並討論各種架構所適合的場景和優劣供大家參考

簡單版架構

image

這種架構下我們把 Logstash 實例與 Elasticsearch 實例直接相連。Logstash 實例直接通過 Input 插件讀取數據源數據(比如 Java 日誌, Nginx 日誌等),經過 Filter 插件進行過濾日誌,最後通過 Output 插件將數據寫入到 ElasticSearch 實例中。

這個階段,日誌的收集、過濾、輸出等功能,主要由這三個核心組件組成 Input 、Filter、Output

Input:輸入,輸入數據可以是 File 、 Stdin(直接從控制台輸入) 、TCP、Syslog 、Redis 、Collectd 等

Filter:過濾,將日誌輸出成我們想要的格式。Logstash 存在豐富的過濾插件:Grok 正則捕獲、時間處理、JSON 編解碼、數據修改 Mutate 。Grok 是 Logstash 中最重要的插件,強烈建議每個人都要使用 Grok Debugger 來調試自己的 Grok 表達式

grok {
      match => ["message", "(?m)\[%{LOGLEVEL:level}\] \[%{TIMESTAMP_ISO8601:timestamp}\] \[%{DATA:logger}\] \[%{DATA:threadId}\] \[%{DATA:requestId}\] %{GREEDYDATA:msgRawData}"]
    }

Output:輸出,輸出目標可以是 Stdout (直接從控制台輸出)、Elasticsearch 、Redis 、TCP 、File 等

這是最簡單的一種ELK架構方式,Logstash 實例直接與 Elasticsearch 實例連接。優點是搭建簡單,易於上手。建議供初學者學習與參考,不能用於線上的環境。

集群版架構

image

這種架構下我們採用多個 Elasticsearch 節點組成 Elasticsearch 集群,由於 Logstash 與 Elasticsearch 採用集群模式運行,集群模式可以避免單實例壓力過重的問題,同時線上上各個伺服器上部署 Logstash Agent,來滿足數據量不大且可靠性不強的場景。

數據收集端:每台伺服器上面部署 Logstash Shipper Agent 來收集當前伺服器上日誌,日誌經過 Logstash Shipper 中 Input插件、Filter插件、Output 插件傳輸到 Elasticsearch 集群

數據存儲與搜索:Elasticsearch 配置預設即可滿足,同時我們看數據重要性來決定是否添加副本,如果需要的話,最多一個副本即可

數據展示:Kibana 可以根據 Elasticsearch 的數據來做各種各樣的圖表來直觀的展示業務實時狀況

這種架構使用場景非常有限,主要存在以下兩個問題

  • 消耗伺服器資源:Logstash 的收集、過濾都在伺服器上完成,這就造成伺服器上占用系統資源較高、性能方面不是很好,調試、跟蹤困難,異常處理困難
  • 數據丟失:大併發情況下,由於日誌傳輸峰值比較大,沒有消息隊列來做緩衝,就會導致 Elasticsearch 集群丟失數據

這個架構相對上個版本略微複雜,不過維護起來同樣比較方便,同時可以滿足數據量不大且可靠性不強的業務使用。

引入消息隊列

image

該場景下麵,多個數據首先通過 Lostash Shipper Agent 來收集數據,然後經過 Output 插件將數據投遞到 Kafka 集群中,這樣當遇到 Logstash 接收數據的能力超過 Elasticsearch 集群處理能力的時候,就可以通過隊列就能起到削峰填谷的作用, Elasticsearch 集群就不存在丟失數據的問題。

目前業界在日誌服務場景中,使用比較多的兩種消息隊列為 :Kafka VS Redis。儘管 ELK Stack 官網建議使用 Redis 來做消息隊列,但是我們建議採用 Kafka 。主要從下麵兩個方面考慮:

  • 數據丟失:Redis 隊列多用於實時性較高的消息推送,並不保證可靠。Kafka保證可靠但有點延時
  • 數據堆積:Redis 隊列容量取決於機器記憶體大小,如果超過設置的Max memory,數據就會拋棄。Kafka 的堆積能力取決於機器硬碟大小。

綜合上述的理由,我們決定採用 Kafka 來緩衝隊列。不過在這種架構下仍然存在一系列問題

  • Logstash shipper 收集數據同樣會消耗 CPU 和記憶體資源
  • 不支持多機房部署

這種架構適合較大集群的應用部署,通過消息隊列解決了消息丟失、網路堵塞的問題。

多機房部署

image

隨著滬江業務的飛速增長,單機房的架構已經不能滿足需求。不可避免的,滬江的業務需要分佈到不同機房中,對於日誌服務來說也是不小的挑戰。當然業界也有不少成熟的方法,比如阿裡的單元化、騰訊的 SET 方案等等。單元化在這邊不詳細展開,大家可以參考微博的【單元化架構】

最終我們決定採用單元化部署的方式來解決 ELK 多機房中遇到的問題(延時、專線流量過大等),從日誌的產生、收集、傳輸、存儲、展示都是在同機房裡面閉環消化,不存在跨機房傳輸與調用的問題。因為交互緊密的應用儘量部署在同機房,所以這種方案並不會給業務查詢造成困擾。

Logstash、Elasticsearch、Kafka、Kibana 四個集群都部署到同一機房中,每個機房都要每個機房自己的日誌服務集群,比如A機房業務的日誌只能傳輸給本機房 Kafka ,而A機房 Indexer 集群消費並寫入到A機房 Elasticsearch 集群中,並由A機房 Kibana 集群展示,中間任何一個步驟不依賴B機房任何服務。

引入Filebeat

image

Filebeat 是基於原先 logstash-forwarder 的源碼改造出來的,無需依賴 Java 環境就能運行,安裝包10M不到。

如果日誌的量很大,Logstash 會遇到資源占用高的問題,為解決這個問題,我們引入了Filebeat。Filebeat 是基於 logstash-forwarder 的源碼改造而成,用 Golang 編寫,無需依賴 Java 環境,效率高,占用記憶體和 CPU 比較少,非常適合作為 Agent 跑在伺服器上。

下麵看看Filebeat的基本用法。編寫配置文件,從 Nginx access.log 中解析日誌數據

# filebeat.yml
filebeat.prospectors:
- input_type: log
  paths: /var/log/nginx/access.log
  json.message_key:

output.elasticsearch:
  hosts: ["localhost"]
  index: "filebeat-nginx-%{+yyyy.MM.dd}"

我們來看看壓測數據

壓測環境

  • 虛擬機 8 cores 64G記憶體 540G SATA盤
  • Logstash 版本 2.3.1
  • Filebeat 版本 5.5.0

壓測方案

Logstash / Filebeat 讀取 350W 條日誌 到 console,單行數據 580B,8個進程寫入採集文件

壓測結果

項目 workers cpu usr 總共耗時 收集速度
Logstash 8 53.7% 210s 1.6w line/s
Filebeat 8 38.0% 30s 11w line/s

Filebeat 所消耗的CPU只有 Logstash 的70%,但收集速度為 Logstash 的7倍。從我們的應用實踐來看,Filebeat 確實用較低的成本和穩定的服務質量,解決了 Logstash 的資源消耗問題。

最後,分享給大家一些血淚教訓,希望大家以我為鑒。

1. Indexer 運行一段時間後自動掛掉

突然有一天監控發現日誌不消費了,排查下來發現消費Kafka數據的indexer 掛掉了。所以,Indexer 進程也是需要用 supervisor 來監控的,保證它時刻都在運行。

2. Java異常日誌輸出

開始我們在通過 grok 切割日誌的時候,發現Java 的 Exception 日誌輸出之後,會出現換行的問題。後來使用 Logstash codec/multiline 插件來解決。

input {
    stdin {
        codec => multiline {
            pattern => "^\["
            negate => true
            what => "previous"
        }
    }
}

3. 由於時區導致日誌8小時時差

Logstash 2.3版本 date插件配置如下,查看解析結果發現@timestamp比中國時間早了8小時

解決方案 Kibana 讀取瀏覽器的當前時區,然後在頁面上轉換時間內容的顯示。

  date {
    match => [ "log_timestamp", "YYYY-MM-dd HH:mm:ss.SSS" ]
    target => "@timestamp"
  }

4.Grok parse failure

我們遇到線上node日誌突然有幾天日誌查看不出來。後來拉出原始日誌對比才發現生成出來的日誌格式不正確,同時包含 JSON 格式和非 JSON格式的日誌。但是我們用grok解析的時候採用是json格式。建議大家輸出日誌保證格式一致同時不要出現空格等異常字元,可以使用線上grok debug (http://grokdebug.herokuapp.com/) 來調試正則。

總結

基於 ELK stack 的日誌解決方案的優勢主要體現於

  • 可擴展性:採用高可擴展性的分散式系統架構設計,可以支持每日 TB 級別的新增數據。
  • 使用簡單:通過用戶圖形界面實現各種統計分析功能,簡單易用,上手快
  • 快速響應:從日誌產生到查詢可見,能達到秒級完成數據的採集、處理和搜索統計。
  • 界面炫麗:Kibana 界面上,只需要點擊滑鼠,就可以完成搜索、聚合功能,生成炫麗的儀錶板

參考資料


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • The factorial function, n! is defined thus for n a non-negative integer:0! = 1 n! = n×(n−1)! (n > 0)We say that a divides b if there exists an integer ...
  • 功能 功能 把格式化的數據寫入某個字元緩衝區。 所需頭文件 所需頭文件 stdio.h 原型 原型 int sprintf( char *buffer, const char *format, [ argument] … ); 參數列表 參數列表 buffer:char型指針,指向將要寫入的字元串的 ...
  • Python 數字數據類型用於存儲數值。 數據類型是不允許改變的,這就意味著如果改變數字數據類型得值,將重新分配記憶體空間。 以下實例在變數賦值時 Number 對象將被創建: 您也可以使用del語句刪除一些數字對象的引用。 del語句的語法是: 您可以通過使用del語句刪除單個或多個對象的引用,例如 ...
  • 生成一個簽章(用java.awt畫一個簽章) 並添加到pdf 公章處package com.bjpowernode.p2p.admin.util;import java.awt.BasicStroke;import java.awt.Color;import java.awt.Font;import ...
  • 1.類和對象 概念:對象是實例,類是一組具有相同行為和屬性的對象的集合; 區別:類是對象的抽象,對象是類的實例化 2.如何聲明一個類: 語法: 修飾符 class 類名{ //類的屬性(數據類型 變數名;) //類的方法(修飾符 返回類型 方法名(參數列表){}) } 舉例: public clas ...
  • 1.抽象類; 定義;包含一個抽象方法的類稱稱為抽象類,抽象類在class前使用adstract關鍵詞修飾。 抽象方法;只聲明未實現的方法稱為抽象方法,使用adstract關鍵字聲明該方法。 抽象類定義語法: adstract class 抽象類類名{ 屬性: 普通方法: 訪問修飾符 adstract ...
  • 從一個任務開始講 某天,公司領導找到開發人員,說要開發一個微信支付寶的收款明細獲取功能,我們把這個任務作為一個案例進行說明。 第一步:設計 案例精簡:把任務指派給開發人員完成。本句話中,有兩個名詞:“任務”和“開發人員”,所以我們考慮設計兩個對象(任務和開發人員)。 開發人員對象: 任務對象: 場景 ...
  • 定義:設計模式是一套被反覆使用、多數人知曉的、經過分類的、代碼設計經驗的總結。 目的:為了代碼可重用性、讓代碼更容易被他人理解、保證代碼可靠性,設計模式使代碼編寫真正工程化。 使用:每一種設計模式都是在特定場景下總結出來的,選用時需要根據特定的場景選擇,不能為了模式而模式。 定義:設計模式是一套被反 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...