在Azure隔离函数中刷新AppConfiguration值时如何刷新服务
如何在Azure App Config配置变更时刷新HttpClient的BaseAddress?
默认情况下,AddHttpClient注册时的配置委托只会执行一次,所以当App Config中的BaseUrl变更后,已创建的HttpClient不会自动更新BaseAddress。你可以通过以下两种方式实现动态刷新:
方法一:使用IOptionsMonitor在请求时动态更新BaseAddress
通过IOptionsMonitor监听配置变更,在每次使用HttpClient前手动更新BaseAddress:
- 先注册HttpClient(无需在注册时设置BaseAddress):
builder.Services.AddHttpClient("GitHub") .ConfigureHttpClient(httpClient => { // 配置不需要动态变更的请求头 httpClient.DefaultRequestHeaders.Add(HeaderNames.Accept, "application/vnd.github.v3+json"); httpClient.DefaultRequestHeaders.Add(HeaderNames.UserAgent, "HttpRequestsSample"); });
- 在使用HttpClient的服务/函数中,注入
IHttpClientFactory和IOptionsMonitor<AppConfigSettings>(AppConfigSettings是绑定App Config配置的实体类):
private readonly IHttpClientFactory _httpClientFactory; private readonly IOptionsMonitor<AppConfigSettings> _appConfigMonitor; public MyFunction(IHttpClientFactory httpClientFactory, IOptionsMonitor<AppConfigSettings> appConfigMonitor) { _httpClientFactory = httpClientFactory; _appConfigMonitor = appConfigMonitor; } public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequest req) { var client = _httpClientFactory.CreateClient("GitHub"); // 每次请求前读取最新的BaseUrl并设置 client.BaseAddress = new Uri(_appConfigMonitor.CurrentValue.BaseUrl!); // 执行请求逻辑 var response = await client.GetAsync("/repos/dotnet/AspNetCore.Docs/branches"); // ... }
方法二:自定义DelegatingHandler统一处理动态BaseAddress
创建自定义消息处理程序,在每次发送请求前自动应用最新的BaseUrl,无需修改业务代码:
- 实现自定义DelegatingHandler:
public class DynamicBaseAddressHandler : DelegatingHandler { private readonly IOptionsMonitor<AppConfigSettings> _appConfigMonitor; public DynamicBaseAddressHandler(IOptionsMonitor<AppConfigSettings> appConfigMonitor) { _appConfigMonitor = appConfigMonitor; } protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var latestBaseUrl = _appConfigMonitor.CurrentValue.BaseUrl!; // 处理相对路径的请求,自动拼接最新的BaseAddress if (request.RequestUri != null && !request.RequestUri.IsAbsoluteUri) { request.RequestUri = new Uri(new Uri(latestBaseUrl), request.RequestUri); } // 如果没有设置BaseAddress,直接赋值最新的 else if (request.BaseAddress == null) { request.BaseAddress = new Uri(latestBaseUrl); } return await base.SendAsync(request, cancellationToken); } }
- 注册Handler和HttpClient:
// 注册自定义Handler builder.Services.AddTransient<DynamicBaseAddressHandler>(); builder.Services.AddHttpClient("GitHub") .AddHttpMessageHandler<DynamicBaseAddressHandler>() .ConfigureHttpClient(httpClient => { // 配置固定请求头 httpClient.DefaultRequestHeaders.Add(HeaderNames.Accept, "application/vnd.github.v3+json"); httpClient.DefaultRequestHeaders.Add(HeaderNames.UserAgent, "HttpRequestsSample"); });
- 使用时直接注入HttpClient即可,无需额外处理BaseAddress:
private readonly HttpClient _githubClient; public MyFunction(IHttpClientFactory httpClientFactory) { _githubClient = httpClientFactory.CreateClient("GitHub"); } public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequest req) { // 直接发送相对路径请求,Handler会自动拼接最新的BaseUrl var response = await _githubClient.GetAsync("/repos/dotnet/AspNetCore.Docs/branches"); // ... }
前置条件
确保你已经正确配置了Azure App Config的动态刷新:
- 在配置App Config时启用了刷新机制(注册需要刷新的配置项并设置缓存过期时间)
- 绑定了
AppConfigSettings到对应的配置节 - 在Functions中启用了动态配置刷新(如添加
UseAzureAppConfiguration()中间件)
内容的提问来源于stack exchange,提问作者Punter Vicky
相关产品推荐
相关产品推荐

