本文說明使用 Azure Functions、Azure 事件中樞 和 Azure 服務匯流排 所建立的分散式系統。 其提供如何使用適用於 Python 和 Application Insights 的 OpenCensus 監視端對端系統的詳細數據。 本文也會介紹分散式追蹤,並說明如何使用 Python 程式代碼範例運作。 虛構的公司 Contoso 會用於架構中,以協助描述案例。
注意
OpenCensus 和 OpenTelemetry 正在合併,但 OpenCensus 仍然是監視 Azure Functions 的建議工具。 適用於 Azure 的 OpenTelemetry 處於預覽狀態, 但部分功能尚無法使用。
架構
工作流程
查詢。 定時器觸發的 Azure 函式會查詢 Contoso 內部 API,以每天取得最新的銷售數據一次。 函式會使用 Azure 事件中樞 輸出系結,將非結構化數據傳送為事件。
處理。 事件中樞會觸發 Azure 函式,以將非結構化數據處理及格式化為預先定義的結構。 函式會將一則訊息發行至每個資產 服務匯流排,這些資產需要透過 服務匯流排 輸出系結匯入。
Upsert。 服務匯流排 觸發 Azure 函式,此函式會取用來自佇列的訊息,並在一般公司記憶體中執行 upsert 作業。
請務必考慮此架構的潛在作業失敗。 這些範例包含:
- 內部 API 無法使用,這會導致查詢數據 Azure 函式在其中一個步驟中引發的例外狀況。
- 在步驟 2 中,處理數據 Azure 函式遇到函式條件或參數以外的數據。
- 在步驟 3 中,upsert 數據 Azure 函式會失敗。 重試數次之後,來自 服務匯流排 佇列的訊息會進入寄不出的信件佇列,這是保留無法在預先定義重試次數之後處理或傳遞至接收者的訊息的次要佇列。 然後訊息可以遵循已建立的自動程式,也可以手動處理它們。
元件
- Azure Functions 是一項無伺服器服務,可管理您的應用程式。
- Application Insights 是 Azure 監視器的一項功能,可監視開發、測試和生產環境中的應用程式。 Application Insights 會分析應用程式的執行方式,並檢閱應用程式執行數據以判斷事件的原因。
- Azure 資料表記憶體 是一項服務,可在雲端中儲存非關係結構化數據(結構化 NoSQL 數據),並提供無架構設計的索引鍵/屬性存放區。
- 事件中 樞是可調整的事件擷取服務,每秒可接收和處理數百萬個事件。
- OpenCensus 是一組開放原始碼連結庫,可用來收集分散式追蹤、計量和記錄遙測。 此架構使用 OpenCensus 的 Python 實作。
- 服務匯流排 是完全受控的訊息代理程式,其中包含消息佇列和發佈-訂閱主題。
案例詳細資料
分散式系統是由鬆散結合的元件所組成。 很難瞭解元件如何通訊,以及完全感知使用者要求的端對端旅程。 此架構可協助您查看元件連線的方式。
與許多公司一樣,Contoso 需要在雲端內嵌內部部署或第三方數據,同時使用服務和內部工具收集其銷售的相關數據。 在此架構中,Contoso 的部門建置了內部 API 來公開非結構化數據,並將數據內嵌至一般記憶體。 通用記憶體包含來自每個部門的結構化數據。 此架構示範 Contoso 如何擷取、處理及內嵌雲端中的元數據。
當您建置系統,特別是分散式系統時,請務必讓它成為可觀察的。 可觀察的系統:
- 提供分散式應用程式健康情況的整體檢視。
- 測量系統的作業效能。
- 識別並診斷失敗,以便快速解決問題。
分散式追蹤
在此架構中,系統是微服務鏈結。 每個微服務可能會因為各種原因而獨立失敗。 發生這種情況時,請務必瞭解所發生的情況,以便進行疑難解答。 隔離端對端交易並遵循由服務或微服務組成的應用程式堆棧旅程很有説明。 這個方法稱為 分散式追蹤。
下列各節說明如何在架構中設定分散式追蹤。 選取下列 [部署至 Azure ] 按鈕,以部署基礎結構和 Azure 函式應用程式。
注意
架構中沒有內部 API,因此 Azure 檔案的讀取會取代對 API 的呼叫。
追蹤和範圍
交易是由追蹤表示,這是範圍集合。 例如,當您選取購買按鈕以在電子商務網站上下訂單時,就會進行數個後續作業。 一些可能的作業包括:
- POST 要求會提交至 API,然後將您重新導向至「等候頁面」。
- 使用內容資訊撰寫記錄。
- 外部呼叫 Web 型軟體以要求計費頁面。
每個作業都可以是範圍的一部分。 追蹤是選取 [購買] 按鈕時所發生狀況的完整描述。
同樣地,在此架構中,當查詢數據 Azure 函式觸發以開始每日擷取銷售數據時,就會建立包含多個範圍的追蹤:
- 用來確認觸發程式詳細數據的範圍。
- 查詢內部 API 的範圍。
- 建立事件並傳送至事件中樞的範圍。
範圍可以有子範圍。 例如,下圖顯示查詢數據 Azure 函式做為追蹤:
sendMessages 範圍分成兩個子範圍:splitToMessages 和 writeToEventHubs。 sendMessages 範圍需要這兩個子作業才能傳送訊息。
所有範圍都是根範圍的子系。
Spans 可讓您輕鬆地描述查詢數據 Azure 函式查詢步驟中涉及的所有元件。 每個 Azure 函式都是追蹤。 因此,透過 Contoso 的擷取系統進行端對端傳遞是三個追蹤的聯集,也就是三個 Azure 函式。 當您結合三個追蹤及其遙測時,您會建置端對端旅程,並描述架構的所有部分。
追蹤器和 W3C 追蹤內容
追蹤是保留內容信息的物件。 在理想情況下,該內容資訊會在透過 Azure 函式傳輸數據時傳播。 為了傳播資訊,OpenCensus 延伸模組會使用 W3C 追蹤內容。
正如其檔所述,W3C 追蹤內容是「規格,可定義標準 HTTP 標頭和值格式,以傳播可啟用分散式追蹤案例的內容資訊」。
系統元件,例如函式,可以藉由讀取追蹤父代來建立具有上一個元件內容的追蹤。 追蹤格式為:
Traceparent: [version]-[traceId]-[parentId]-[traceFlags]
例如,如果 traceparent = 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-00
base16(version) = 00
base16(traceId) = 0af7651916cd43dd8448eb211c80319c
base16(parentId) = b7ad6b7169203331
base16(traceFlags) = 00
追蹤標識碼和父標識碼是最重要的欄位。 追蹤標識碼是追蹤的全域唯一標識碼。 父標識碼是跨範圍的全域唯一標識碼。 該範圍是追蹤標識碼識別之追蹤的一部分。
如需詳細資訊,請參閱 Traceparent 標頭。
在本文的其餘章節中,假設base16(version) 和base16(traceFlags) 設定為00。
使用 OpenCensus 擴充功能建立追蹤
使用 Azure Functions 特有的 OpenCensus 擴充功能。 請勿使用您可能在其他情況下使用的 OpenCensus 套件(例如 Python Webapps)。
Azure Functions 提供許多輸入和輸出系結,而且每個系結都有不同的方式來內嵌追蹤父系。 在此架構中,當取用事件和訊息時,會觸發兩個 Azure 函式。
在兩個函式可以觸發之前:
內容(以追蹤的標識碼和目前範圍的標識符為特徵)必須內嵌在 W3C 追蹤內容格式的追蹤父系中。 此內嵌取決於輸出系結的性質。 例如,架構會使用事件中樞作為傳訊系統。 追蹤父系會編碼為位元組,並內嵌在傳送的事件中做為診斷標識元屬性,以達到輸出系結中正確的追蹤內容。
即使兩個範圍不是父系和子系,也可以連結兩個範圍。 針對分散式追蹤,目前的範圍會指向下一個範圍。 建立 連結 會建立此關聯性。
Azure Functions 背景工作角色套件會為您管理內嵌和連結。
端對端流程中間的 Azure 函式會從傳遞的追蹤父代擷取內容資訊。 針對此步驟使用適用於 Azure Functions 的 OpenCensus 擴充功能。 OpenCensus 擴充功能不會在每個 Azure 函式的程式代碼中新增此程式,而是在函式應用程式層級實作叫用攔截。
預先叫用勾點:
- 建立範圍內容物件,此物件會保存上一個範圍的資訊,並觸發 Azure 函式。 在下一節中,請參閱此步驟的視覺範例。
- 建立包含範圍內容的追蹤器,併為觸發的 Azure 函式建立新的追蹤。
- 在 Azure 函式執行內容中插入追蹤。
若要確保追蹤出現在 Application Insights 中,您必須呼叫
configure
方法來建立及設定 導出遙測的 Azure 導出工具。延伸模組位於應用層級,因此本節中的步驟會套用至函式應用程式中的所有 Azure 函式。
瞭解及建構程序代碼
在此架構中,Azure 函式中的程式代碼會以範圍進行結構化。 在 Python 中,使用 with 語句來存取插入 Azure 函式執行內容內容的追蹤範圍部分,以建立 OpenCensus 範圍。 下列字串提供目前範圍及其父系的詳細資料:
with context.tracer.span("nameSpan"):
# DO SOMETHING WITHIN THAT SPAN
下列程式代碼顯示查詢資料 Azure 函式的詳細資料:
import datetime
import logging
import azure.functions as func
from opencensus.extension.azure.functions import OpenCensusExtension
from opencensus.trace import config_integration
OpenCensusExtension.configure()
config_integration.trace_integrations(['requests'])
config_integration.trace_integrations(['logging'])
def main(timer: func.TimerRequest, outputEventHubMessage: func.Out[str], context: func.Context) -> None:
utc_timestamp = datetime.datetime.utcnow().replace(
tzinfo=datetime.timezone.utc).isoformat()
if timer.past_due:
logging.info('The timer is past due!')
logging.info(f"Query Data Azure Function triggered. Current tracecontext is: {context.trace_context.Traceparent}")
with context.tracer.span("queryExternalCatalog"):
logging.info('querying the external catalog')
content = {"key_content_1": "thisisavalue1"}
content = json.dumps(content)
with context.tracer.span("sendMessage"):
logging.info('reading the external catalog')
with context.tracer.span("splitToMessages"):
# Do sthg
logging.info('splitting to messages')
with context.tracer.span("setMessages"):
logging.info('sending messages')
outputEventHubMessage.set(content)
logging.info('Python timer trigger function ran at %s', utc_timestamp)
此程式代碼的主要點是:
通話
OpenCensusExtension.configure
。 在每個函式應用程式中,只對一個 Azure 函式執行此呼叫。 此動作會將 Azure 匯出工具設定為將 Python 遙測,例如記錄、計量和追蹤導出至 Application Insights。OpenCensus
requests
和logging
整合,可從 HTTP 呼叫的要求和記錄模組設定遙測集合。有五個範圍:
- 根範圍,這是在執行之前插入內容之追蹤的一部分
queryExternalCatalog
sendMessage
splitToMessages
(一個孩子)sendMessage
setMessages
(一個孩子)sendMessage
追蹤和範圍
下圖顯示每次建立範圍時,追蹤範圍的範圍內容都會更新的方式。
在上圖中:
- 觸發 Azure 函式。 追蹤父系會在追蹤內容物件中插入具有叫用攔截,而 Python 背景工作角色會在函式執行之前呼叫。
- 執行 Azure 函式。 呼叫
OpenCensusExtension.configure
方法,它會初始化 Azure 匯出工具,並啟用對 Application Insights 的追蹤寫入。
下列詳細資料說明追蹤與此架構中的範圍之間的關聯性:
- Azure 函式內容的追蹤物件包含描述 根範圍的span_context 欄位。
- 每次在程式代碼中建立範圍時,它會建立新的全域唯一標識碼,並在執行內容的追蹤物件中更新 span_context 屬性。
- span_context欄位包含trace_id和標識符欄位。
- trace_id永遠不會更新,但標識符會更新為產生的唯一標識碼。
- 在上圖中,根範圍有兩個子範圍:queryExternalApi 和 sendMessage。
- queryExternalApi 範圍和 sendMessage 範圍具有與root_span_id不同的新範圍標識符。
- sendMessage 範圍有兩個子範圍:splitToMessages 和 setMessages。 其範圍標識碼會在 內容之追蹤物件的 span_context 欄位中更新。
- 若要擷取子範圍與其父系之間的關聯性, spans_list 欄位會提供清單窗體中的範圍譜系。 在splitToMessages範圍中, spans_list 字段包含sendMessage (父範圍) 和splitToMessages (目前範圍)。 此父/子關聯性是您在 Azure 函式執行內建立隔離作業鏈結的方式。
使用內容欄位鏈結函式
既然作業鏈結已組織在一個 Azure 函式中,您可以將它鏈結至下一個 Azure 函式所執行的後續作業。
在上圖中:
- setMessages 範圍是查詢數據 Azure 函式的最後一個範圍。 範圍內的程式代碼會將訊息傳送至事件中樞,並觸發後續的 Azure 函式。 內容 追蹤物件的span_context 欄位包含與此範圍相關的資訊。 該資訊會系結至查詢數據 Azure 函式的內容。
- Azure Functions 背景工作角色會在傳送事件的屬性中新增位元組編碼 的診斷標識碼 ,並建立 後續 Azure 函式根範圍的連結 。
- 後續進程數據 Azure 函式的叫用攔截會 讀取 Diagnostic-Id 並設定內容,以鏈結 Azure 函式,並分別執行。
當進程數據 Azure 函式將訊息傳送至 服務匯流排 佇列時,內容會以相同方式傳遞。
當監視組態就緒時,請使用ApplicationInsights功能來查詢和可視化端對端交易。
遙測類型
Application Insights 中有數種類型的遙測可用。 此架構中的程式代碼會產生下列遙測:
- 當您呼叫 HTTP 或觸發 Azure 函式時,要求 遙測會發出。 Contoso 系統的專案具有發出要求遙測的查詢數據 Azure 函式定時器觸發程式。
- 當您呼叫 Azure 服務或外部服務時,相依性 遙測會發出。 當 Azure 函式將事件寫入事件中樞時,它會發出相依性遙測。
- 追蹤 遙測會從 Azure Functions 運行時間和 Azure Functions 所產生的記錄發出。 Azure 函式內的記錄會發出追蹤遙測。
參與者
本文由 Microsoft 維護。 原始投稿人如下。
主體作者:
- Raouf Aliouat |軟體工程師II
其他投稿人:
- 朱利安·科里奧蘭 |首席軟體工程師
- Benjamin Guinebertière |主要軟體工程管理員
- Jodi Martis |技術寫入器
- Adina Stoll |軟體工程師II
若要查看非公開的 LinkedIn 設定檔,請登入 LinkedIn。
下一步
- Azure 監視器概觀
- 微服務中的可檢視性
- 分散式追蹤和遙測相互關聯
- 瞭解事件中樞中的作業標識碼和作業連結
- OpenCensus Azure 監視器導出工具
- Microsoft Purview 中外部目錄的元數據擷取