AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

從 Dapper 到 OpenTelemetry:分布式追蹤的演進之旅

來源: 責編: 時間:2024-06-07 17:20:36 206觀看
導讀從基本概念到如何部署 demo 實戰了解 OpenTelemetry,從那個 demo 中也可以得知整個 OpenTelemetry 體系的復雜性,包含了太多的組件和概念。為了能更清晰的了解每個關鍵組件的作用以及原理,我打算分為幾期來講解 OpenTele

FFv28資訊網——每日最新資訊28at.com

從基本概念到如何部署 demo 實戰了解 OpenTelemetry,從那個 demo 中也可以得知整個 OpenTelemetry 體系的復雜性,包含了太多的組件和概念。FFv28資訊網——每日最新資訊28at.com

為了能更清晰的了解每個關鍵組件的作用以及原理,我打算分為幾期來講解 OpenTelemetry 的三個核心組件:FFv28資訊網——每日最新資訊28at.com

  • Trace
  • Metrics
  • Logs

首先以 Trace 講起。FFv28資訊網——每日最新資訊28at.com

Trace

開始之前還是先復習一下 Trace 的歷史背景。FFv28資訊網——每日最新資訊28at.com

如今現代的分布式追蹤的起源源自于 Google 在 2010 年發布的一篇論文:FFv28資訊網——每日最新資訊28at.com

  • Dapper, a Large-Scale Distributed Systems Tracing Infrastructure

在這篇論文中提出了分布式追蹤的幾個核心概念:FFv28資訊網——每日最新資訊28at.com

  • Trace
  • Span
  • Span 的一些基礎數據結構
  • 可視化追蹤以及展示

之后 Twitter 受到了 Dapper 的啟發開源了現在我們熟知的 Zipkin,包含了存儲和可視化 UI 展示我們的追蹤鏈路。FFv28資訊網——每日最新資訊28at.com

Uber 也在 2015 年開源了 Jaeger 項目,它的功能和 Zipkin 類似,但目前我們用的較多的還是 Jaeger;現在已經成為 CNCF 的托管項目。FFv28資訊網——每日最新資訊28at.com

之后陸續出現過 OpenTracing 和 OpenCensus 項目,他們都企圖統一分布式追蹤這一領域。FFv28資訊網——每日最新資訊28at.com

直到 OpenTelemetry 的出現整合了以上兩個項目,并且逐漸成為可觀測領域的標準。FFv28資訊網——每日最新資訊28at.com

更多歷史背景可以參考之前的文章:OpenTelemetry 實踐指南:歷史、架構與基本概念FFv28資訊網——每日最新資訊28at.com

FFv28資訊網——每日最新資訊28at.com

FFv28資訊網——每日最新資訊28at.com

這里我們結合 Dapper 論文中的資料進行分析,在這個調用中用戶發起了一次請求,內部系統經歷了 4 次 RPC 調用。FFv28資訊網——每日最新資訊28at.com

從第二張圖會看到一些關鍵信息:FFv28資訊網——每日最新資訊28at.com

  • spanName
  • parentId
  • spanId

parentId 很好理解,主要是定義調用的主次關系;要注意的是并行調用時 parentId 是同一個。FFv28資訊網——每日最新資訊28at.com

spanId 在可以理解為每一個獨立的操作,在這里就是一次 RPC 調用;同理一次數據庫操作、消息的收發都是一個 span。FFv28資訊網——每日最新資訊28at.com

span 的更多內容在后文繼續講解。FFv28資訊網——每日最新資訊28at.com

Span

FFv28資訊網——每日最新資訊28at.com

當我們把某一個具體的 span 放大會看到更加詳細的信息,其中最關鍵的如下:FFv28資訊網——每日最新資訊28at.com

  • traceId
  • spanName
  • spanId
  • parentId
  • 開始時間
  • 結束時間

由于一個完整的 trace 鏈路由 N 個 span 組成,所以這個鏈路必須得有一個唯一的 traceId 將這些 span 串聯起來。這樣才可以在可視化的時候更好的展示鏈路信息。FFv28資訊網——每日最新資訊28at.com

