Share via


教學課程:在 .NET 應用程式中使用推送重新整理使用動態設定

應用程式組態 .NET 用戶端連結庫支援視需要更新設定,而不會造成應用程式重新啟動。 應用程式可以設定成使用下列兩種方式中,其中一種或兩種方式來偵測應用程式組態中的變更。

  1. 輪詢模型:這是預設行為,使用輪詢來偵測組態變更。 設定的快取值到期後,下一次呼叫 TryRefreshAsyncRefreshAsync 會將要求傳送給伺服器,以檢查組態是否已變更,並視需要提取更新的組態。

  2. 推送模型:使用應用程式組態事件來偵測組態中發生的變更。 一旦應用程式組態設定為傳送機碼值變更事件至 Azure Event Grid,應用程式就可以使用這些事件來最佳化所需的要求總數,讓組態保持更新狀態。 應用程式可以選擇直接從事件方格訂閱這些事件,或透過其中一個支援的事件處理常式,例如 Webhook、Azure 函式或服務匯流排主題。

本教學課程會示範如何使用推送重新整理在您的程式碼中實作動態組態更新。 其會以本教學課程中介紹的應用程式作為基礎。 繼續之前,請先完成教學課程: 先在 .NET 應用程式中 使用動態設定。

您可以使用任何程式碼編輯器來進行本教學課程中的步驟。 Windows、macOS 及 Linux 平台上都有提供的 Visual Studio Code 是一個絕佳的選項。

在本教學課程中,您會了解如何:

  • 設定訂用帳戶,將組態變更事件從應用程式組態傳送至服務匯流排主題
  • 設定 .NET 應用程式以更新其設定,以回應 應用程式組態 中的變更。
  • 在您的應用程式中使用最新的組態。

必要條件

設定 Azure 服務匯流排主題與訂用帳戶

本教學課程使用事件方格的服務匯流排整合,針對不想要持續輪詢應用程式組態變更的應用程式,簡化組態變更偵測。 Azure 服務匯流排 SDK 會提供 API 來註冊訊息處理常式,可在應用程式組態中偵測到變更時用來更新組態。 請遵循快速入門:使用 Azure 入口網站 建立 服務匯流排 主題和訂用帳戶,以建立服務總線命名空間、主題和訂用帳戶。

建立資源之後,請新增下列環境變數。 此變數會用來註冊事件處理常式,以用於應用程式程式碼中的組態變更。

機碼
ServiceBusConnectionString 服務匯流排命名空間的連接字串
ServiceBusTopic 服務匯流排主題的名稱
ServiceBusSubscription 服務匯流排訂用帳戶的名稱

設定事件訂閱

  1. 在 Azure 入口網站中開啟應用程式組態資源,然後按一下 Events 窗格中的 + Event Subscription

    應用程式組態事件

  2. Event SubscriptionSystem Topic 輸入其名稱。

    建立事件訂閱

  3. 選取 Endpoint Type 作為 Service Bus Topic,選取 [服務匯流排主題],然後按一下 Confirm Selection

    事件訂用帳戶服務總線端點

  4. Create 按一下以建立事件訂用帳戶。

  5. 按一下 Events 窗格中的 Event Subscriptions,以驗證訂閱已成功建立。

    應用程式組態 事件訂用帳戶

注意

訂閱組態變更時,可以使用一或多個篩選條件來減少傳送至應用程式的事件數目。 這些可以設定為事件方格訂用帳戶篩選條件服務匯流排訂用帳戶篩選條件。 例如,訂閱篩選條件可用來只訂閱針對以特定字串開頭的索引碼變更事件。

請註冊事件處理常式,以從應用程式組態重新載入資料

開啟 Program.cs 檔案,並以下列程式碼更新該檔案。

using Azure.Messaging.EventGrid;
using Azure.Messaging.ServiceBus;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.AzureAppConfiguration;
using Microsoft.Extensions.Configuration.AzureAppConfiguration.Extensions;
using System;
using System.Threading.Tasks;

namespace TestConsole
{
    class Program
    {
        private const string AppConfigurationConnectionStringEnvVarName = "AppConfigurationConnectionString";
        // e.g. Endpoint=https://{store_name}.azconfig.io;Id={id};Secret={secret}
        
        private const string ServiceBusConnectionStringEnvVarName = "ServiceBusConnectionString";
        // e.g. Endpoint=sb://{service_bus_name}.servicebus.windows.net/;SharedAccessKeyName={key_name};SharedAccessKey={key}
        
        private const string ServiceBusTopicEnvVarName = "ServiceBusTopic";
        private const string ServiceBusSubscriptionEnvVarName = "ServiceBusSubscription";

        private static IConfigurationRefresher _refresher = null;

        static async Task Main(string[] args)
        {
            string appConfigurationConnectionString = Environment.GetEnvironmentVariable(AppConfigurationConnectionStringEnvVarName);

            IConfiguration configuration = new ConfigurationBuilder()
                .AddAzureAppConfiguration(options =>
                {
                    options.Connect(appConfigurationConnectionString);
                    options.ConfigureRefresh(refresh =>
                        refresh
                            .Register("TestApp:Settings:Message")
                            // Important: Reduce poll frequency
                            .SetCacheExpiration(TimeSpan.FromDays(1))  
                    );

                    _refresher = options.GetRefresher();
                }).Build();

            await RegisterRefreshEventHandler();
            var message = configuration["TestApp:Settings:Message"];
            Console.WriteLine($"Initial value: {configuration["TestApp:Settings:Message"]}");

            while (true)
            {
                await _refresher.TryRefreshAsync();

                if (configuration["TestApp:Settings:Message"] != message)
                {
                    Console.WriteLine($"New value: {configuration["TestApp:Settings:Message"]}");
                    message = configuration["TestApp:Settings:Message"];
                }

                await Task.Delay(TimeSpan.FromSeconds(1));
            }
        }

