前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >.NET Core开发实战(第16课:选项数据热更新:让服务感知配置的变化)--学习笔记

.NET Core开发实战(第16课:选项数据热更新:让服务感知配置的变化)--学习笔记

作者头像
郑子铭
发布2021-01-13 15:25:04
5860
发布2021-01-13 15:25:04
举报

16 | 选项数据热更新:让服务感知配置的变化

选项框架还有两个关键类型:

1、IOptionsMonitor

2、IOptionsSnapshot

场景:

1、范围作用域类型使用 IOptinsSnapshot

2、单例服务使用 IOptionsMonitor

通过代码更新选项:

IPostConfigureOptions

延续上一节的代码,但是做一些特殊处理,之前注册 Order 服务用的是单例模式,这里改为 Scoped 模式

代码语言:javascript
复制
public void ConfigureServices(IServiceCollection services)
{
    services.Configure<OrderServiceOptions>(Configuration.GetSection("OrderService"));
    //services.AddSingleton<IOrderService, OrderService>();
    services.AddScoped<IOrderService, OrderService>();
    services.AddControllers();
}

service 还是使用 IOptions

代码语言:javascript
复制
public class OrderService : IOrderService
{
    IOptions<OrderServiceOptions> _options;
    
    public OrderService(IOptions<OrderServiceOptions> options)
    {
        _options = options;
    }

    public int ShowMaxOrderCount()
    {
        return _options.Value.MaxOrderCount;
    }
}

启动程序,输出如下:

代码语言:javascript
复制
orderService.ShowMaxOrderCount:200

修改配置

代码语言:javascript
复制
{
    "OrderService": {
    "MaxOrderCount": 2000
  }
}

启动程序,输出如下:

代码语言:javascript
复制
orderService.ShowMaxOrderCount:200

输出值还是200

那么如何能够读到新的配置呢?

只需要把 IOptions 换成 IOptionsSnapshot 即可

代码语言:javascript
复制
IOptionsSnapshot<OrderServiceOptions> _options;

public OrderService(IOptionsSnapshot<OrderServiceOptions> options)
{
    ...
}

这是因为我们的服务注册的是 Scoped 模式,并且使用 Snapshot 来读取配置,每次请求都会重新计算并读取配置

那如果我们的服务是单例的时候怎么办呢?

把服务注册改为单例模式

代码语言:javascript
复制
services.AddSingleton<IOrderService, OrderService>();

这里需要使用另一个接口,把 Snapshot 改为 Monitor

代码语言:javascript
复制
IOptionsMonitor<OrderServiceOptions> _options;

public OrderService(IOptionsMonitor<OrderServiceOptions> options)
{
    ...
}

Monitor 与 Snapshot 的定义略微有些不同,它获取值是需要用 CurrentValue 字段

代码语言:javascript
复制
public int ShowMaxOrderCount()
{
    return _options.CurrentValue.MaxOrderCount;
}

启动程序,修改配置文件,刷新浏览器,可以看到输出了修改后的数据,也就是说单例对象同时也能读取到最新的配置

如果说我想知道配置的值发生变化并且通知到我的 Options 怎么做呢?

首先看一下 Monitor 的定义

代码语言:javascript
复制
namespace Microsoft.Extensions.Options
{
  public interface IOptionsMonitor<out TOptions>
  {

    TOptions CurrentValue { get; }

    TOptions Get(string name);

    IDisposable OnChange(Action<TOptions, string> listener);
  }
}

它有一个 OnChange 方法,也就是说可以监听它的变更

代码语言:javascript
复制
public OrderService(IOptionsMonitor<OrderServiceOptions> options)
{
    _options = options;

    _options.OnChange(option =>
    {
        Console.WriteLine($"配置更新了,最新的值是:{_options.CurrentValue.MaxOrderCount}");
    });
}

启动程序,修改配置,可以看到输出配置变化,也就是说可以在单例模式下监听到 Options 的变化

通常情况下,在设计服务的时候,会在 ConfigureServices 添加配置注入、服务注入,但是当配置多起来的时候,注入代码就会非常多

那么如何使代码结构更加良好?

实际上可以把服务注册的代码放在静态扩展方法里,使得 ConfigureServices 更加简洁

代码语言:javascript
复制
namespace Microsoft.Extensions.DependencyInjection
{
    public static class OrderServiceExtensions
    {
        public static IServiceCollection AddOrderService(this IServiceCollection services,IConfiguration configuration)
        {

            services.Configure<OrderServiceOptions>(configuration);
            services.AddSingleton<IOrderService, OrderService>();
            return services;
        }
    }
}

这样在 Startup 的注册就变得更为简单了

代码语言:javascript
复制
services.AddOrderService(Configuration.GetSection("OrderService"));

我们在设计系统的时候会涉及大量的 service,所以我们可以把 service 的注册提炼在扩展方法里,不同的模块用不同的扩展方法隔开,使模块之间更加清晰,代码的结构也更加的清晰

那么实际上我们在设计服务的时候,还有一些特殊的述求,比如说把配置读取出来之后,还需要在内存里面进行一些特殊的处理,我们就可以使用动态配置的方式

动态配置的方式是在我们的 Configure 的代码之后,调用 PostConfigure 的方法,这里需要配置 OrderServiceOptions

代码语言:javascript
复制
{
    public static class OrderServiceExtensions
    {
        public static IServiceCollection AddOrderService(this IServiceCollection services,IConfiguration configuration)
        {

            services.Configure<OrderServiceOptions>(configuration);
            
            services.PostConfigure<OrderServiceOptions>(options =>
            {
                options.MaxOrderCount += 20;
            });
            
            services.AddSingleton<IOrderService, OrderService>();
            return services;
        }
    }
}

启动程序,可以看到输出动态增加了20

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DotNet NB 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 16 | 选项数据热更新:让服务感知配置的变化
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档