1. 程式人生 > 其它 >Databend 全鏈路追蹤

Databend 全鏈路追蹤

全鏈路追蹤意味著能夠追蹤到每一個呼叫請求的完整呼叫鏈路、收集效能資料並反饋異常。Databend 使用 tracing 賦能可觀測性,實現全鏈路追蹤。

Databend 與 Tracing

初步瞭解 Databend 怎麼實現全鏈路追蹤。

初識 Tracing

Tracing 是由 Tokio 團隊維護的 Rust 應用跟蹤框架,用來收集結構化的、基於事件的診斷資訊。

專案地址:https://github.com/tokio-rs/tracing

示例:

use tracing::{info, Level};
use tracing_subscriber;

fn main() {
    let collector = tracing_subscriber::fmt()
        // filter spans/events with level TRACE or higher.
        .with_max_level(Level::TRACE)
        // build but do not install the subscriber.
        .finish();

    tracing::collect::with_default(collector, || {
        info!("This will be logged to stdout");
    });
    info!("This will _not_ be logged to stdout");
}

Databend 中的 Tracing

Databend 的 tracing-subscriber 被統一整合在 common/tracing,由 query 和 meta 共用。

// Use env RUST_LOG to initialize log if present.
// Otherwise use the specified level.
let directives = env::var(EnvFilter::DEFAULT_ENV).unwrap_or_else(|_x| level.to_string());
let env_filter = EnvFilter::new(directives);
let subscriber = Registry::default()
    .with(env_filter)                # 根據環境變數過濾
    .with(JsonStorageLayer)          # 利用 tracing-bunyan-formatter 格式化為 json
    .with(stdout_logging_layer)      # 標準輸出
    .with(file_logging_layer)        # 輸出到檔案,預設位於 `_logs` 目錄下
    .with(jaeger_layer);             # opentelemetry-jaeger

#[cfg(feature = "console")]
let subscriber = subscriber.with(console_subscriber::spawn()); # tokio console

tracing::subscriber::set_global_default(subscriber)
    .expect("error setting global tracing subscriber");

具體到內部的 tracing 記錄,大致有兩類:

  • 普通:與其他 log 方式一樣,利用 info!、debug! 來收集資訊。
use common_tracing::tracing;

tracing::info!("{:?}", conf);
tracing::info!("DatabendQuery {}", *databend_query::DATABEND_COMMIT_VERSION);
  • Instruments:在呼叫函式時建立並進入 tracing span(跨度),span 表示程式在特定上下文中執行的時間段。
use common_tracing::tracing::debug_span;
#[tracing::instrument(level = "debug", skip_all)]
async fn read(&mut self) -> Result<Option<DataBlock>> {
    ...
        fetched_metadata = read_metadata_async(&mut self.reader)
            .instrument(debug_span!("parquet_source_read_meta"))
            .await
            .map_err(|e| ErrorCode::ParquetError(e.to_string()))?;
    ...
}

示例:

{
  "v": 0,
  "name": "[email protected]:3307",
  "msg": "Shutdown server.",
  "level": 30,
  "hostname": "dataslime",
  "pid": 53341,
  "time": "2022-05-11T00:51:56.374807359Z",
  "target": "databend_query",
  "line": 153,
  "file": "query/src/bin/databend-query.rs"
}

觀測 Databend 追蹤的方式

Databend 原生提供了多種觀測方式,以方便診斷和除錯:

  • http tracing :訪問 localhost:8080/v1/logs(根據配置)

  • stdout/filelog :檢查終端輸出或 _logs 目錄(根據配置)

  • system.tracing 表 :執行 select * from system.tracing limit 20;

  • jaeger :執行 jaeger ,訪問 http://127.0.0.1:16686/

  • console :按特定方式構建後,執行 tokio-console

Jaeger 分散式追蹤

使用 Jaeger 對 Databend 進行全鏈路追蹤。

Opentelemetry & Jaeger

OpenTelemetry 是工具、API 和 SDK 的集合。使用它來檢測、生成、收集和匯出遙測資料(度量、日誌和追蹤),以幫助您分析軟體的效能和行為。Jaeger 是一個開源的端到端分散式追蹤系統。由 Uber 捐贈給 CNCF 。它可以用於監視基於微服務的分散式系統,提供以下能力:

  • 分散式上下文傳播
  • 分散式事務監視
  • 根本原因分析
  • 服務依賴性分析
  • 效能/延遲優化

Step by Step

遵循下述步驟,即可使用 Jaeger 探索 Databend :

  • 構建二進位制程式:cargo build(可以使用 --bin 指定)
  • 將日誌級別設定為 DEBUG ,執行需要除錯的應用程式。例如,LOG_LEVEL=DEBUG ./databend-query
  • 執行 jaeger :docker run -d -p6831:6831/udp -p6832:6832/udp -p16686:16686 jaegertracing/all-in- one:latest
  • 開啟 http://127.0.0.1:16686/ 以檢視 jaeger 收集的資訊

結果探索

