微軟Azure配置中心 App Configuration (三):配置的動態更新

Get Azure key-value pairs from App configuration | Serverless360

寫在前面

我在前文:

《微軟Azure配置中心 App Configuration (一):輕鬆集成到Asp.Net Core》已經介紹了Asp.net Core怎麼輕易的接入azure 配置中心App Configuration(下稱azure 配置中心);

《微軟Azure配置中心 App Configuration (二):Feature Flag 功能開關特性》 講Asp.net Core功能開關的兩種方式的簡單使用;

本文重點來講講Azure配置中心是怎麼配置的動態更新的。

概念定義

一般對配置中心來說都有動態更新的概念,我這裏給個定義:

配置中心的動態更新是指,當用戶在配置中心管理後臺更新配置後,集成的客戶端能以某種形式到配置的更新;

一般有兩種模式

  • 1、客戶端輪詢;
  • 2、服務端主動推送更新;包括但不限於Grpc(Nacos),Websocket等方式;

客戶端輪詢模式

本文在前文基礎上開始的,有些略過的地方請看前文;

1、修改集成方式

var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("AppConfig");

builder.Host.ConfigureAppConfiguration((hostingContext, config) =>
{
    //配置不同功能
    config.AddAzureAppConfiguration(options =>
    {
        ////啓用Label(多環境)支持
        //options.Connect(connectionString)
        //    .Select(KeyFilter.Any, LabelFilter.Null)//配置過濾器,讀取空Lable的配置
        //    .Select(KeyFilter.Any, hostingContext.HostingEnvironment.EnvironmentName); //配置過濾器,只讀取某個環境的配置

        //啓用Poll模式的主動更新
        options.Connect(connectionString)
            .Select(KeyFilter.Any, LabelFilter.Null)//配置過濾器,讀取空Lable的配置
            .Select(KeyFilter.Any, hostingContext.HostingEnvironment.EnvironmentName) //配置過濾器,只讀取某個環境的配置
            .ConfigureRefresh(refresh =>
            {
                refresh.Register("TestApp:Settings:Sentinel", refreshAll: true).SetCacheExpiration(new TimeSpan(0, 0, 30));
            });
    });
});

這裏方法ConfigureRefresh參數:

TestApp:Settings:Sentinel:這就是程序輪詢的配置Key;

refreshAll=true: 表示當輪詢的配置Key更新時,更新所有配置;

SetCacheExpiration:設置多久時間輪詢一次,這裏設置了30秒,這也是默認值;

2、注入服務

builder.Services.AddAzureAppConfiguration();

3、驗證

我們現在Azure配置管理後臺設置好key:TestApp:Settings:Sentinel

1659710138480

可以看到初始值==1;

我們新增一個測試的TestKey4==TestKey4-azure1659710272267

啓動程序後,我們無論怎麼修改配置後臺,都不會程序拿到值始終:TestKey4 ==TestKey4-azure

我們把監控Key:TestApp:Settings:Sentinel設置爲2

再次獲取可以看到,TestKey4 的值更新了:

1659710583034

OK,輪詢模式就是這麼樸實無華,卻又足以滿足大部分需求;

服務端主動推送更新

流程簡介

除了輪詢的方式動態更新配置外,Azure配置中心也提供了push的方式主動推送配置更新到客戶端,不過它的實現流程不太像我們經常遇到的Grpc或者Websocket等那樣直連的方式,而是藉助Azure消息隊列Service Bus實現的。

大體流程:

  1. 先創建一個Service Bus的Topic訂閱(類似於RabbitMQ的Topic);

  2. Azure配置中心註冊一個事件訂閱到Service Bus的Topic訂閱,當配置修改時觸發事件發送一個配置更新消息到Service Bus;

  3. 客戶端程序訂閱了Service Bus的Topic,實時接收配置更新消息並更新本地程序的IConfiguration;

下面我們看看流程怎麼實現;

1、先創建Service Bus的Topic訂閱

創建Service Bus命名空間

1659796317423

信息自己填

1659796361277

創建Topic

我創建的topic名:config-topic

1659759474037

創建topic訂閱

訂閱名:config-s1

1659759526382

1659759571039

ok,到這步位置,Service Bus這邊基本配置完;

2、創建配置中心的事件訂閱到topic訂閱

App Configuration下創建事件訂閱

填寫Topic訂閱信息

注意右側紅框,要選擇你上步創建的Service Bus 的Topic訂閱 config-topic

1659760042342

創建成功

1659760088732

3、Asp.Net Core中集成

安裝包

install-package Microsoft.Azure.ServiceBus

