本教學的目的是為 OpenTelemetry 中的跨度連結提供實用且易於理解的指南。
它旨在幫助開發人員,特別是那些使用複雜和非同步系統的開發人員,了解跨度連結是什麼,它們與傳統追蹤中的父子關係有何不同,以及為什麼它們對於更好的追蹤關聯很有價值。
在本指南結束時,您將獲得有效使用跨度連結來追蹤分散式系統內互動所需的技能,從而提高可觀察性和調試能力。
過去,應用程式通常是整體式的,這意味著每個進程或功能都作為一個伺服器上的單一單元執行。監控此類應用程式非常簡單。
例如:如果出現問題,您可以查看該伺服器的日誌來識別問題。然而,微服務的興起改變了這種簡單性。
現在,現代應用程式通常由數十個甚至數百個協同工作的較小的獨立服務組成。例如:當您使用行動應用程式下訂單時,可能會有單獨的服務來處理使用者身分驗證、處理付款、管理庫存和發送確認電子郵件。
這些服務並不總是位於同一伺服器上,甚至可以透過網路進行通信,這增加了追蹤與應用程式互動時發生的情況的複雜性。
這就是分散式追蹤的用武之地。將分散式追蹤視為一種在單一請求經過複雜應用程式中的各種服務時追蹤單一請求的方法。它追蹤請求通過複雜系統的旅程。
在現代應用程式中,請求經常透過多個服務傳輸,每個服務運行在不同的機器上。分散式追蹤幫助我們可視化這個過程,從而更容易識別瓶頸和錯誤。
它就像一張偵探地圖,將流程每個步驟之間的點連接起來,向您顯示每個部分花費了多長時間以及出現問題的位置。當您查看追蹤時,您會看到請求如何透過不同服務移動的時間線,從而更容易識別速度減慢、錯誤或失敗。
程式碼庫
這是本教學的程式碼儲存庫:
[https://github.com/Noibisjunior/Span-Links-in-OpenTelemetry]
OpenTelemetry 是實現這種可見性的關鍵角色。它是一個開源可觀察性框架,允許開發人員從應用程式收集日誌、指標和追蹤等資料。它作為一個工具集,用於捕獲有關服務內部發生的情況的詳細資訊。
在現代可觀測性的世界中,OpenTelemetry 可協助您了解分散式應用程式的效能和運作狀況。它就像一座橋樑,從各種服務收集數據並將其發送到 SigNoz 等工具,您可以在其中可視化正在發生的情況。這使得 OpenTelemetry 對於識別瓶頸、追蹤錯誤和確保應用程式順利運行非常有價值。
透過將 OpenTelemetry 與分散式追蹤結合使用,您可以全面了解應用程式的行為方式,從而更輕鬆地診斷問題並改善使用者體驗。
隨著軟體,尤其是分散式系統變得越來越複雜,理解其內部工作原理成為一項具有挑戰性的任務。這就是 OpenTelemetry 的跨度可以輕鬆解決挑戰的地方。
跨度是 OpenTelemetry 追蹤系統中的基本工作單元。它是應用程式中發生的單一操作或事件。
它會捕捉該操作期間發生的情況、花費的時間以及任何相關詳細信息,例如操作是否成功或失敗。
例如,假設您的應用程式處理使用者請求:
跨度的關鍵屬性:
單獨使用時,跨度很有用,但是當它們一起形成軌跡時,它們會更有效。
追蹤是跨度的集合,代表請求或操作流經系統時的整個過程。
讓我們回到我們的使用者請求範例:
當請求進入系統時,追蹤開始,並建立根跨度。當請求觸發資料庫查詢時,資料庫互動跨度連結到根跨度,表示它是同一進程的一部分。
用於呼叫其他服務的額外跨度被加入到追蹤中。透過查看此跟踪,您可以大致了解請求如何通過系統的不同部分。它不僅可以幫助您了解發生了什麼,還可以幫助您了解應用程式的不同部分是如何連接的。
找出問題:跨度可幫助您放大出現問題的位置。如果請求很慢,span 可以告訴您是否是資料庫查詢、網路呼叫或進程的其他部分導致了延遲。您可以看到哪個跨度花費的時間比預期更長,更容易找到瓶頸。
建立上下文:每個跨度都包含上下文訊息,例如開始時間、結束時間和自訂標籤(屬性)。此資料可讓您深入了解系統中特定時刻發生的情況,例如請求中涉及的特定使用者 ID 或執行的查詢。
建立關係:跨度之間存在關係,通常採用父子結構。根跨度是父跨度,後續跨度是其子跨度。這個結構可幫助您了解事件發生的順序以及它們如何相互依賴。這就像在您的應用程式中查看操作的家譜。
偵錯分散式系統:對於具有微服務的應用程式(其中不同的服務處理請求的不同部分),跨度尤其重要。它們可以幫助您追蹤在服務之間移動的請求,即使這些服務運行在不同的伺服器或不同的資料中心。這是理解服務之間複雜互動的關鍵。
什麼是跨度連結?
在分散式系統的世界中,多個服務協同工作來處理使用者請求,追蹤就像偵探的地圖,它顯示了請求在這些服務中移動時所採取的路徑。這個旅程中的每一個活動稱為一個跨度,一個完整的旅程稱為一個痕跡。
傳統上,跨度是使用父子關係連結的。將它們想像成一個家譜:父跨度啟動一個流程(例如向另一個服務發出請求),子跨度代表由此發生的活動(例如處理請求的服務)。這是表示請求流的一種簡單方法。
但是當兩個跨度相關但它們並不完全適合父子層次結構時會發生什麼?這就是跨距連結的用武之地。
跨度連結允許您連接兩個相關但沒有直接父子關係的跨度。它就像是分散式系統中兩個活動之間的「引用」或「捷徑」。
例如,假設您有一個使用者發出觸發多個獨立進程的請求,例如發送電子郵件和寫入資料庫。這些過程不是彼此的子活動;而是彼此的子活動。它們同時發生。使用跨度鏈接,您可以指示電子郵件發送跨度和資料庫寫入跨度與同一個初始用戶請求相關,即使它們在父子概念中沒有直接連接。
親子關係:這是一個簡單的事件鏈。使用者傳送請求(父級),該請求觸發在資料庫(子級)中建立記錄。如果沒有父跨度,子跨度就不會存在,這使其成為直接結果。
跨度連結:這些更像是在某些上下文中相關的活動之間繪製虛線,但不遵循直接的操作鏈。它們提供了一種表達方式:「這些事情是相關的,儘管其中一個並沒有直接導致另一個。」跨度連結非常適合表示相互作用但不嚴格分層的平行活動或事件。
跨度連結在複雜和非同步系統中的重要性
跨度連結在複雜和非同步系統中特別有價值,在這些系統中,事件流並不總是遵循清晰的父子路徑。以下是一些實際使用場景;
非同步工作流程:
想像一個從後台作業開始的使用者請求(例如產生報表)。初始請求完成,但報告產生仍在後台繼續。
透過跨度連結的實現,您可以將初始請求跨度與後台作業跨度相關聯,即使它們不遵循直接的父子模式。
微服務通訊:
在微服務架構中,服務通常以不嚴格分層的方式相互通訊。
例如,使用者操作可以觸發多個服務來同時處理資料的不同部分。 Span 連結可讓您追蹤這些獨立且相關的 Span,作為更廣泛的工作流程的一部分。
批次:如果您正在處理批次數據,其中批次中的每個項目都會產生自己的範圍,則可以使用範圍連結將這些範圍連接回原始批次數據。
這樣可以更輕鬆地追蹤批次的整個生命週期,並了解各個項目如何與主流程相關。
它充當程式碼和可觀察性系統之間的橋樑,使收集有關應用程式運作方式的詳細資訊成為可能。
將 OpenTelemetry 想像為一個“相機”,用於捕獲應用程式操作的快照。透過將 SDK 整合到您的應用程式中,您可以放置此攝影機來記錄幕後發生的事情。
您需要使用應用程式的程式語言(例如 Python、Java、JavaScript)安裝 SDK。
(2) SigNoz 設定:SigNoz 是一個開源可觀察性工具,可讓您視覺化和分析透過 OpenTelemetry 收集的資料。
將 SigNoz 視為“控制室”,您可以在其中查看 OpenTelemetry 設定捕獲的鏡頭。您可以在這裡清楚地了解應用程式中的追蹤和指標。
您需要設定一個 SigNoz 實例,這涉及將其部署在本機電腦或伺服器上,通常使用 Docker 或 Kubernetes。
SigNoz 有助於將原始資料轉換為視覺化效果,例如圖形和圖表,讓您更輕鬆地了解應用程式內部發生的情況。
痕跡:
簡單來說,追蹤就像用戶或請求與應用程式互動時發生的情況的「故事」。它捕獲由於該交互而發生的所有操作,從初始請求到可能涉及的所有服務和資料庫。
想像一個使用者點擊您網站上的按鈕。痕跡會記錄接下來發生的每一步。
跨度:
跨度是跟蹤故事中的「章節」。每個跨度代表作為追蹤的一部分所發生的特定操作或任務。
例如,如果追蹤捕獲了使用者請求的整個過程,則跨度可以代表單一步驟,例如查詢資料庫或呼叫外部 API。
每個跨度都有開始和結束時間,為您提供有關每個步驟花費多長時間的精確詳細資訊。這使得更容易找出任何速度減慢或錯誤。
使用 OpenTelemetry 偵測程式碼:
檢測是向應用程式添加程式碼以收集可觀測性資料的過程。透過使用 OpenTelemetry 檢測您的程式碼,這通常涉及在您想要建立追蹤和跨度的位置添加幾行程式碼。
例如,您可以偵測資料庫查詢以查看需要多長時間,或偵測使用者登入程序以追蹤其效能。
OpenTelemetry SDK 提供可直接整合到程式碼中的函式庫和函數,讓這一切變得更容易。可以將其想像為將追蹤器連接到機器的各個部分以監控它們如何協同工作。
讓我們來看一個 Python 中的基本範例。我們將使用 OpenTelemetry SDK 創建兩個跨度並將它們連結在一起。
from opentelemetry import trace from opentelemetry.trace import Link from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import SimpleSpanProcessor, ConsoleSpanExporter # Set up the tracer provider and span exporter trace.set_tracer_provider(TracerProvider()) tracer = trace.get_tracer(__name__) span_processor = SimpleSpanProcessor(ConsoleSpanExporter()) trace.get_tracer_provider().add_span_processor(span_processor) # Create the first span, simulating some work being done with tracer.start_as_current_span("span_one") as span_one: span_one.add_event("Processing order") order_id = "12345" # Imagine this as an order ID we're processing # Create a second span with a link to the first span with tracer.start_as_current_span("span_two", links=[Link(span_one.get_span_context())]) as span_two: span_two.add_event("Updating order status") # Simulate some additional work here print("Order ID: {order_id} has been updated.") print("Tracing complete")
上述 Python 程式碼片段的說明
設定追蹤器提供者:
上面的程式碼片段以追蹤器提供者開始,它管理跨度的建立。
這對於 OpenTelemetry 了解如何處理跨度至關重要。我們也配置了 SimpleSpanProcessor 和 ConsoleSpanExporter 以將跨度資料列印到控制台。這有助於我們了解正在創建的跨度類型以及它們是如何連結的
.
(2) 建立第一個 Span (span_one):
使用tracer.start_as_current_span方法,我們建立一個名為span_one的span。這可以代表任何操作,例如處理訂單。
在此範圍內,我們新增一個事件處理順序來指示在該特定時間點發生的情況。
我們也模擬了將在下一個跨度中使用的訂單 ID (order_id = "12345")。
(3) 建立第二個帶有連結的 Span (span_two):
在這裡,我們啟動了另一個名為 span_two 的跨度來表示不同但相關的操作,例如更新訂單的狀態。
注意 links 參數。我們使用 Link(span_one.get_span_context()) 在 span_two 和 span_one 之間建立連結。
這告訴 OpenTelemetry,「雖然這些操作不是父子關係,但它們是相關的。」
在span_two中,我們新增了另一個事件,更新訂單狀態,並模擬一些工作,例如更新資料庫中的訂單狀態。
(4) 輸出:
當您執行此程式碼時,您將在 ConsoleSpanExporter 的控制台中看到輸出,其中顯示兩個跨度以及它們之間的連結。這有助於可視化這兩個跨度在追蹤中如何相互關聯。
(1) 缺失的跨度上下文:
錯誤:如果您嘗試在不調用 span_one.get_span_context() 的情況下創建鏈接,您將收到錯誤,因為 OpenTelemetry 需要有效的跨度上下文才能創建鏈接。
解決方案:始終確保在建立連結時傳遞跨度上下文。使用活動範圍的 .get_span_context() 方法。
(2) 連結未開始或結束的 Span:
錯誤:如果您嘗試建立指向尚未開始或已經結束的跨度的鏈接,您可能會遇到無法識別該鏈接的問題。
解決方案:建立連結時,請確保您連結到的跨度處於活動狀態。使用已經結束的跨度建立連結可能會導致追蹤顯示方式出現意外行為。
(3) 效能考量:
效能問題:連結太多跨度會增加追蹤資料的開銷,導致高流量系統中的效能下降。
解決方案:選擇性地使用連結。只有當存在需要視覺化或分析的有意義的關係時,才會出現連結跨度。對於高流量環境,您可以使用 OpenTelemetry 的取樣選項來減少擷取的追蹤資料量。
在使用分散式系統時,了解系統不同部分如何通訊至關重要。 OpenTelemetry 中的跨度連結 在連接可能沒有直接父子關係的追蹤方面發揮著至關重要的作用,可以更清晰地了解請求如何流經您的服務。
為什麼視覺化跨度連結很重要
想像一下您的應用程式有一個支付服務,當付款成功時會觸發通知服務。雖然這些服務交互,但它們可能不會共享直接的父子關係。
跨度連結可讓您關聯這些交互,顯示付款觸發了通知。視覺化這些連結可以幫助您更全面地了解獨立服務如何即時關聯。
透過設定 SigNoz 來視覺化這些跨度鏈接,您可以更深入地了解應用程式的行為。
以下是如何設定 SigNoz 來擷取和檢視 Span 連結
第 1 步:確保 SigNoz 已正確安裝
第 2 步:設定 OpenTelemetry SDK 以包含您的 Span 連結
下一步是確保您的 OpenTelemetry SDK 配置為將跨度連結資料傳送到 SigNoz。在應用程式的程式碼中,您需要添加跨度連結作為追蹤邏輯的一部分。
這是 Python 程式語言的程式碼片段:
from opentelemetry import trace from opentelemetry.trace import Link from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import SimpleSpanProcessor, ConsoleSpanExporter # Set up the tracer provider and span exporter trace.set_tracer_provider(TracerProvider()) tracer = trace.get_tracer(__name__) span_processor = SimpleSpanProcessor(ConsoleSpanExporter()) trace.get_tracer_provider().add_span_processor(span_processor) # Create the first span, simulating some work being done with tracer.start_as_current_span("span_one") as span_one: span_one.add_event("Processing order") order_id = "12345" # Imagine this as an order ID we're processing # Create a second span with a link to the first span with tracer.start_as_current_span("span_two", links=[Link(span_one.get_span_context())]) as span_two: span_two.add_event("Updating order status") # Simulate some additional work here print("Order ID: {order_id} has been updated.") print("Tracing complete")
上述Python程式碼片段的解釋
我們首先配置 TracerProvider 來處理應用程式中的追蹤並設定跨度處理器。
OTLPSpanExporter 用於使用 OTLP 協定將跨度傳送到 SigNoz 的後端。
如果您沒有在本機上執行 SigNoz,請將 http://localhost:4317 替換為適當的 SigNoz 端點。
其次,建立跨度和連結:
先建立parent_span,代表一個初始操作(例如,使用者請求)。我們使用 get_span_context() 來提取parent_span的上下文,這允許我們將另一個span連結到它。
然後建立linked_span,並加入一個連結來引用parent_span的上下文。這意味著雖然 linked_span 不是 Parent_span 的直接子級,但它與之相關。
最後,將資料傳送到 SigNoz:
使用BatchSpanProcessor處理span數據,確保span數據有效率地傳送到SigNoz。
trace.get_tracer_provider().shutdown() 在最後調用,以確保在程式退出之前刷新並導出任何剩餘的跨度。
第 3 步:更新 SigNoz 配置以追蹤資料
from opentelemetry import trace from opentelemetry.trace import SpanKind, Link from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter # Set up the tracer provider and add a span processor trace.set_tracer_provider(TracerProvider()) tracer = trace.get_tracer(__name__) # Configure the exporter to send spans to SigNoz using the OTLP exporter otlp_exporter = OTLPSpanExporter(endpoint="http://localhost:4317", insecure=True) span_processor = BatchSpanProcessor(otlp_exporter) trace.get_tracer_provider().add_span_processor(span_processor) # Create two spans, linking the second span to the context of the first with tracer.start_as_current_span("parent_span") as parent_span: # Simulate some logic for the parent_span print("Parent span is active") # Get the context of the parent span parent_context = parent_span.get_span_context() # Create a linked span and add a link to the parent span's context with tracer.start_as_current_span( "linked_span", links=[Link(parent_context)] ) as linked_span: # Simulate some logic for the linked_span print("Linked span is active") # Ensure all spans are flushed before exiting the application trace.get_tracer_provider().shutdown()
第 4 步:在 SigNoz 中可視化跨度連結
應用程式將帶有跨度連結的追蹤資料傳送到 SigNoz 後,您可以透過以下方式視覺化這些連結:
第 5 步:調整視圖以獲得清晰度
為了獲得完美的視覺化效果,您需要注意以下幾點:
後續步驟
在本教程中,我們學習如何使用跨度連結來追蹤分散式系統內的互動
在下一個教程中,我們將學習使用 Span 連結的最佳實踐和高級用例
以上是使用 OpenTelemetry 和 Signoz 掌握透過 Span Links 進行追蹤分析(實用指南)的詳細內容。更多資訊請關注PHP中文網其他相關文章!