以上的這些字段很容易理解,都是一些必須的信息。FFv28資訊網——每日最新資訊28at.com

在 Dapper 論文中使用 Annotations 來存放 span 的屬性,也就是剛才那些字段,當然也可以自定義存放一些數據,比如圖中的 "foo"FFv28資訊網——每日最新資訊28at.com

OpenTelemetry 中的 Span

OpenTelemetry 的 trace 自然也是基于 Dapper 的,只是額外做了一些優化,比如在剛才那些字段的基礎上新增了一些概念:FFv28資訊網——每日最新資訊28at.com

{  "name": "/v1/sys/health",  "context": {    "trace_id": "7bba9f33312b3dbb8b2c2c62bb7abe2d",    "span_id": "086e83747d0e381e"  },  "parent_id": "",  "start_time": "2021-10-22 16:04:01.209458162 +0000 UTC",  "end_time": "2021-10-22 16:04:01.209514132 +0000 UTC",  "status_code": "STATUS_CODE_OK",  "status_message": "",  "attributes": {    "net.transport": "IP.TCP",    "net.peer.ip": "172.17.0.1",    "net.peer.port": "51820",    "net.host.ip": "10.177.2.152",    "net.host.port": "26040",    "http.method": "GET",    "http.target": "/v1/sys/health",    "http.server_name": "mortar-gateway",    "http.route": "/v1/sys/health",    "http.user_agent": "Consul Health Check",    "http.scheme": "http",    "http.host": "10.177.2.152:26040",    "http.flavor": "1.1"  },  "events": [    {      "name": "",      "message": "OK",      "timestamp": "2021-10-22 16:04:01.209512872 +0000 UTC"    }  ]}

以這個 JSON 為例,新增了:FFv28資訊網——每日最新資訊28at.com

  • [ ] Span Context
  • Span 的上下文,存放的都是不可變的數據,因為每個 Span 之間是存在關聯關系的,這些關聯關系都是存放在 context 中,主要就是 trace_id, span_id.
  • Attributes: 可以理解為 Dapper 中的 Annotations,存放的是我們自定義的鍵值對,通常是由我們常用第三方開源 Instrumentation 內置的一些屬性。
  • Span Events: Span 的一些關鍵事件。

FFv28資訊網——每日最新資訊28at.com

比如我們常用的 Redis 客戶端 lettuce,它就會自己記錄一些 Attributes。FFv28資訊網——每日最新資訊28at.com

如果有多個 span 存在依賴關系:FFv28資訊網——每日最新資訊28at.com

[Span A]  ←←←(the root span)            |     +------+------+     |             | [Span B]      [Span C] ←←←(Span C is a `child` of Span A)     |             | [Span D]      +---+-------+               |           |           [Span E]    [Span F]

大部分的可視化工具都是以時間線的方式進行展示:FFv28資訊網——每日最新資訊28at.com

––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–> time [Span A···················································]   [Span B··········································]      [Span D······································]    [Span C····················································]         [Span E·······]        [Span F··]

這些和 Dapper 中描述的概念沒有本質區別。FFv28資訊網——每日最新資訊28at.com

Span Status

Span 還內置了一些 Status:FFv28資訊網——每日最新資訊28at.com

  • Unset
  • Error
  • Ok

默認情況下是 Unset,出現錯誤時則是 Error,一切正常時則是 Ok。FFv28資訊網——每日最新資訊28at.com

FFv28資訊網——每日最新資訊28at.com

通過可視化頁面很容易得知某個 trace 中 span 的異常情況,點進去后可以看到具體的異常 span 以及它的錯誤日志。FFv28資訊網——每日最新資訊28at.com

Span Kind

最后是 Span 的類型:FFv28資訊網——每日最新資訊28at.com

  • Client
  • Server
  • Internal
  • Producer
  • Consumer

FFv28資訊網——每日最新資訊28at.com

Client 和 Server 非常好理解,比如我們有一個 gRPC 接口,調用方的 Span 是 client,而服務端的 Span 自然就是 Server。FFv28資訊網——每日最新資訊28at.com