新增配置信息

 //ServiceBus 的配置
 "AzureServiceBusConfig": {
    "ConnectionString": "< ConnectionString >",
    "TopicName": "< Your TopicName >", //我的是config-topic
    "SubscriptionName": "< Your SubscriptionName >" // 我的是 config-s1
  }

修改ConfigureService做集成

var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("AppConfig");
IConfigurationRefresher _refresher = null;

builder.Host.ConfigureAppConfiguration((hostingContext, config) =>
{
    ////簡單使用只配置connection string
    //config.AddAzureAppConfiguration(connectionString);

    //配置不同功能
    config.AddAzureAppConfiguration(options =>
    {
        //啓用Push模式的主動推送更新配置
        options.Connect(connectionString)
            .Select(KeyFilter.Any, LabelFilter.Null)//配置過濾器,讀取空Lable的配置
            .Select(KeyFilter.Any, hostingContext.HostingEnvironment.EnvironmentName) //配置過濾器,只讀取某個環境的配置
            .ConfigureRefresh(refresh =>
            {
                refresh.Register("TestApp:Settings:Sentinel", refreshAll: true)
                       .SetCacheExpiration(TimeSpan.FromDays(10)); //這個刷新頻率要設置特別低了
            });
        _refresher = options.GetRefresher();

    });
});

TestApp:Settings:Sentinel:只訂閱這個key的刷新事件;

SetCacheExpiration:這裏的刷新頻率設置很低就行;

修改IApplicationBuilder集成

先寫個拓展方法


/// <summary>
/// 啓用一個Service bus事件處理程序在配置更新時刷新 IConfiguration
/// </summary>
/// <param name="app">The application.</param>
/// <param name="refresher">The refresher.</param>
/// <returns></returns>
/// <exception cref="System.ArgumentNullException">serviceBusConfig</exception>
public static IApplicationBuilder UseAzureConfigChangeEventHandler(this IApplicationBuilder app, IConfigurationRefresher refresher)
{
    var serviceBusConfig = PassportConfig.Get<AzureServiceBusConfig>(nameof(AzureServiceBusConfig));
    if (serviceBusConfig == null)
    {
        throw new ArgumentNullException(nameof(serviceBusConfig));
    }

    SubscriptionClient serviceBusClient = new SubscriptionClient(serviceBusConfig.ConnectionString, serviceBusConfig.TopicName, serviceBusConfig.SubscriptionName);

    serviceBusClient.RegisterMessageHandler(handler: (message, cancellationToken) =>
        {
            // 構建一個 EventGridEvent
            EventGridEvent eventGridEvent = EventGridEvent.Parse(BinaryData.FromBytes(message.Body));

            // 創建PushNotification
            eventGridEvent.TryCreatePushNotification(out PushNotification pushNotification);

            // 刷新IConfiguration
            refresher.ProcessPushNotification(pushNotification);
            refresher.TryRefreshAsync();

            return Task.CompletedTask;
        },
        exceptionReceivedHandler: (exceptionargs) =>
        {
            Console.WriteLine($"{exceptionargs.Exception}");
            return Task.CompletedTask;
        }
        );

    return app;
}

然後直接在管道中啓用

app.UseAzureConfigChangeEventHandler(_refresher);

這個函數的功能是,訂閱Service Bus的Topic ,當服務端配置修改時,接收配置更新信息,刷新本地配置;

驗證

還是用TestKey4來測試,先運行程序,

本來:TestKey4TestKey4-azure,我們改成:TestKey4TestKey4-azure 2022年8月6日

1659762724065

但怎麼刷新程序獲取的值都不會更新。

我們打個斷點到函數:UseAzureConfigChangeEventHandler(),再更新Key TestApp:Settings:Sentinel

看到,收到配置更新消息命中斷點了:

1659797999344

同時,通過Service Bus的後臺,我們也已看到配置更新事件消息正確發送:

1659798843360

我們再次獲取配置看到確已更新:

1659762786635

OK,服務端基於訂閱消息隊列獲取配置的主動更新方式驗證成功;

總結

1、我覺得動態更新配置用主動輪詢的方式基本能滿足大部分需求(但是每次輪詢消耗次數,請設置好輪詢間隔時間),基於消息隊列的主動推送方式稍微有點麻煩,看需求選用;

2、當配置中心的Key和本地配置文件的Key衝突時,以配置中心爲準;

3、總體來說Azure配置中心還是挺香的,除了貴(畢竟Azure 土豪雲),價格

Azure配置中心的基本學習到這裏告一段落,後面挖掘到更實用的功能/技巧將再次水文補充;

源碼

https://github.com/gebiWangshushu/Hei.Azure.Test

[參考]

https://docs.microsoft.com/en-us/azure/azure-app-configuration/overview

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章