예제 #1
0
        /// <summary>
        /// 超时处理
        /// 用途:请求网络接口,避免接口长期没有响应造成系统卡死。
        /// </summary>
        private static void Timeout()
        {
            ISyncPolicy policy = Policy.Handle <Exception>()
                                 .Fallback(() =>
            {
                Console.WriteLine("执行出错");
            }, ex =>
            {
                Console.WriteLine("详细异常对象" + ex);
            });

            policy = policy.Wrap(Policy.Timeout(2, TimeoutStrategy.Pessimistic));

            policy.Execute(() =>
            {
                Console.WriteLine("开始任务");
                Thread.Sleep(5000);
                Console.WriteLine("完成任务");
            });

            //        ISyncPolicy policy = Policy.Handle<TimeoutRejectedException>()
            //.Retry(1);
            //        policy = policy.Wrap(Policy.Timeout(3, TimeoutStrategy.Pessimistic));
            //        policy.Execute(() =>
            //        {
            //            Console.WriteLine("开始任务");
            //            Thread.Sleep(5000);
            //            Console.WriteLine("完成任务");
            //        });
        }
예제 #2
0
        public void Generic_interface_wraps_generic_instance_syntax_wrapping_null_should_throw()
        {
            ISyncPolicy <int> retry = Policy.HandleResult <int>(0).Retry(1);

            Action config = () => retry.Wrap((Policy <int>)null);

            config.ShouldThrow <ArgumentNullException>().And.ParamName.Should().Be("innerPolicy");
        }
예제 #3
0
        public void Generic_interface_wraps_nongeneric_instance_syntax_null_wrapping_should_throw()
        {
            ISyncPolicy <int> outerNull = null;
            ISyncPolicy       retry     = Policy.Handle <Exception>().Retry(1);

            Action config = () => outerNull.Wrap(retry);

            config.ShouldThrow <ArgumentNullException>().And.ParamName.Should().Be("outerPolicy");
        }
예제 #4
0
        public void Generic_interface_wraps_generic_using_instance_wrap_syntax_should_set_outer_inner()
        {
            ISyncPolicy <int> policyA = Policy.NoOp <int>();
            ISyncPolicy <int> policyB = Policy.NoOp <int>();

            IPolicyWrap <int> wrap = policyA.Wrap(policyB);

            wrap.Outer.Should().BeSameAs(policyA);
            wrap.Inner.Should().BeSameAs(policyB);
        }
예제 #5
0
        public PollyResilientWorker(int retries, TimeSpan?timeout)
        {
            m_Policy = Policy
                       .Handle <Exception>()
                       .Retry(retries, OnRetry);

            if (timeout.HasValue)
            {
                var timeoutPolicy = Policy.Timeout(timeout.Value,
                                                   TimeoutStrategy.Pessimistic, OnTimeout);

                m_Policy = m_Policy.Wrap(timeoutPolicy);
            }
        }
예제 #6
0
        /*
         *  超时分为乐观超时与悲观超时,乐观超时依赖于CancellationToken ,
         *  它假设我们的具体执行的任务都支持CancellationToken。那么在进行timeout的时候,
         *  它会通知执行线程取消并终止执行线程,避免额外的开销。
         */

        public static void Timeout_Fallback()
        {
            ISyncPolicy policy = Policy.Handle <Exception>()
                                 .Fallback(() =>
            {
                Console.WriteLine("方法执行出错");
            });

            // 悲观超时
            // 悲观超时与乐观超时的区别在于,如果执行的代码不支持取消CancellationToken,它还会继续执行,这会是一个比较大的开销
            policy = policy.Wrap(Policy.Timeout(2, TimeoutStrategy.Pessimistic));
            policy.Execute(() =>
            {
                DoSomething();
            });
        }
예제 #7
0
        private ISyncPolicy WrapSync(ISyncPolicy outerPolicy, ISyncPolicy innerPolicy)
        {
            if (innerPolicy != null && outerPolicy != null)
            {
                return(outerPolicy.Wrap(innerPolicy));
            }
            else if (innerPolicy != null)
            {
                return(innerPolicy);
            }
            else if (outerPolicy != null)
            {
                return(outerPolicy);
            }

            return(null);
        }
예제 #8
0
        public override Task Invoke(AspectContext context, AspectDelegate next)
        {
            ISyncPolicy policy = null;

            if (MaxRetryTimes > 0)
            {
                if (HandleTimeoutOnly)
                {
                    policy = Policy.Handle <TimeoutRejectedException>().Retry(MaxRetryTimes);
                }
                else
                {
                    policy = Policy.Handle <Exception>().Retry(MaxRetryTimes);
                }
            }
            if (TimeoutByMillisecond > 0)
            {
                var timeoutPolicy = Policy.Timeout(TimeSpan.FromMilliseconds(TimeoutByMillisecond), Polly.Timeout.TimeoutStrategy.Pessimistic);
                if (policy == null)
                {
                    policy = timeoutPolicy;
                }
                else
                {
                    policy = policy.Wrap(timeoutPolicy);
                }
            }
            if (policy == null)
            {
                return(context.Invoke(next));
            }
            else
            {
                return(policy.Execute(() => context.Invoke(next)));
            }
        }
예제 #9
0
 /// <summary>
 /// Converts a non-generic <see cref="ISyncPolicy"/> into a generic <see cref="ISyncPolicy{TResult}"/> for handling only executions returning <typeparamref name="TResult"/>.
 /// </summary>
 /// <remarks>This method allows you to convert a non-generic <see cref="ISyncPolicy"/> into a generic <see cref="ISyncPolicy{TResult}"/> for contexts such as variables or parameters which may explicitly require a generic <see cref="ISyncPolicy{TResult}"/>. </remarks>
 /// <param name="policy">The non-generic <see cref="ISyncPolicy"/>  to convert to a generic <see cref="ISyncPolicy{TResult}"/>.</param>
 /// <returns>A generic <see cref="ISyncPolicy{TResult}"/> version of the supplied non-generic <see cref="ISyncPolicy"/>.</returns>
 public static ISyncPolicy <TResult> AsPolicy <TResult>(this ISyncPolicy policy)
 => policy.Wrap(Policy.NoOp <TResult>());
