具代表性的面試主題

資料與可觀測性面試:批次處理為何應使用 OpenTelemetry Span Links?

資料困難
Offer.cc 編輯團隊發佈 更新

題幹

一個 worker 從訊息佇列批次取出 100 個事件,合併後呼叫一次下游服務。請設計 OpenTelemetry 追蹤,說明何時使用 parent、何時使用 Span Links,以及採樣、連結數量、指標和隱私邊界。

題幹與適用場景

一個 worker 每次從佇列取出 100 個事件,聚合後只呼叫一次下游 API。每個事件可能來自不同 Trace,worker 也可能由排程或人工重放觸發。請設計追蹤模型,既能回溯每個來源,又不把 100 條不相關請求偽裝成單一父子樹。

OpenTelemetry 將 Span 描述為可形成樹的操作,並允許一個 Span 關聯零個或多個 Link。官方概覽明確把「批次由多個入站 Span 發起」列為 Links 的典型場景。

面試官考察點

考察候選人是否理解 parent 表示單一目前上下文,Link 表示因果相關但非父子關係;能否控制連結數量、採樣和高基數屬性,避免 Trace 爆炸,同時讓指標和日誌仍可關聯。

回答前需要釐清的問題

  • 批次是否包含不同租戶、不同安全等級或不同業務類型?
  • 下游呼叫是一次合併請求,還是仍可拆成每個事件的操作?
  • 需要按單一事件追責、延遲分析,還是只看批次吞吐?
  • 採樣由入口決定,還是 worker 可以保留部分來源上下文?
  • Link 屬性是否允許放事件 ID、租戶 ID 或敏感欄位?

30 秒回答框架

「批次處理 Span 以 worker 或批次觸發上下文為 parent;100 個入站 Span 作為 Links,因為它們共同促成一次批次卻不構成單一父子鏈。每個 Link 只保留必要的 SpanContext 和低基數屬性,設定連結上限並統計截斷數。批次 Span 記錄大小、等待、處理、下游耗時和失敗數,日誌用批次 ID 與事件雜湊關聯。敏感租戶欄位需脫敏,採樣要保證失敗批次和重放批次可定位。」

分步深入解答

第一步:區分 parent 與 Link

Parent 表示目前操作從哪個單一 Span 繼續,形成 Trace 樹並繼承 TraceId。Link 只表示一個相關 SpanContext,可來自同一或不同 Trace。批次有多個同等來源時,不能任選一個事件作父節點,再把其他事件掛成子節點。

text
批次處理 Span
  parent: worker / scheduler context
  links: event-1 SpanContext ... event-100 SpanContext

第二步:保留跨邊界的 SpanContext

從訊息標頭提取 TraceContext,驗證格式和採樣標記後建立 Link;不要把完整訊息、使用者輸入或原始權杖寫入 Link 屬性。若訊息沒有合法上下文,記錄「無來源上下文」計數,不要產生偽造 TraceId。

第三步:控制連結規模與成本

100 個連結只是題設上限,生產批次可能更大。設定 SDK 的 link count limit 或應用層上限,優先保留錯誤、重試和關鍵租戶的代表性來源,並記錄 dropped-link 數量。連結被截斷時要在批次指標與日誌中可見。

第四步:設計批次 Span 生命週期

Span 覆蓋等待批次、反序列化、聚合、下游呼叫和提交結果;按階段記錄事件或指標。任何建立的 Span 都必須結束,即使處理失敗、取消或部分提交。不要讓單一事件的長處理掩蓋整個批次 Span 的結束時間。

第五步:處理採樣與失敗可見性

入口採樣決定是否保留來源 Trace,但 worker 應為失敗、重試、死信和人工重放設定保底策略。Link 在 Span 建立時可能影響採樣,建立後加入的 Link 不一定能被採樣器使用,因此需要明確採樣順序和降級行為。

第六步:把追蹤、指標和日誌分工

Trace 解釋單一批次的因果關係;指標承載批次大小、佇列等待、處理延遲、成功/失敗和截斷計數;日誌用批次 ID、事件雜湊和重放 ID 定位樣本。不要把事件 ID 作為無限基數的指標標籤。

第七步:隔離租戶與隱私

跨租戶批次需要在 Link 和日誌中使用不可逆雜湊或內部引用,並在匯出前做屬性過濾。若不同安全等級不能共存,應按租戶或權限拆批,避免一個 Trace 讓低權限操作者看到其他租戶上下文。

第八步:驗證查詢與故障場景

測試單一來源、混合 Trace、缺失上下文、連結超限、採樣遺失、下游重試、部分失敗、死信和重放。驗證從批次 Span 能跳回保留的來源 Trace,也能從指標定位被截斷或未採樣的批次。

高品質示範回答

「批次 Span 以 worker 或排程器為 parent,訊息中的每個來源 SpanContext 作為 Link。這樣保留 100 個事件共同促成一次下游呼叫的事實,避免偽造父子樹。我會限制連結數量並記錄丟棄計數,過濾租戶和敏感屬性;用指標記錄批次大小、佇列等待、下游延遲、失敗與重試,日誌用批次和重放 ID 關聯。採樣策略為失敗批次保底,測試缺失上下文、混合 Trace、超限和重放。」

常見錯誤

  • 任選第一條訊息作 parent → 偽造因果樹 → 批次用共同 parent,其餘來源用 Links。
  • 把整個訊息放進 Link 屬性 → 洩漏敏感資料並增加成本 → 只保留必要、脫敏的低基數欄位。
  • 無限制加入 Links → Span 體積和匯出成本失控 → 設定上限並記錄截斷。
  • Span 只在成功路徑結束 → 錯誤和取消留下懸掛 Span → 用 finally 或作用域自動結束。
  • 用事件 ID 作指標標籤 → 高基數爆炸 → 把細節留給日誌或 Trace。
  • 認為建立後 Link 一定影響採樣 → 重要來源被採樣遺失 → 建立 Span 前準備採樣所需上下文。

追問及應對

追問一:批次只有一個訊息時還需要 Link 嗎?

可以直接以該訊息上下文作 parent;若 worker 有獨立生命週期,也可用 worker parent 加一個 Link,取決於是否要把批次視為該請求的直接子操作。

追問二:Link 會把不同 Trace 合併成一個 Trace 嗎?

不會。Link 表示相關性,保留各自 TraceId;查詢系統需要提供從 Link 跳轉來源 Trace 的能力。

追問三:如何選擇被截斷的來源?

按錯誤、重試、重放、關鍵租戶或確定性採樣保留,並記錄總數和 dropped 數;不要靜默保留前 N 條造成偏差。

追問四:批次失敗如何保證可診斷?

讓失敗批次和死信重放帶獨立批次/重放 ID,保留錯誤事件連結或摘要;指標記錄失敗類型,日誌提供受控的事件引用。

追問五:Link 屬性能否放 tenant.id?

只有通過權限、基數和隱私評估才可放內部穩定標識;跨租戶匯出通常應雜湊或刪除,並避免當作高頻指標標籤。

公開來源

同類題目