本文提供在應用程式中同時使用 Azure 事件中樞 和 Azure Functions 時,優化延展性和效能的指引。
函式群組
一般而言,函式會在事件處理數據流中封裝工作單位。 例如,函式可以將事件轉換成新的數據結構,或擴充下游應用程序的數據。
在 Functions 中,函式應用程式會提供函式的執行內容。 函式應用程式行為適用於函式應用程式裝載的所有函式。 函式應用程式中的函式會一起部署並一起調整。 函數應用程式中的所有函式都必須是相同語言。
如何將函式分組為函式應用程式,可能會影響函式應用程式的效能和調整功能。 您可以根據存取權、部署和叫用程式代碼的使用模式來分組。
如需群組和其他層面之 Functions 最佳做法的指引,請參閱可靠 Azure Functions 的最佳做法和改善 Azure Functions 的效能和可靠性。
下列清單是群組函式的指引。 指引會考慮記憶體和取用者群組層面:
在函式應用程式中裝載單一函式: 如果事件中樞觸發函式,您可以減少該函式與其他函式之間的爭用,將函式隔離在自己的函式應用程式中。 如果其他函式需要大量CPU或記憶體,隔離就特別重要。 這項技術有助於因為每個函式都有自己的記憶體使用量和使用模式,而這可能會直接影響裝載它的函式應用程序調整。
為每個函式應用程式提供自己的記憶體帳戶: 避免在函式應用程式之間共用記憶體帳戶。 此外,如果函式應用程式使用記憶體帳戶,請勿使用該帳戶進行其他記憶體作業或需求。 避免共用事件中樞觸發之函式的記憶體帳戶特別重要,因為這類函式可能會因為檢查點而擁有大量的記憶體交易。
為每個函式應用程式建立專用的取用者群組: 取用者群組是事件中樞的檢視。 不同的取用者群組有不同的檢視,這表示狀態、位置和位移可能會有所不同。 取用者群組可讓多個取用的應用程式有自己的事件串流檢視,以及以自己的步調獨立讀取數據流,以及使用自己的位移讀取數據流。 如需取用者群組的詳細資訊,請參閱 Azure 事件中樞 中的功能和術語。
取用者群組有一或多個與其相關聯的取用者應用程式,而取用者應用程式可以使用一或多個取用者群組。 在串流處理解決方案中,每個取用者應用程式等同於取用者群組。 函式應用程式是取用者應用程式的主要範例。 下圖提供兩個從事件中樞讀取的函式應用程式範例,其中每個應用程式都有自己的專用取用者群組:
請勿在函式應用程式與其他取用者應用程式之間共用取用者群組。 每個函式應用程式都應該是具有自己指派取用者群組的不同應用程式,以確保每個取用者的位移完整性,並簡化事件串流架構中的相依性。 這類設定,並提供每個事件中樞觸發函式自己的函式應用程式和記憶體帳戶,有助於為最佳效能和調整設定基礎。
函式主控方案
函式應用程式有數個裝載選項,請務必檢閱其功能。 如需這些裝載選項的相關信息,請參閱 Azure Functions 裝載選項。 請記下選項調整的方式。
取用方案是預設值。 「取用方案」中的函式應用程式會獨立調整,且在避免長時間執行的工作時最有效。
進階和專用方案通常用來裝載多個需要大量 CPU 和記憶體的函式應用程式和函式。 使用專用方案時,您會以一般 App Service 方案費率在 Azure App 服務 方案中執行函式。 請務必注意,這些方案中的所有函式應用程式都會共用配置給方案的資源。 如果函式有不同的負載配置檔或唯一需求,最好在不同的方案中裝載它們,特別是在串流處理應用程式中。
Azure Container Apps 提供在 Azure Functions 上開發、部署和管理容器化函式應用程式的整合式支援。 這可讓您在完全受控、以 Kubernetes 為基礎的環境中執行事件驅動函式,內建支持開放原始碼監視、mTLS、Dapr 和 KEDA。
事件中樞調整
當您部署事件中樞命名空間時,您需要正確設定數個重要的設定,以確保尖峰效能和調整。 本節著重於事件中樞的標準層,以及當您也使用 Functions 時影響調整的該層的獨特功能。 如需事件中樞層的詳細資訊,請參閱 基本與標準與進階與專用層。
事件中樞命名空間會對應至 Kafka 叢集。 如需事件中樞和 Kafka 彼此關聯的相關信息,請參閱 Apache Kafka 的 Azure 事件中樞。
瞭解輸送量單位 (TU)
在事件中樞標準層中,輸送量會分類為輸入的數據量,並依時間單位從命名空間讀取。 TU 是預先購買的輸送量容量單位。
TU 會按小時計費。
命名空間中的所有事件中樞都會共用 TU。 若要正確計算容量需求,您必須考慮發行者和取用者的所有應用程式和服務。 函式會影響發佈至事件中樞並從中讀取的位元組和事件數目。
判斷 TU 數目的重點在於輸入點。 不過,取用者應用程式的匯總,包括處理這些事件的速率,也必須包含在計算中。
如需事件中樞輸送量單位的詳細資訊,請參閱 輸送量單位。
使用自動擴充相應增加
事件中樞命名空間可啟用自動擴充功能,以因應負載超過設定的 TU 數目的情況。 使用自動擴充可防止應用程式的節流,並協助確保處理,包括擷取事件,持續而不會中斷。 因為 TU 設定會影響成本,因此使用自動擴充有助於解決過度布建的擔憂。
自動擴充是事件中樞的一項功能,通常與自動調整混淆,特別是在無伺服器解決方案的內容中。 不過,與自動調整不同,自動擴充不會在不再需要新增容量時相應減少。
如果應用程式需要超過最大允許的 TU 數目,請考慮使用事件中樞進階層或專用層。
數據分割和並行函式
建立事件中樞時,必須指定分割區數目。 分割區計數會維持固定狀態,而且除了進階和專用層之外,無法變更。 當事件中樞觸發函式應用程式時,並行實例的數目可能會等於分割區數目。
在取用和進階主控方案中,函式應用程式實例會視需要動態相應放大以符合分割區數目。 專用主控方案會在 App Service 方案中執行函式,並要求您手動設定實例或設定自動調整配置。 如需詳細資訊,請參閱 Azure Functions 的專用裝載方案。
最後,分割區數目與函式實例或取用者之間的一對一關聯性,是串流處理解決方案中最大輸送量的理想目標。 若要達到最佳平行處理原則,請在取用者群組中擁有多個取用者。 針對 Functions,此目標會轉譯為方案中函式的許多實例。 結果稱為 數據分割層級平行處理原則 或 平行處理原則的最大程度,如下圖所示:
設定盡可能多的分割區可能很合理,以達到最大輸送量,並考慮更多事件量的可能性。 不過,當您設定許多分割區時,需要考慮幾個重要因素:
- 更多的分割區可能會導致更多的輸送量: 因為平行處理原則的程度是取用者數目(函式實例),因此有更多的分割區,並行輸送量就越高。 當您與其他取用者應用程式共用事件中樞的指定 RU 數目時,這個事實很重要。
- 更多函式可能需要更多記憶體: 函式實例數目增加時,計劃中的資源記憶體使用量也會增加。 在某些時候,太多分割區可能會讓取用者的效能惡化。
- 下游服務會產生回壓的風險: 由於會產生更多輸送量,因此您會承擔壓倒性下游服務或從中接收回壓力的風險。 考慮周邊資源的後果時,必須考慮取用者展開。 可能的後果包括從其他服務進行節流、網路飽和度,以及其他形式的資源爭用。
- 分割區可以疏鬆填入: 許多分割區與少量事件的組合可能會導致數據分散在分割區之間。 相反地,較小的分割區可以提供更好的效能和資源使用量。
可用性與一致性
未指定分割區索引鍵或標識符時,事件中樞會將傳入事件路由傳送至下一個可用的分割區。 這種做法提供高可用性,並協助增加取用者的輸送量。
當需要排序一組事件時,事件產生者可以指定特定分割區要用於集合的所有事件。 從分割區讀取的取用者應用程式會依適當順序接收事件。 這種取捨可提供一致性,但會危害可用性。 除非必須保留事件的順序,否則請勿使用此方法。
針對 Functions,當事件發佈至特定分割區,而事件中樞觸發的函式會取得相同數據分割的租用時,就會達到排序。 目前不支援使用事件中樞輸出系結設定數據分割的功能。 相反地,最佳方法是使用其中一個事件中樞 SDK 發佈至特定分割區。
如需事件中樞如何支援可用性和一致性的詳細資訊,請參閱 事件中樞的可用性和一致性。
事件中樞觸發程序
本節著重於優化事件中樞觸發之函式的設定和考慮。 因素包括批處理、取樣,以及影響事件中樞觸發程式系結行為的相關功能。
觸發函式的批處理
您可以設定事件中樞觸發的函式,以一次處理一批事件或一個事件。 處理一批事件可能會更有效率,因為它可減少函式調用的一些額外負荷。 除非您只需要處理單一事件,否則您的函式應該設定為在叫用時處理多個事件。
啟用事件中樞觸發程式系結的批次處理會因語言而異:
- 當基數屬性設定為函式function.json檔案中的許多時,JavaScript、Python 和其他語言會啟用批處理。
- 在 C# 中,當為 EventHubTrigger 屬性中的類型指定陣列時,會自動設定基數。
如需如何啟用批處理的詳細資訊,請參閱 Azure Functions 的 Azure 事件中樞 觸發程式。
觸發程序設定
host.json檔案中的數個組態設定在函式事件中樞觸發程式系結的效能特性中扮演重要角色:
- maxEventBatchSize: 此設定代表函式在叫用時可以接收的事件數目上限。 如果收到的事件數目小於此數量,仍會以可用的事件數目來叫用函式。 您無法設定最小批次大小。
- prefetchCount: 預先擷取計數是優化效能時最重要的設定之一。 基礎AMQP通道會參考此值,以判斷要擷取和快取客戶端的訊息數量。 預先擷取計數應該大於或等於 maxEventBatchSize 值,而且通常會設定為該數量中的倍數。 將此值設定為小於 maxEventBatchSize 設定的數位可能會損害效能。
- batchCheckpointFrequency: 當您的函式處理批次時,此值會決定建立檢查點的速率。 默認值為 1,這表示每當函式成功處理單一批次時,就會有檢查點。 系統會在取用者群組中每個讀取器的數據分割層級建立檢查點。 如需此設定如何影響事件重新執行和重試的資訊,請參閱事件中樞觸發的 Azure 函式:重新執行和重試(部落格文章)。
執行數個效能測試,以判斷要為觸發程式系結設定的值。 建議您以累加方式變更設定,並持續測量以微調這些選項。 預設值是大部分事件處理解決方案的合理起點。
檢查點檢查
檢查點會標記或認可分割區事件順序中的讀取器位置。 當處理事件且符合批次檢查點頻率的設定時,函式主機會負責檢查點。 如需檢查點的詳細資訊,請參閱 Azure 事件中樞 中的功能和術語。
下列概念可協助您了解檢查點與函式處理事件的方式之間的關聯性:
- 例外狀況仍然計入成功: 如果函式進程在處理事件時不會當機,即使發生例外狀況,函式的完成也會被視為成功。 函式完成時,Functions 主機會 評估 batchCheckpointFrequency。 如果是檢查點的時間,則不論是否有例外狀況,都會建立檢查點。 例外狀況不會影響檢查點的事實,不應該影響您適當地使用例外狀況檢查和處理。
- 批次頻率很重要:在大量事件串流解決方案中,將 batchCheckpointFrequency 設定變更為大於 1 的值會很有説明。 增加此值可以降低檢查點建立速率,並因此減少記憶體 I/O 作業的數目。
- 重新執行可能發生: 每次使用事件中樞觸發程式系結叫用函式時,都會使用最新的檢查點來判斷繼續處理的位置。 每個取用者的位移會儲存在每個取用者群組的數據分割層級。 重新執行會在函式的最後一次叫用期間未發生檢查點,並再次叫用函式時發生。 如需重複和重複數據刪除技術的詳細資訊,請參閱 等冪性。
當您考慮錯誤處理和重試的最佳做法時,瞭解檢查點會變得很重要,本文稍後討論的主題。
遙測取樣
Functions 提供 Application Insights 的內建支援,這是 Azure 監視器的擴充功能,可提供應用程式效能監視功能。 透過這項功能,您可以記錄函式活動、效能、運行時間例外狀況等相關信息。 如需詳細資訊,請參閱 Application Insights 概觀。
這項功能強大的功能提供影響效能的一些重要組態選擇。 監視和效能的一些值得注意的設定和考慮包括:
- 啟用遙測取樣: 針對高輸送量案例,您應該評估所需的遙測和資訊量。 請考慮在 Application Insights 中使用遙測 取樣 功能,以避免使用不必要的遙測和計量來降低函式的效能。
- 設定匯總設定: 檢查和設定將數據匯總和傳送至 Application Insights 的頻率。 此組態設定位於host.json檔案中,以及許多其他取樣和記錄相關選項。 如需詳細資訊,請參閱 設定匯總工具。
- 停用 AzureWebJobDashboard:針對以 Functions 運行時間 1.x 版為目標的應用程式,此設定會將 連接字串 儲存至 Azure SDK 用來保留 WebJobs 儀錶板記錄的記憶體帳戶。 如果使用 Application Insights 而非 WebJobs 儀錶板,則應該移除此設定。 如需詳細資訊,請參閱 AzureWebJobsDashboard。
在未取樣的情況下啟用ApplicationInsights時,會傳送所有遙測。 傳送所有事件的相關數據可能會對函式的效能造成不利影響,特別是在高輸送量事件串流案例下。
利用取樣並持續評估監視所需的適當遙測量,對於最佳效能至關重要。 遙測應該用於一般平臺健康情況評估,以及偶爾進行疑難解答,而不是擷取核心商務計量。 如需詳細資訊,請參閱設定取樣。
輸出繫結
使用 Azure Functions 的事件中樞輸出系結,簡化從函式發佈至事件數據流。 使用此系結的優點包括:
- 資源管理: 系結會為您處理客戶端和聯機生命週期,並減少埠耗盡和連線集區管理可能發生的問題。
- 較少的程式代碼: 系結會擷取基礎 SDK,並減少您需要發佈事件的程式代碼數量。 它可協助您撰寫更容易撰寫和維護的程序代碼。
- 批處理: 針對數種語言,支援批處理以有效率地發佈至事件數據流。 批處理可以改善效能,並協助簡化傳送事件的程序代碼。
強烈建議您檢閱 Functions 支援的語言清單,以及這些語言的開發人員指南。 每個語言的 [ 系結] 區段會提供詳細的範例和檔。
發佈事件時的批處理
如果您的函式只發佈單一事件,將系結設定為傳回值是常見的方法,如果函式執行一律以傳送事件的語句結尾,則很有用。 這項技術只應用於只傳回一個事件的同步函式。
建議您在將多個事件傳送至數據流時改善效能。 批處理可讓系結以最有效率的方式發佈事件。
C#、Java、Python 和 JavaScript 提供使用輸出系結將多個事件傳送至事件中樞的支援。
使用同行程模型輸出多個事件 (C#)
當您從 C# 中的 函式傳送多個事件時,請使用 ICollector 和 IAsyncCollector 類型。
- ICollector<T>。Add() 方法可用於同步和異步函式。 它會在呼叫新增作業時立即執行。
- IAsyncCollector<T>。AddAsync() 方法會準備要發行至事件數據流的事件。 如果您撰寫異步函式,您應該使用 IAsyncCollector 來更妥善地管理已發佈的事件。
如需使用 C# 發佈單一和多個事件的範例,請參閱 Azure Functions 的 Azure 事件中樞 輸出系結。
使用隔離背景工作模型輸出多個事件 (C#)
根據 Functions 執行時間版本,隔離的背景工作模型會針對傳遞至輸出系結的參數支援不同類型的參數。 針對多個事件,會使用數位來封裝集合。 建議您檢閱隔離模型的輸出系結屬性和使用方式詳細數據,並記下擴充功能版本之間的差異。
節流和回溯壓力
節流考慮適用於輸出系結,不僅適用於事件中樞,也適用於 Azure Cosmos DB 等 Azure 服務。 請務必熟悉適用於這些服務的限制和配額,並據以規劃。
若要處理同進程模型中的下游錯誤,您可以將 AddAsync 和 FlushAsync 包裝在 .NET Functions 的例外狀況處理程式中,以便從 IAsyncCollector 攔截例外狀況。 另一個選項是直接使用事件中樞 SDK,而不是使用輸出系結。
如果您要針對函式利用隔離模型,則傳回輸出值時,應該使用結構化例外狀況處理來負責攔截例外狀況。
函式程序代碼
本節涵蓋撰寫程式代碼來處理事件中樞觸發之函式中的事件時,必須考慮的重要區域。
非同步程式設計
建議您撰寫函式來 使用異步程序代碼,並避免封鎖呼叫,尤其是在涉及 I/O 呼叫時。
以下是撰寫函式以異步方式處理時應遵循的指導方針:
- 所有異步或所有同步: 如果函式設定為以異步方式執行,則所有 I/O 呼叫都應該是異步的。 在大部分情況下,部分異步程式代碼會比完全同步的程式代碼更差。 選擇異步或同步,並堅持一路選擇。
- 避免封鎖呼叫: 只有在呼叫完成之後,封鎖呼叫才會傳回給呼叫端,與立即傳回的異步呼叫相反。 C# 中的範例是呼叫 異步操作的 Task.Result 或 Task.Wait 。
深入了解封鎖通話
使用異步操作的封鎖呼叫可能會導致線程集區耗盡,並導致函式進程當機。 發生當機是因為封鎖呼叫需要建立另一個線程,以補償目前正在等候的原始呼叫。 因此,它需要兩倍多的線程才能完成作業。
避免在涉及事件中樞時,透過異步方法進行這項 同步 處理特別重要,因為函式當機不會更新檢查點。 下次叫用函式時,它最終可能會在此迴圈中結束,而且似乎停滯或隨著函式執行最終逾時而緩慢移動。
針對這種現象進行疑難解答時,通常會從檢閱觸發程式設定和執行實驗開始,這些實驗可能涉及增加分割區計數。 調查也可能導致變更數個批處理選項,例如批次大小上限或預先擷取計數。 印象是,這是輸送量問題或組態設定,只需要據以調整。 不過,核心問題在於程序代碼本身,而且必須加以解決。
參與者
本文由 Microsoft 維護。 原始投稿人如下。
主要作者:
- 大衛·巴科爾 |主要解決方案專家 GBB
若要查看非公開的 LinkedIn 設定檔,請登入 LinkedIn。
下一步
在繼續之前,請考慮檢閱下列相關文章: