Azure / AppConfiguration-DotnetProvider

The .NET Standard configuration provider for Azure App Configuration
https://github.com/Azure/AppConfiguration
MIT License
80 stars 37 forks source link

Force to reload configuration periodically #231

Open zhenlan opened 3 years ago

zhenlan commented 3 years ago

Consider adding an API so data from App Configuration can be reloaded periodically at custom intervals regardless of whether the registered keys have been modified or have refreshAll=true. This helps to reload values of Key Vault references, so App Config is more useful in "secret/cert rotation" scenarios.

cc: @jimmyca15 @avanigupta @abhilasharora @drago-draganov

theo-albers commented 3 years ago

Yes, please and disabling caching would be part of this feature.

What I find confusing is the ConfigureRefresh API: when I upgraded to v4.x I had to remove the SetCacheExpiration call, since I have no watchers (see #162). Adding SetCacheExpiration results in a runtime exception, which is not so nice.

Without documentation it's difficult to tell what the default behavior is of the caching algorithm. When I look at the code I see some conditional statements like "if watchers.count > 0 then use configured timeout else use default timeout". The default timeout is 30 seconds. Now you can't override the default timeout, but I have no confirmation this means that the cache will last forever.

From the feature management perspective I suddenly have "UseFeatureFlags(x => x.CacheExpirationInterval...". I noticed in my production environment feature flag requests from Azure App Configuration, which I didn't expect. So the default behavior of feature flags is different than the regular config values. Why?

We also have some KeyVault keys mapped to AAC. I don't know what the cache refresh options are in this case. How do we set that, is that on a specific config provider?

Summary:

avanigupta commented 3 years ago

Hi @theo-albers, here's a short description of the refresh behavior for key-values, feature flags and Key Vault references.

Key-Values

We don't support a default cache expiration interval for all key-values yet. You must register each key-value which needs to be monitored for changes and then set cache expiration for those registered key-values. We use the default cache expiration value of 30 seconds only if you register a key-value for refresh, but don't set a cache expiration time.

If you want to avoid refreshing any key-values from AppConfig, just remove the ConfigureRefresh method from your code. Your key-values will be refreshed only when you call ConfigureRefresh and register a specific key for refresh. The concept of cache expiration time applies only if ConfigureRefresh is invoked. If ConfigureRefresh is not invoked, the cache will last forever and nothing will be reloaded from App Config.

Feature Flags

The feature flag cache expiration is different from the key-value cache expiration time. Feature flags are always refreshed by default. If you need a workaround to avoid reloading any feature flags, you may set an arbitrarily high cache expiration time in UseFeatureFlags method. Starting from v4.4.0, you can also select which feature flags your application needs to load by invoking the Select method in UseFeatureFlags. Please see this discussion about selecting feature flags and disabling feature flag refresh: #163

Key Vault References

We recently released a new API in v4.4.0 to enable refreshing secrets from Key Vault. Please see this for more details: #249

Let me know if you have any more questions.

theo-albers commented 3 years ago

Thanks for the great summary @avanigupta, much appreciated!

gkarnik-gl commented 3 years ago

Can I refresh the provider on-demand using IConfigurationRefresher instance since IConfigurationRefresherProvider is now available as part of dependency injection? I tried invoking TryRefreshAsync but don't see the key values refreshed in IConfiguration instance even in subsequent calls even though the TryRefreshAsync returns true.

var azAppConfigRefresher = _configurationRefresherProvider.Refreshers.FirstOrDefault();
await azAppConfigRefresher.TryRefreshAsync();
avanigupta commented 3 years ago

Hello @gkarnik-gl, yes, it's possible to refresh configuration on demand by invoking TryRefreshAsync method. There are two common issues which could cause your configuration to not refresh:

  1. In order to keep the settings updated and avoid too many calls to App Configuration, a cache is used for each setting. Until the cached value of a setting has expired, the refresh operation does not update the value, even when the value has changed in the App Configuration store. The default cache expiration time for a configuration setting is 30 seconds, but can be overridden by calling the SetCacheExpiration method on the options initializer passed as an argument to the ConfigureRefresh method. Make sure that TryRefreshAsync is called after the cache expiration time has elapsed.

  2. In the ConfigureRefresh method, you register keys in your App Configuration store that you want to monitor for changes. The refreshAll parameter to the Register method indicates whether all configuration values should be updated if the registered key changes. If refreshAll is false, only the registered key's value will be refreshed.