写在前面

我在前文:

《微软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

可以看到初始值==1;

我们新增一个测试的TestKey4==TestKey4-azure

启动程序后,我们无论怎么修改配置后台,都不会程序拿到值始终:TestKey4 ==TestKey4-azure

我们把监控Key:TestApp:Settings:Sentinel设置为2

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

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命名空间

信息自己填

创建Topic

我创建的topic名:config-topic

创建topic订阅

订阅名:config-s1

ok,到这步位置,Service Bus这边基本配置完;

2、创建配置中心的事件订阅到topic订阅

App Configuration下创建事件订阅

填写Topic订阅信息

注意右侧红框,要选择你上步创建的Service Bus 的Topic订阅 config-topic

创建成功

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日

但怎么刷新程序获取的值都不会更新。

我们打个断点到函数:UseAzureConfigChangeEventHandler(),再更新Key TestApp:Settings:Sentinel

看到,收到配置更新消息命中断点了:

同时,通过Service Bus的后台,我们也已看到配置更新事件消息正确发送:

我们再次获取配置看到确已更新:

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

最新文章

  1. c# c++ oc java || mac android ios
  2. QEMU 中的QOM分析
  3. What Is Mathematics?
  4. Teamcenter 2007 &quot;由于某些意外的 DBMS 错误失败&quot;
  5. MyBatis拦截器原理探究
  6. Spring使用环境变量控制配置文件加载
  7. Sharepoint学习笔记—习题系列--70-573习题解析 -(Q118-Q120)
  8. flex数据交互方式 转
  9. css3动画使用技巧之—JQ配合css3实现轮播之animation-delay应用
  10. Qt 之 show,hide,setVisible,setHidden,close 等小结
  11. Python学习笔记(十四)
  12. python 金融网贷数据,pandas进行数据分析并可视化系列 (词频统计,基本操作)
  13. centos7中输入ifconfig出现ens33,没有eth0
  14. 实战Performance Monitor监测EnyimMemcached
  15. CSS 实现隐藏滚动条同时又可以滚动
  16. MyEclipse2014安装插件的几种方式(适用于Eclipse或MyEclipse其他版本)
  17. 形成一个zigzag数组(JPEG编码里取像素数据的排列顺序)
  18. ubuntu16.04 中文输入法
  19. SDET面试之感受篇。
  20. 释放Linux系统缓存

热门文章

  1. Linux Cgroup v1(中文翻译)(1):Control Group
  2. midway的使用教程
  3. Nginx安装及支持https代理配置和禁用TSLv1.0、TSLv1.1配置
  4. 文件输入输出处理-File
  5. Kali MSF漏洞利用
  6. bat-安装程序-切换路径的问题(小坑)
  7. JS 会有变量提升和函数提升
  8. CPI教程-异步接口创建及使用
  9. 解决方案:可以ping别人,但是别人不能ping我
  10. 6. RDD综合练习:更丰富的操作