zoukankan      html  css  js  c++  java
  • Polly简介 — 2. 弹性策略

    和故障处理策略不同的是,弹性策略并不是针对委托执行过程中的异常进行处理,而是改变委托本身的行为,因此弹性策略并没有故障定义这一过程,它的处理流程为:

    1. 定义策略
    2. 应用策略

    Polly对弹性策略也做了不少支持,本文这里就简单的介绍一下。

    弹性策略:超时(Timeout)

    超时策略用于控制委托的运行时间,如果达到指定时间还没有运行,则触发超时异常。

    Policy.Timeout(TimeSpan.FromSeconds(3), TimeoutStrategy.Pessimistic);

    超时策略常见的重载版本有如下几个:

    Policy.Timeout(300);
    Policy.Timeout(TimeSpan.FromMilliseconds(3));
    Policy.Timeout(() => TimeSpan.FromSeconds(3));
    Policy.Timeout(TimeSpan.FromSeconds(3), TimeoutStrategy.Optimistic);

    超时策略:

    Polly支持两种超时策略:

    • TimeoutStrategy.Pessimistic: 悲观模式
      当委托到达指定时间没有返回时,不继续等待委托完成,并抛超时TimeoutRejectedException异常。
    • TimeoutStrategy.Optimistic:乐观模式
      这个模式依赖于 co-operative cancellation,只是触发CancellationTokenSource.Cancel函数,需要等待委托自行终止操作。

    其中悲观模式比较容易使用,因为它不需要在委托额外的操作,但由于它本身无法控制委托的运行,函数本身并不知道自己被外围策略取消了,也无法在超时的时候中断后续行为。因此用起来反而还不是那么实用。

    一个乐观模式的的策略示例如下:

    var policy = Policy.Timeout(300);
    var cts = new CancellationTokenSource();
    policy.Execute(ct =>
    {
        for (int i = 0; i < 1000; i++)
        {
            Thread.Sleep(100);
            ct.ThrowIfCancellationRequested();
        }
    }, cts.Token);

    复合策略:

    在日常的使用中,仅仅只有超时往往是并不够的,很多时候还需要和重试等其它故障处理策略一起使用,如:

    Policy.Handle<TimeoutRejectedException>()
        .Retry(3)
        .Wrap(Policy.Timeout(3, TimeoutStrategy.Pessimistic));

     

    弹性策略:无操作(NoOp)

    在开发过程中,处于测试或定位问题时的需要,有时我们也需要一个没有任何行为的策略,Polly系统默认提供了一个.

    Policy.NoOp();

    这个啥都没干,也没啥好介绍的了。

     

    弹性策略:缓存(Cache)

    有的时候,数据更新并不是频繁的,此时可以使用缓存策略减少对服务的访问,提高系统性能:

    var memoryCacheProvider =
        new Polly.Caching.MemoryCache.MemoryCacheProvider(new System.Runtime.Caching.MemoryCache("cache"));

    var cachePolicy = Policy.Cache(memoryCacheProvider, TimeSpan.FromMinutes(5));

    //Context.ExecutionKey
    就是cachekey
    var context = new Context("cache_key");
    for (int i = 0; i < 3; i++)
    {
        var cache = cachePolicy.Execute(_ =>
        {
            Console.WriteLine("get value");
            return 3;
        }, context);
        Console.WriteLine(cache);
    }

    PS:这个示例使用了MemoryCache,需要使用Nuget安装Polly.Caching.MemoryCache程序包,以及添加System.Runtime.Caching的引用。

    从运行结果可以看到,虽然三次执行都有结果,但系统只有第一次才需要执行函数,剩下两次都是直接从缓存中获取的结果。

    系统也提供了多种不同的过期策略:

    Policy.Cache(memoryCacheProvider, new AbsoluteTtl(DateTimeOffset.Now.Date.AddDays(1)));
    Policy.Cache(memoryCacheProvider, new SlidingTtl(TimeSpan.FromMinutes(5)));

    对于布式缓存,Polly也有默认的实现,只需要安装Polly.Caching.IdistributedCache程序包即可,它提供了SqlServer和Redis的支持。

    关于Cache的更多内容,可以参考官方文档:Cache

     

    弹性策略:舱壁隔离(Bulkhead Isolation)

    舱壁隔离是一种并发控制的行为,并发控制是一个比较常见的模式,Polly也提供了这方面的支持,如:

    //该策略下最多只有12个任务并发执行
    Policy.Bulkhead(12);

    超过了并发数的任务会抛BulkheadRejectedException,如果要放在队列中等待,Polly也提供了等待队列的支持:

    Policy.Bulkhead(12, 100);

    这种方式下,有12个并发任务,每个任务维持着一个并发队列,每个队列可以自持最大100个任务。

    不过,和微软自己的DataFlow模块比起来,感觉Polly模块的并发控制的功能还是比较弱的。不过这也它本身的应用场景也相关,如果需要更强大的策略,也可以自行封装。

     

    弹性策略:策略封装(PolicyWrap)

    我们可以通过PolicyWrap的方式,封装出一个更加强大的策略:

    var fallback = Policy<int>.Handle<TimeoutException>().Fallback(100);
    var retry = Policy<int>.Handle<TimeoutException>().Retry(2);

    Policy.Wrap(fallback, retry);

    这个策略就是将Retry和Fallback组合起来,形成一个retry and fallback的策略,也可以写成如下形式:

    var retryAndFallback = fallback.Wrap(retry);

    当执行这个新策略时:

    retryAndFallback.Execute(DoSomething);

    等价于执行:

    fallback.Execute(()=> retry.Execute(DoSomething));

  • 相关阅读:
    规矩与管理
    信息系统叫设施比叫工具更贴近本义
    让ansbile和docker愉快的在一起
    elasearch基础教程
    markdown语法
    python 实用pickle序列化
    python 解析配置文件
    ansible状态管理
    haproxy官方配置文档地址
    ansible操作模块相关
  • 原文地址:https://www.cnblogs.com/TianFang/p/8215732.html
Copyright © 2011-2022 走看看