        private static async Task RegisterRefreshEventHandler()
        {
            string serviceBusConnectionString = Environment.GetEnvironmentVariable(ServiceBusConnectionStringEnvVarName);
            string serviceBusTopic = Environment.GetEnvironmentVariable(ServiceBusTopicEnvVarName);
            string serviceBusSubscription = Environment.GetEnvironmentVariable(ServiceBusSubscriptionEnvVarName); 
            ServiceBusClient serviceBusClient = new ServiceBusClient(serviceBusConnectionString);
            ServiceBusProcessor serviceBusProcessor = serviceBusClient.CreateProcessor(serviceBusTopic, serviceBusSubscription);

            serviceBusProcessor.ProcessMessageAsync += (processMessageEventArgs) =>
            {
                // Build EventGridEvent from notification message
                EventGridEvent eventGridEvent = EventGridEvent.Parse(BinaryData.FromBytes(processMessageEventArgs.Message.Body));

                // Create PushNotification from eventGridEvent
                eventGridEvent.TryCreatePushNotification(out PushNotification pushNotification);

                // Prompt Configuration Refresh based on the PushNotification
                _refresher.ProcessPushNotification(pushNotification);

                return Task.CompletedTask;
            };

            serviceBusProcessor.ProcessErrorAsync += (exceptionargs) =>
            {
                Console.WriteLine($"{exceptionargs.Exception}");
                return Task.CompletedTask;
            };

            await serviceBusProcessor.StartProcessingAsync();
        }
    }
}

ProcessPushNotification 方法會將快取到期時間重設為短時間隨機延遲。 此作法會導致未來呼叫 RefreshAsyncTryRefreshAsync 時針對應用程式組態重新驗證快取的值,並視需要加以更新。 在此範例中,您會註冊來監視索引碼發生的變更:TestApp:Settings:Message,快取到期日為一天。 這表示在上次檢查再一天過後,不會向應用程式組態提出任何要求。 藉由呼叫 ProcessPushNotification,您的應用程式將會在下幾秒內將要求傳送至應用程式組態。 您的應用程式會在 App Configuration 存放區中發生變更之後,立即載入新的組態值,而不需要持續輪詢以進行更新。 如果您的應用程式因為任何原因而遺漏變更通知,其仍會每天檢查組態變更一次。

如果您有許多應用程式執行個體或微服務使用推送模型連線到相同的應用程式組態存放區,快取到期的短時間隨機延遲將會很有幫助。 如果未設定此延遲,應用程式的所有執行個體可能會在收到變更通知時,立即將要求傳送至您的應用程式組態存放區。 此舉動可能會導致應用程式組態服務節流您的存放區。 快取到期延遲預設會設定為介於 0 到最多 30 秒之間的隨機時數,但您可以透過選擇性參數 maxDelay 將最大值變更為 ProcessPushNotification 方法。

方法ProcessPushNotification會接受 物件,PushNotification其中包含 應用程式組態 觸發推播通知之變更的相關信息。 這有助於確保觸發事件的所有組態變更都會在下列組態重新整理中被載入。 SetDirty方法不保證會觸發立即組態重新整理中載入推播通知的變更。 如果您使用推送模型的 SetDirty 方法,建議您改用 ProcessPushNotification 方法。

於本機建置並執行應用程式

  1. 設定名為 AppConfigurationConnectionString 的環境變數,並將其設定為應用程式組態存放區的存取金鑰。

    如果您使用 Windows 命令提示字元來組建和在本機執行應用程式,請執行下列命令,然後重新啟動命令提示字元以讓變更生效:

    setx AppConfigurationConnectionString "connection-string-of-your-app-configuration-store"
    
  2. 執行下列命令來建置主控台應用程式:

    dotnet build
    
  3. 建置成功完成後,請執行下列命令以於本機執行應用程式:

    dotnet run
    

    更新前的推送重新整理執行

  4. 登入 Azure 入口網站。 選取 [所有資源],然後選取您在快速入門中建立的應用程式組態存放區執行個體。

  5. 選取 [組態總管],然後更新下列索引鍵的值:

    機碼
    TestApp:Settings:Message Azure 應用程式設定的值 - 已更新
  6. 請稍候片刻,以允許處理事件。 您會看到更新的組態。

    更新之後的推送重新整理執行

清除資源

如果您不想繼續使用本文中建立的資源,請刪除在此處建立的資源群組,以避免產生費用。

重要

刪除資源群組是無法回復的動作。 資源群組和其中的所有資源都將被永久刪除。 請確定您不會誤刪錯誤的資源群組或資源。 如果您是在包含需保留其他資源的資源群組內部,建立本文的資源,則可以從每個資源各自的窗格中個別刪除每個資源,而不必刪除整個資源群組。

  1. 登入 Azure 入口網站,然後選取 [資源群組]
  2. 在 [依名稱篩選] 方塊中,輸入您資源群組的名稱。
  3. 在結果清單中,選取資源群組名稱以查看概觀。
  4. 選取 [刪除資源群組]
  5. 系統將會要求您確認是否刪除資源群組。 輸入您資源群組的名稱以進行確認,然後選取 [刪除]

不久後,系統便會刪除該資源群組及其所有的資源。

下一步

在本教學課程中,您已啟用 .NET 應用程式,以動態方式從應用程式組態重新整理組態設定。 若要了解如何使用 Azure 受控服務識別來簡化對應用程式組態的存取,請繼續進行下一個教學課程。