예제 #10
0
        //Intercept方法是拦截的关键所在,也是IInterceptor接口中的唯一定义
        public void Intercept(IInvocation invocation)
        {
            var method = invocation.MethodInvocationTarget ?? invocation.Method;

            //对当前方法的特性验证

            //需要验证
            if (method.GetCustomAttributes(true).FirstOrDefault(x => x.GetType() == typeof(HystrixAttribute)) is HystrixAttribute qHystrixAttribute)
            {
                // Polly CircuitBreaker要求对于同一段代码要共享一个policy对象
                lock (this) // 线程安全考虑
                {
                    if (policy == null)
                    {
                        policy = Policy
                                 .Handle <ArgumentException>()
                                 .Fallback(async(ctx, t) =>
                        {
                            var type               = invocation.TargetType;
                            object obj             = System.Activator.CreateInstance(type);
                            var method             = type.GetMethod(qHystrixAttribute.FallBackMethod);
                            invocation.ReturnValue = await Task.Run(() => method.Invoke(obj, invocation.Arguments));
                            //return;

                            Console.WriteLine("我是降级后的数据");
                        }, async(ex, t) =>
                        {
                            Console.WriteLine("哈哈 我终于进来了");
                            invocation.ReturnValue = await Task.Run(() => "哈哈哈");
                            return;
                        });
                    }


                    // 设置 最大重试次数限制
                    if (qHystrixAttribute.MaxRetryTimes > 0)
                    {
                        policy = policy.Wrap(Policy.Handle <ArgumentException>()
                                             .WaitAndRetry(qHystrixAttribute.MaxRetryTimes,
                                                           i => TimeSpan.FromMilliseconds(qHystrixAttribute.RetryIntervalMilliseconds)));
                    }

                    // 启用熔断保护(CircuitBreaker)
                    if (qHystrixAttribute.IsEnableCircuitBreaker)
                    {
                        policy = policy.Wrap(Policy.Handle <ArgumentException>()
                                             .CircuitBreaker(qHystrixAttribute.ExceptionsAllowedBeforeBreaking,
                                                             TimeSpan.FromMilliseconds(qHystrixAttribute.MillisecondsOfBreak), (ex, ts) =>
                        {
                            // assuem to do logging
                            Console.WriteLine($"Service API OnBreak -- ts = {ts.Seconds}s, ex.message = {ex.Message}");
                        }, () =>
                        {
                            // assume to do logging
                            Console.WriteLine($"Service API OnReset");
                        }));
                    }

                    // 设置超时时间
                    if (qHystrixAttribute.TimeOutMilliseconds > 0)
                    {
                        policy = policy.Wrap(Policy.Timeout(() =>
                                                            TimeSpan.FromMilliseconds(qHystrixAttribute.TimeOutMilliseconds),
                                                            Polly.Timeout.TimeoutStrategy.Pessimistic));
                    }
                }


                // 设置缓存时间
                if (qHystrixAttribute.CacheTTLMilliseconds > 0)
                {
                    var cacheKey = CustomCacheKey(invocation);

                    if (_memoryCache.TryGetValue(cacheKey, out var cacheValue))
                    {
                        // 如果缓存中有,直接用缓存的值
                        invocation.ReturnValue = cacheValue;
                        return;
                    }
                    else
                    {
                        // 如果缓存中没有,则执行实际被拦截的方法
                        policy.Execute(() =>
                        {
                            throw new ArgumentException();
                            invocation.Proceed();
                        });

                        // 执行完被拦截方法后存入缓存中以便后面快速复用
                        using (var cacheEntry = _memoryCache.CreateEntry(cacheKey))
                        {
                            cacheEntry.Value = invocation.ReturnValue;
                            cacheEntry.AbsoluteExpiration = DateTime.Now
                                                            + TimeSpan.FromMilliseconds(qHystrixAttribute.CacheTTLMilliseconds); // 设置缓存过期时间
                        }
                    }
                }
                else
                {
                    // 如果没有启用缓存,则直接执行业务方法
                    policy.Execute(() =>
                    {
                        //测试熔断机制
                        //throw new ArgumentException();
                        try
                        {
                            throw new ArgumentException();
                            invocation.Proceed();
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("我出现错误了");
                        }
                    });
                }
            }
            else
            {
                // 将策略应用到 invocation.Proceed 方法上
                policy.Execute(() =>
                {
                    //测试熔断机制
                    throw new ArgumentException();
                    invocation.Proceed();
                });
            }
        }
        public override async Task Invoke(AspectContext context, AspectDelegate next)
        {
            ISyncPolicy policy = Policy.Handle <Exception>().RetryAsync();

            policy.Execute(() =>
            {
                var fallBackMethod    = context.ServiceMethod.DeclaringType.GetMethod(this.FallBackMethod);
                Object fallBackResult = fallBackMethod.Invoke(context.Implementation, context.Parameters);
                context.ReturnValue   = fallBackResult;
            });
            if (MaxRetryTimes > 0)
            {
                policy = policy.Wrap(Policy.Handle <Exception>().WaitAndRetry(MaxRetryTimes, i => TimeSpan.FromMilliseconds(RetryIntervalMilliseconds)));
            }
            if (EnableCircuitBreaker)
            {
                policy = policy.Wrap(Policy.Handle <Exception>().CircuitBreaker(ExceptionsAllowedBeforeBreaking, TimeSpan.FromMilliseconds(RetryIntervalMilliseconds)));
            }
            if (TimeOutMilliseconds > 0)
            {
                policy = policy.Wrap(Policy.Timeout(() => TimeSpan.FromMilliseconds(TimeOutMilliseconds), TimeoutStrategy.Pessimistic));
            }
            //Install-Package Microsoft.Extensions.Caching.Memory
            if (CacheTTLMilliseconds > 0)
            {
                //用类名+方法名+参数的下划线连接起来作为缓存key
                string cacheKey = "HystrixMethodCacheManager_Key_" + context.ServiceMethod.DeclaringType
                                  + "." + context.ServiceMethod + string.Join("_", context.Parameters);
                Object cacheValue;
                //尝试去缓存中获取
                if (memoryCache.TryGetValue(cacheKey, out cacheValue))
                {
                    context.ReturnValue = cacheValue;
                    await Task.FromResult(0);
                }
                else
                {
                    object returnValue = null;
                    policy.Execute(() =>
                    {
                        //执行实际的方法
                        // returnValue = context.Invoke(next);
                        returnValue = next(context);//执行被拦截的方法
                    });
                    using (var cacheEntry = memoryCache.CreateEntry(cacheKey))
                    {
                        cacheEntry.Value = context.ReturnValue;
                        cacheEntry.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMilliseconds(CacheTTLMilliseconds);
                    }
                    await Task.FromResult(returnValue);
                }
            }
            else//如果没有启用缓存,就直接执行业务方法
            {
                object returnValue = null;
                policy.Execute(() =>
                {
                    returnValue = context.Invoke(next);
                });
                await Task.FromResult(returnValue);
            }
        }