x 軸是執行時刻,y 軸是持續的時間,圓點反映 span 的聚集程度。
執行下述語句即可得到上圖所示追蹤結果:

CREATE TABLE t1(a INT);
INSERT INTO t1 VALUES(1);
INSERT INTO t1 SELECT * FROM t1;

Timeline

下圖是點選最大的圓點得到的追蹤情況:

使用 timeline 模式來展現 tracing 的各個跨度之間的關係。以時間為主線進行分析,方便使用者觀看在某個時間點觀看程式資訊。

點開第一個跨度,可以看到這是執行 INSERT INTO t1 SELECT *FROM t1 查詢時的情況。

Graph

切換到 graph 模式,可以看到各個 span 之間的呼叫鏈,每個 span 具體用時 ,以及百分比。

通過這個檢視使用者很容易知道系統瓶頸,快速定位問題。

Compare

連起來的各個部分形成整個 trace 的呼叫鏈。因為比較時一般會比較兩個相同型別的呼叫,所以看到的會是重合後的檢視。

對於顏色的一個說明:

  • 深綠色,表示這個 span 只存在於 trace-B 中,A 沒有這個 span
  • 深紅色,表示這個 span 只存在於 trace-A 中,B 沒有這個 span
  • 淺綠色,表示這個 span 在 trace-B(右邊這個)的數量多
  • 淺紅色,表示這個 span 在 trace-A(左邊這個)的數量多

tokio-console 診斷

tokio-console 診斷

tokio-rs 團隊出品的診斷和除錯工具,可以幫助我們診斷與 tokio 執行時相關的問題。

console 是什麼

tokio-console 是專為非同步程式設計的除錯與診斷工具,能夠列出 tokio 的任務,提供對程式的任務和資源的實時、易於導航的檢視,總結了它們的當前狀態和歷史行為。主要包含以下元件:

  • 傳輸診斷資料的協議
  • 用於收集診斷資料的儀器
  • 當然,用於展示和探索診斷資料的實用工具\

專案地址:https://github.com/tokio-rs/console

Step by Step

  • 使用特定的 rustflags 和 features 來構建:RUSTFLAGS="--cfg tokio_unstable" cargo build --features tokio-console ,也可以只構建單個二進位制程式,使用 --bin 進行指定。
  • 將日誌級別設定為 TRACE ,執行需要除錯的應用程式 LOG_LEVEL=TRACE databend-query 或者 databend-meta --single --log-level=TRACE。可以使用 TOKIO_CONSOLE_BIND 指定埠,以避免潛在的埠搶佔問題。
  • 執行 tokio-console,預設連線到 http://127.0.0.1:6669

結果探索

任務
先看什麼是 tokio 任務:

  • 任務是一個輕量級的、非阻塞的執行單元。類似作業系統的執行緒,但是是由 tokio 執行時管理,一般叫做“綠色執行緒”,與 Go 的 goroutine,Kotlin 的 coroutine 類似。
  • 任務是協同排程的。大多數作業系統實現搶佔式多工。作業系統允許每個執行緒執行一段時間,然後搶佔它,暫停該執行緒並切換到另一個執行緒。另一方面,任務實現協同多工。一個任務被允許執行直到它讓出執行權,執行時會切換到執行下一個任務。

基礎檢視

通過左右切換,可以得到總忙時間或輪詢次數等指標對任務進行排序。控制檯通過高亮來提示較大差異,比如從毫秒到秒的切換。

控制檯還實現了一個“警告”系統。通過監視應用程式中任務的執行時操作,控制檯可以檢測可能提示 bug 或效能問題的行為模式,並突出顯示這些行為模式供使用者分析。比如已經運行了很長時間而沒有讓步的任務,喚醒的次數比被其他任務喚醒的次數還要多的任務。

任務檢視

上下切換選中任務,enter 檢視關於每個任務的翔實資料,比如輪詢持續時間的直方圖。

不僅列出任務。console 還會插入非同步互斥和訊號量等資源。Tokio Console 的資源詳細資訊檢視顯示了哪些任務已經進入臨界區,哪些任務正在等待獲得訪問許可權。

還能做什麼

還能做什麼

與分散式追蹤和日誌系統相關的一些其他內容。

可觀測性 + +

目前還有一系列關於可觀測性和 Tracing 的 Issue 有待解決:

  • Integrate tokio metrics for query task based tokio runtime monitoring #4205
  • Configure on jaeger tracing address similar to metrics api server #3633
  • Summary of todos about distributed tracing #1227
  • Query traces and analysis, based on user behavior. #1177
  • Http stack traces #1085
  • Shuffle read/write metrics #1004

另外,更進一步的考量是,如何基於可觀測性來自動/半自動地發現問題並對系統進行調優。瞭解更多

瞭解更多

Tracing

Jaeger

tokio-console

關於 Databend

Databend 是一款開源、彈性、低成本,基於物件儲存也可以做實時分析的新式數倉。期待您的關注,一起探索雲原生數倉解決方案,打造新一代開源 Data Cloud。


文章首發於公眾號:Databend