Internal 則是內部組件調用產生的 Span,這類 Span 相對會少一些。FFv28資訊網——每日最新資訊28at.com

Producer 和 Consumer 一般指的是發起異步調用時的 Span,我們常見的就是往消息隊列里生產和消費消息。FFv28資訊網——每日最新資訊28at.com

通過這幾種類型的 Span 也可以了解到什么情況下會創建 Span,通常是以下幾種場景:FFv28資訊網——每日最新資訊28at.com

  • RPC 調用
  • 數據庫(Redis、MySQL、Mongo 等等)操作
  • 生產和消費消息
  • 有意義的內部調用

通常在一個函數內部再調用其他的本地函數是不用創建 span 的,不然這個鏈路會非常的長。FFv28資訊網——每日最新資訊28at.com

Annotations

當然也有一些特殊情況,比如我的某個內部函數非常重要,需要單獨關心它的調用時長。FFv28資訊網——每日最新資訊28at.com

此時我們就可以使用 Annotations 來單獨創建自己的 Span。FFv28資訊網——每日最新資訊28at.com

這個 Annotations 和 Dapper 中的不是同一個,只是 Java 中的注解。FFv28資訊網——每日最新資訊28at.com

@Override  public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseObserver) {      Executors.newFixedThreadPool(1).execute(() -> {          myMethod(request.getName());      });            HelloReply reply = HelloReply.newBuilder()              .setMessage("Hello ==> " + request.getName())              .build();      responseObserver.onNext(reply);      responseObserver.onCompleted();  }    @SneakyThrows  @WithSpan  public void myMethod(@SpanAttribute("request.name") String name) {      TimeUnit.SECONDS.sleep(1);      log.info("myMethod:{}", name);  }

以這段代碼為例,這是一個 gRPC 的服務端接口,在這個接口中調用了一個函數 myMethod,默認情況下并不會為它單獨創建一個 Span。FFv28資訊網——每日最新資訊28at.com

但如果我們想單獨記錄它,就可以使用 @WithSpan 這個注解,同時也可以使用  @SpanAttribute 來自定義 attribute。FFv28資訊網——每日最新資訊28at.com

最終的效果如下:FFv28資訊網——每日最新資訊28at.com

FFv28資訊網——每日最新資訊28at.com

此時就會單獨為這個函數創建一個 Span。FFv28資訊網——每日最新資訊28at.com

需要單獨引入一個依賴:FFv28資訊網——每日最新資訊28at.com

<dependencies>  <dependency>    <groupId>io.opentelemetry.instrumentation</groupId>    <artifactId>opentelemetry-instrumentation-annotations</artifactId>    <version>2.3.0</version>  </dependency></dependencies>

Context Propagation

上下文傳播也是 Trace 中非常重要的概念,剛才提到了每個 Span 都有自己不可變的上下文,那么后續的 Span 如何和上游的 Span 進行關聯呢?FFv28資訊網——每日最新資訊28at.com

這里有兩種情況:FFv28資訊網——每日最新資訊28at.com

  • 同一進程
  • 垮進程

同一進程

同一個進程也分為兩種情況:FFv28資訊網——每日最新資訊28at.com

  • 單線程
  • 多線程

單線程的比較好處理,我們只需要把數據寫入 ThreadLocal 中就可以做到線程隔離。FFv28資訊網——每日最新資訊28at.com

private static final ThreadLocal<Context> THREAD_LOCAL_STORAGE = new ThreadLocal<>();@Override  @Nullable  public Context current() {    return THREAD_LOCAL_STORAGE.get();  }

這點我們可以通過源碼 io.opentelemetry.context.ThreadLocalContextStorage看到具體的實現過程。FFv28資訊網——每日最新資訊28at.com

而如果是多線程時:FFv28資訊網——每日最新資訊28at.com

Executors.newFixedThreadPool(1).execute(() -> {      myMethod(request.getName());  });

