• dotnetcore中的IOptionsSnapshot<>的自动更新原理


    1、首先讲讲ChangeToken.OnChange方法:

    原理是给一个CancellationToken注册一个消费者委托,调用CancellationToken的Cancel的时候会调用这个CancellationToken中所有的委托 代码实现如下:

    public static IDisposable OnChange(Func<IChangeToken> changeTokenProducer, Action changeTokenConsumer)
    {
        if (changeTokenProducer == null)
        {
            throw new ArgumentNullException("changeTokenProducer");
        }
        if (changeTokenConsumer == null)
        {
            throw new ArgumentNullException("changeTokenConsumer");
        }
        Action<object> callback = null;
        callback = delegate(object s)
        {
            IChangeToken changeToken = changeTokenProducer();
            try
            {
                changeTokenConsumer();
            }
            finally
            {
                changeToken.RegisterChangeCallback(callback, null);
            }
        };
        return changeTokenProducer().RegisterChangeCallback(callback, null);
    }
    2、IOptions<> 生命周期为Singleton,初始化的时候配置就已经存入缓存,并且不再更新
    3、IOptionsSnapshot<> 生命周期为Scope,初始化的时候会写入缓存,内容由OptionsMonitor提供,初始化OptionsMonitor的时候会给所有的IOtionsChangeTokenSource<T>对象的ChangeToken注册一个重载配置的方法代码如下
    using (IEnumerator<IOptionsChangeTokenSource<TOptions>> enumerator =  this._sources.GetEnumerator())
    {
        while (enumerator.MoveNext())
        {
            IOptionsChangeTokenSource<TOptions> source = enumerator.Current;
            ChangeToken.OnChange(() => source.GetChangeToken(), delegate
            {
                this.InvokeChanged();
            });
        }
    }

    这里的source.GetChangeToken中的Token是从IConfigurationRoot中获取的,以下代码可以证明:

    public class ConfigurationChangeTokenSource<TOptions> : IOptionsChangeTokenSource<TOptions>
        {
            private IConfiguration _config;
    
            /// <summary>
            /// Constructor taking the IConfiguration instance to watch.
            /// </summary>
            /// <param name="config">The configuration instance.</param>
            public ConfigurationChangeTokenSource(IConfiguration config)
            {
                if (config == null)
                {
                    throw new ArgumentNullException("config");
                }
                this._config = config;
            }
    
            /// <summary>
            /// Returns the reloadToken from IConfiguration.
            /// </summary>
            /// <returns></returns>
            public IChangeToken GetChangeToken()
            {
                return this._config.GetReloadToken();
            }
        }

    这里的_config就是调用AddOptions.Config(...)方法的时候注册进去的,而ConfigurationRoot在初始化的时候,会把自己的ChangeToken的Reload事件注册到所有的IConfigurationProvider对象的ChangeToken,代码如下

    public ConfigurationRoot(IList<IConfigurationProvider> providers)
    {
        if (providers == null)
        {
            throw new ArgumentNullException("providers");
        }
        this._providers = providers;
        using (IEnumerator<IConfigurationProvider> enumerator = providers.GetEnumerator())
        {
            while (enumerator.MoveNext())
            {
                IConfigurationProvider p = enumerator.Current;
                p.Load();
                ChangeToken.OnChange(() => p.GetReloadToken(), delegate
                {
                    this.RaiseChanged();
                });
            }
        }
    }
    private void RaiseChanged()
    {
        //执行自身的_changeToken的OnReload事件并且重新初始化一个ConfigurationReloadToken
        Interlocked.Exchange<ConfigurationReloadToken>(ref this._changeToken, new ConfigurationReloadToken()).OnReload();
    }

    这样就可以保证所有的ConfigurationProvider发生Reload的时候,IConfigurationRoot中的ChangeToken也会发生Reload事件。而我们的配置发生改变的时候,我们的ConfigurationProvider需要先更新Data数据,然后再触发他的Reload事件,就可以触发IConfigurationRoot的Reload事件,OptionsMonitor初始化的时候会给IConfigurationRoot的ChangeToken注册一个更新配置缓存的事件(前面说到过),所以OptionsMonitor就会更新配置缓存,然后下一次请求的时候创建的新IOptionsSnapshot<>接口对象就可以读取到更新之后的配置信息了

  • 相关阅读:
    MybatisPlus-03
    MybatisPlus-02
    MybatisPlus_01
    卷积网络可解释性复现 | Grad-CAM | ICCV | 2017
    卷积涨点论文 | Asymmetric Convolution ACNet | ICCV | 2019
    pytorch实现 | Deformable Convolutional Networks | CVPR | 2017
    图像处理论文详解 | Deformable Convolutional Networks | CVPR | 2017
    轮廓检测论文解读 | Richer Convolutional Features for Edge Detection | CVPR | 2017
    Argo CD使用指南:如何构建一套完整的GitOps?
    Kubernetes弃用Docker后怎么办?
  • 原文地址:https://www.cnblogs.com/dingsblog/p/6761804.html
Copyright © 2020-2023  润新知