예제 #12
0
 /// <summary>
 /// Converts a non-generic <see cref="ISyncPolicy"/> into a generic <see cref="ISyncPolicy{TResult}"/> for handling only executions returning <typeparamref name="TResult"/>.
 /// </summary>
 /// <remarks>This method allows you to convert a non-generic <see cref="ISyncPolicy"/> into a generic <see cref="ISyncPolicy{TResult}"/> for contexts such as variables or parameters which may explicitly require a generic <see cref="ISyncPolicy{TResult}"/>. </remarks>
 /// <param name="policy">The non-generic <see cref="ISyncPolicy"/>  to convert to a generic <see cref="ISyncPolicy{TResult}"/>.</param>
 /// <returns>A generic <see cref="ISyncPolicy{TResult}"/> version of the supplied non-generic <see cref="ISyncPolicy"/>.</returns>
 public static ISyncPolicy <TResult> AsPolicy <TResult>(this ISyncPolicy policy)
 {
     return(policy.Wrap(Policy.NoOp <TResult>()));
 }
예제 #13
0
        static void Main(string[] args)
        {
            //{
            //    ISyncPolicy policy = Policy.Handle<Exception>().RetryForever();

            //    policy.Execute(() =>
            //    {
            //        Console.WriteLine("开始任务!");

            //        if (new Random().Next(10) < 9)
            //        {
            //            throw new ApplicationException("触发异常,重试直到成功!");
            //        }

            //        Console.WriteLine("结束任务!");
            //    });
            //}

            //{

            //    ISyncPolicy policy = Policy.Handle<Exception>().Retry(3);

            //    try
            //    {
            //        policy.Execute(() =>
            //        {
            //            Console.WriteLine("开始任务!");

            //            if (new Random().Next(10) < 9)
            //            {
            //                throw new ApplicationException("触发异常,只试3次!");
            //            }

            //            Console.WriteLine("结束任务!");
            //        });
            //    }
            //    catch (Exception e)
            //    {
            //        Console.WriteLine(e);
            //    }
            //}


            //{

            //    ISyncPolicy policy = Policy.Handle<Exception>().WaitAndRetry(new TimeSpan[]{TimeSpan.FromMilliseconds(100) ,TimeSpan.FromMilliseconds(200)});

            //    try
            //    {
            //        policy.Execute(() =>
            //        {
            //            Console.WriteLine("开始任务!");

            //            if (new Random().Next(10) < 9)
            //            {
            //                throw new ApplicationException("触发异常,只试3次!");
            //            }

            //            Console.WriteLine("结束任务!");
            //        });
            //    }
            //    catch (Exception e)
            //    {
            //        Console.WriteLine(e);
            //    }
            //}

            //{
            //    //连续出错6次后熔断5秒,(不会尝试去执行业务代码)
            //    ISyncPolicy policy = Policy.Handle<Exception>().CircuitBreaker(6,TimeSpan.FromSeconds(5));

            //    while (true)
            //    {
            //        Console.WriteLine("开始Execute");
            //        try
            //        {
            //            policy.Execute(() =>
            //            {
            //                Console.WriteLine("开始任务!");
            //                throw new ApplicationException("触发异常");
            //                Console.WriteLine("结束任务!");
            //            });
            //        }
            //        catch (Exception e)
            //        {
            //            Console.WriteLine("Execute执行出错:"+e.Message);
            //        }
            //        Thread.Sleep(500);
            //    }
            //}


            {
                //出现异常,或者超时
                ISyncPolicy policy = Policy.Handle <Exception>().Fallback(() =>
                {
                    Console.WriteLine("执行出错");
                });
                //悲观会抛异常,乐观不会抛异常
                policy = policy.Wrap(Policy.Timeout(2, TimeoutStrategy.Pessimistic));//悲观/乐观

                policy.Execute(() =>
                {
                    Console.WriteLine("开始任务!");
                    Thread.Sleep(5000);
                    Console.WriteLine("结束任务!");
                });
            }

            Console.WriteLine("Hello World!");
        }