則需要對使用的線程池進行單獨處理,將父線程中 threadlocal 中的數據拷貝出來進行傳遞,比如有阿里提供的 TransmittableThreadLocal,可以提供對線程池的支持。FFv28資訊網——每日最新資訊28at.com

跨進程

而如果是垮進程的場景,就需要將 context 的信息進行序列化傳遞。FFv28資訊網——每日最新資訊28at.com

如果是 gRPC 調用會將信息存放到 metadata 中。FFv28資訊網——每日最新資訊28at.com

HTTP 調用則是存放在 header 中。FFv28資訊網——每日最新資訊28at.com

消息隊列,比如 Pulsar 也可以將數據存放在消息中的 header 中進行傳遞。FFv28資訊網——每日最新資訊28at.com

數據一旦跨進程傳輸成功后,就和單進程一樣的處理方式了。FFv28資訊網——每日最新資訊28at.com

Baggage

FFv28資訊網——每日最新資訊28at.com

有時候我們需要通過垮 Span 傳遞信息,比如如上圖所示:我們需要在 serverB 中拿到 serverA 中收到的一個請求參數:http://127.0.0.1:8181/request/?name/=1232。FFv28資訊網——每日最新資訊28at.com

FFv28資訊網——每日最新資訊28at.com

這個數據默認會作為 span 的 attribute ,但只會存在于第一個 span。FFv28資訊網——每日最新資訊28at.com

如果我們想要在后續的 span 中也能拿到這個數據,甚至是垮進程也能獲取到。FFv28資訊網——每日最新資訊28at.com

那就需要使用 Baggage 這個對象了。FFv28資訊網——每日最新資訊28at.com

它的使用也很簡單:FFv28資訊網——每日最新資訊28at.com

@RequestMapping("/request")  public String request(@RequestParam String name) {   // 寫入    Baggage.current().toBuilder().            put("request.name", name).build()            .storeInContext(Context.current()).makeCurrent();}         // 獲取String value = Baggage.current().getEntryValue("request.name");  log.info("request.name: {}", value);

只要是屬于同一個 trace 的調用就可以直接獲取到數據。FFv28資訊網——每日最新資訊28at.com

FFv28資訊網——每日最新資訊28at.com

traceId 也是垮 Span 傳遞的。FFv28資訊網——每日最新資訊28at.com

而它的原理也是通過往 context 中寫入數據實現的:FFv28資訊網——每日最新資訊28at.com

@Immutable  class BaggageContextKey {    static final ContextKey<Baggage> KEY = ContextKey.named("opentelemetry-baggage-key");      private BaggageContextKey() {}  }

FFv28資訊網——每日最新資訊28at.com

而這個 context 是通過一個 entries 數據存儲數據的,不管是在內部還是外部的跨進程調用,OpenTelemetry 都會將 context 通過 Context Propagation 傳遞出去。FFv28資訊網——每日最新資訊28at.com

總結

Trace 這部分的內容我覺得比 Metrics 和 Logs 更加復雜一些,畢竟多了一些數據結構;現在的內容也只是冰山一角,現在也在做 trace 的一些定制化開發,后續有新的進展會接著更新。FFv28資訊網——每日最新資訊28at.com

參考鏈接:FFv28資訊網——每日最新資訊28at.com

  • https://static.googleusercontent.com/media/research.google.com/zh-CN//archive/papers/dapper-2010-1.pdf。
  • https://opentelemetry.io/docs/languages/java/automatic/annotations/。
  • https://opentelemetry.io/docs/specs/otel/overview/#tracing-signal。
  • https://opentelemetry.io/docs/concepts/context-propagation/。
  • https://opentelemetry.io/docs/concepts/observability-primer/#distributed-traces。
  • https://tech.meituan.com/2023/04/20/traceid-google-dapper-mtrace.html。

本文鏈接:http://www.tebozhan.com/showinfo-26-92748-0.html從 Dapper 到 OpenTelemetry:分布式追蹤的演進之旅

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: React 19 出手解決了異步請求的競態問題,是好事還是壞事?

下一篇: 華為回應“投資柔宇”:未有此計劃,也未提出投資要求

標簽:
  • 熱門焦點
Top