国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

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

開發 前端
從基本概念到如何部署 demo 實戰了解 OpenTelemetry,從那個 demo 中也可以得知整個 OpenTelemetry 體系的復雜性,包含了太多的組件和概念。

從基本概念到如何部署 demo 實戰了解 OpenTelemetry,從那個 demo 中也可以得知整個 OpenTelemetry 體系的復雜性,包含了太多的組件和概念。

為了能更清晰的了解每個關鍵組件的作用以及原理,我打算分為幾期來講解 OpenTelemetry 的三個核心組件:

  • Trace
  • Metrics
  • Logs

首先以 Trace 講起。

Trace

開始之前還是先復習一下 Trace 的歷史背景。

如今現代的分布式追蹤的起源源自于 Google 在 2010 年發布的一篇論文:

  • Dapper, a Large-Scale Distributed Systems Tracing Infrastructure

在這篇論文中提出了分布式追蹤的幾個核心概念:

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

之后 Twitter 受到了 Dapper 的啟發開源了現在我們熟知的 Zipkin,包含了存儲和可視化 UI 展示我們的追蹤鏈路。

Uber 也在 2015 年開源了 Jaeger 項目,它的功能和 Zipkin 類似,但目前我們用的較多的還是 Jaeger;現在已經成為 CNCF 的托管項目。

之后陸續出現過 OpenTracing 和 OpenCensus 項目,他們都企圖統一分布式追蹤這一領域。

直到 OpenTelemetry 的出現整合了以上兩個項目,并且逐漸成為可觀測領域的標準。

更多歷史背景可以參考之前的文章:OpenTelemetry 實踐指南:歷史、架構與基本概念

這里我們結合 Dapper 論文中的資料進行分析,在這個調用中用戶發起了一次請求,內部系統經歷了 4 次 RPC 調用。

從第二張圖會看到一些關鍵信息:

  • spanName
  • parentId
  • spanId

parentId 很好理解,主要是定義調用的主次關系;要注意的是并行調用時 parentId 是同一個。

spanId 在可以理解為每一個獨立的操作,在這里就是一次 RPC 調用;同理一次數據庫操作、消息的收發都是一個 span。

span 的更多內容在后文繼續講解。

Span

當我們把某一個具體的 span 放大會看到更加詳細的信息,其中最關鍵的如下:

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

由于一個完整的 trace 鏈路由 N 個 span 組成,所以這個鏈路必須得有一個唯一的 traceId 將這些 span 串聯起來。這樣才可以在可視化的時候更好的展示鏈路信息。

以上的這些字段很容易理解,都是一些必須的信息。

在 Dapper 論文中使用 Annotations 來存放 span 的屬性,也就是剛才那些字段,當然也可以自定義存放一些數據,比如圖中的 "foo"

OpenTelemetry 中的 Span

OpenTelemetry 的 trace 自然也是基于 Dapper 的,只是額外做了一些優化,比如在剛才那些字段的基礎上新增了一些概念:

{
  "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 為例,新增了:

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

比如我們常用的 Redis 客戶端 lettuce,它就會自己記錄一些 Attributes。

如果有多個 span 存在依賴關系:

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

大部分的可視化工具都是以時間線的方式進行展示:

––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–> time

 [Span A···················································]
   [Span B··········································]
      [Span D······································]
    [Span C····················································]
         [Span E·······]        [Span F··]

這些和 Dapper 中描述的概念沒有本質區別。

Span Status

Span 還內置了一些 Status:

  • Unset
  • Error
  • Ok

默認情況下是 Unset,出現錯誤時則是 Error,一切正常時則是 Ok。

通過可視化頁面很容易得知某個 trace 中 span 的異常情況,點進去后可以看到具體的異常 span 以及它的錯誤日志。

Span Kind

最后是 Span 的類型:

  • Client
  • Server
  • Internal
  • Producer
  • Consumer

Client 和 Server 非常好理解,比如我們有一個 gRPC 接口,調用方的 Span 是 client,而服務端的 Span 自然就是 Server。

Internal 則是內部組件調用產生的 Span,這類 Span 相對會少一些。

Producer 和 Consumer 一般指的是發起異步調用時的 Span,我們常見的就是往消息隊列里生產和消費消息。

通過這幾種類型的 Span 也可以了解到什么情況下會創建 Span,通常是以下幾種場景:

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

通常在一個函數內部再調用其他的本地函數是不用創建 span 的,不然這個鏈路會非常的長。

Annotations

當然也有一些特殊情況,比如我的某個內部函數非常重要,需要單獨關心它的調用時長。

此時我們就可以使用 Annotations 來單獨創建自己的 Span。

這個 Annotations 和 Dapper 中的不是同一個,只是 Java 中的注解。

@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。

但如果我們想單獨記錄它,就可以使用 @WithSpan 這個注解,同時也可以使用  @SpanAttribute 來自定義 attribute。

最終的效果如下:

此時就會單獨為這個函數創建一個 Span。

需要單獨引入一個依賴:

<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 進行關聯呢?

這里有兩種情況:

  • 同一進程
  • 垮進程

同一進程

同一個進程也分為兩種情況:

  • 單線程
  • 多線程

單線程的比較好處理,我們只需要把數據寫入 ThreadLocal 中就可以做到線程隔離。

private static final ThreadLocal<Context> THREAD_LOCAL_STORAGE = new ThreadLocal<>();

@Override  
@Nullable  
public Context current() {  
  return THREAD_LOCAL_STORAGE.get();  
}

這點我們可以通過源碼 io.opentelemetry.context.ThreadLocalContextStorage看到具體的實現過程。

而如果是多線程時:

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

則需要對使用的線程池進行單獨處理,將父線程中 threadlocal 中的數據拷貝出來進行傳遞,比如有阿里提供的 TransmittableThreadLocal,可以提供對線程池的支持。

跨進程

而如果是垮進程的場景,就需要將 context 的信息進行序列化傳遞。

如果是 gRPC 調用會將信息存放到 metadata 中。

HTTP 調用則是存放在 header 中。

消息隊列,比如 Pulsar 也可以將數據存放在消息中的 header 中進行傳遞。

數據一旦跨進程傳輸成功后,就和單進程一樣的處理方式了。

Baggage

有時候我們需要通過垮 Span 傳遞信息,比如如上圖所示:我們需要在 serverB 中拿到 serverA 中收到的一個請求參數:http://127.0.0.1:8181/request\?name\=1232。

這個數據默認會作為 span 的 attribute ,但只會存在于第一個 span。

如果我們想要在后續的 span 中也能拿到這個數據,甚至是垮進程也能獲取到。

那就需要使用 Baggage 這個對象了。

它的使用也很簡單:

@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 的調用就可以直接獲取到數據。

traceId 也是垮 Span 傳遞的。

而它的原理也是通過往 context 中寫入數據實現的:

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

而這個 context 是通過一個 entries 數據存儲數據的,不管是在內部還是外部的跨進程調用,OpenTelemetry 都會將 context 通過 Context Propagation 傳遞出去。

總結

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

參考鏈接:

  • 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。
責任編輯:姜華 來源: crossoverJie
相關推薦

2024-08-21 08:09:17

2013-06-07 13:46:29

分布式存儲自動化運維

2021-04-29 19:07:33

Redis演進微服務

2024-06-14 08:19:45

2022-06-14 15:28:37

數據庫存儲系統變革趨勢

2024-04-22 08:10:29

2024-05-16 07:51:55

分布式系統架構

2021-11-26 06:43:19

Java分布式

2018-04-03 09:27:42

分布式架構系統

2017-09-01 05:35:58

分布式計算存儲

2022-12-04 22:41:15

IPC分布式機制

2022-03-25 08:40:32

分布式架構

2020-12-16 09:24:18

Skywalking分布式鏈路追蹤

2024-06-07 13:04:31

2020-03-09 08:24:06

TengineWeb代理服務器

2018-10-18 08:15:27

開源分布式追蹤工具

2023-08-18 09:00:00

Kubernetes數據庫SQL

2021-11-29 08:18:22

架構互聯網分布式

2020-10-20 09:38:15

分布式存儲Ceph

2022-09-25 22:19:24

Dapr分布式追蹤
點贊
收藏

51CTO技術棧公眾號

精品72久久久久中文字幕| 亚洲婷婷在线视频| 日产日韩在线亚洲欧美| 国产污视频在线播放| 图片区小说区区亚洲影院| 免费一级特黄毛片| 激情欧美一区二区三区在线观看| 动漫3d精品一区二区三区 | 91在线看片| 亚洲一区二区欧美激情| 国产三级国产精品国产专区50| 成人精品国产福利| av在线播放天堂| 国产很黄免费观看久久| 中国一区二区三区| 日韩av在线发布| 国产一区二区自拍| 国产精品www.| 成人av在线网址| 91久久夜色精品国产按摩| 国产成人精品一区二区| 在线亚洲a色| 国产成人精品999| 精品99在线| 91精品视频一区| 午夜精品影院| 国内外成人免费视频| 亚洲国产一区二区三区高清| 亚洲xxx大片| 99亚洲一区二区| 免费久久99精品国产自| 日精品一区二区三区| 亚欧精品在线| 福利电影一区二区三区| 成人免费aaa| 日本一区二区三区四区| www.成人69.com| 午夜精品福利一区二区蜜股av| 中文在线一二区| 在线观看一区二区视频| 黄网址在线观看| 亚洲精品自产拍| 免费精品一区| 国产精品久久久久久久午夜| 欧美在线亚洲综合一区| 欧美国产综合视频| 国产精品一区二区91| 婷婷六月天在线| 精品动漫一区二区| 欧美色图天堂| 久久视频在线视频| 国产免费久久| 久久伊人资源站| 成人久久久精品乱码一区二区三区| 国产又猛又黄的视频| 欧美日韩国产精品一区二区三区四区| 久草免费在线观看| 久久人人爽人人爽人人片亚洲| 在线视频亚洲专区| 六月婷婷久久| 99re成人精品视频| 在线观看免费av网| 亚洲成人国产精品| 国偷自产av一区二区三区| 丁香五月网久久综合| 成人毛片老司机大片| 黄页免费在线| 亚洲欧美999| 精品国产一区二区三区av片| 国产精品视频免费观看| 久久99热99| www.三区| 欧美成人video| 欧美理论电影在线精品| 欧美极品一区| 国产精品国产三级国产| 成人全视频高清免费观看| 中文字幕日韩欧美| 91精品婷婷色在线观看| 特大黑人娇小亚洲女mp4| 夜夜精品浪潮av一区二区三区| 中文国产字幕在线观看| 国内偷自视频区视频综合| 久久久蜜桃一区二区人| 国产区二区三区| 精品国产伦一区二区三区观看方式| 视频国产精品| 亚洲国产成人不卡| 亚洲18女电影在线观看| 日本一区二区三区中文字幕| 国产成人精品免费视频大全最热| 久久嫩草精品久久久精品一| 午夜视频在线观看免费视频| 欧美美女操人视频| 日韩中文字幕1| 天堂在线观看一卡二卡三卡四卡| 亚洲欧洲在线免费| 国产婷婷精品| 男女激情网站| 精品国模在线视频| 日本女优在线视频一区二区| 亚洲aⅴ优女av综合久久久| 欧美激情欧美激情在线五月| 美女视频一区二区| 77导航福利在线| 国产精品第3页| 国产亚洲一区字幕| 欧美日韩免费看片| 欧美日韩高清免费| 色婷婷精品大在线视频| 亚洲色图丝袜| 久久久精品在线视频| 亚洲成年人在线播放| 91久久夜色精品国产九色| 免费裸体视频网站| 欧美一级淫片aaaaaaa视频| 91欧美激情一区二区三区成人| 九色porny丨国产首页在线| 国内一区在线| 欧美亚洲综合色| 色777狠狠狠综合伊人| 男人插女人欧美| 久久99久久99精品免观看粉嫩 | 国产综合久久久久久久久久久久| 欧美亚洲精品在线| 国产女教师bbwbbwbbw| 亚洲欧美国产三级| 国产精品久久久久久久久久久久久久久| 欧美日韩精品免费看| 色婷婷综合久久久| 亚洲精品a级片| 尤物视频网站在线观看| 人人做人人澡人人爽欧美| 中文字幕乱码一区二区免费| 外国成人毛片| 国产精品无码av在线播放| 亚洲免费影视第一页| 久久精品国产秦先生| 黄色羞羞视频在线观看| 神马一区二区影院| 日韩欧美国产综合一区| 日本不卡视频在线| av漫画网站在线观看| 黄色www在线观看| 国产一区二区三区在线观看视频| 麻豆精品在线视频| 性爽视频在线| 国产精品www在线观看| 日日噜噜噜夜夜爽亚洲精品 | 亚洲福利视频网站| 91精品推荐| 中文字幕乱在线伦视频乱在线伦视频 | 亚洲一区二区三区乱码| 日韩欧美久久久| 捆绑调教一区二区三区| 黄色软件视频在线观看| 亚洲国产一二三精品无码| 亚洲最新av网址| 久久伊人中文字幕| 美女视频免费精品| 在线视频你懂| 蜜桃91精品入口| 亚洲日本中文字幕免费在线不卡| 成人国产在线观看| 国产成人福利av| 宅男深夜国产| 精品欧美一区二区三区久久久| 亚洲精品成人av| 国产精品无人区| 欧美激情1区| 涩涩视频在线免费看| 国产精品无码av无码| 色老头一区二区三区在线观看| 国产精品少妇自拍| 欧美a级在线| 亚洲成人短视频| 国产午夜电影| 久久狠狠久久综合桃花| 亚洲欧洲黄色网| 亚洲精品水蜜桃| 久久久精品五月天| 欧美另类中文字幕| 四虎精品成人免费网站| 精品国产无码在线| 亲爱的老师9免费观看全集电视剧| 欧美专区日韩专区| 91在线看国产| 欧美日韩1区| 国产精品日本一区二区三区在线 | 校园春色影音先锋| 欧美一级二级三级| 欧美二区乱c黑人| 欧美制服丝袜第一页| 波多野结衣中文字幕一区| 久久中文字幕av一区二区不卡| 欧美卡一卡二| 麻豆av在线| 日韩国产精品毛片| 国产欧美va欧美va香蕉在| 日韩精品视频在线|