/// <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("完成任务"); // }); }
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"); }
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"); }
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); }
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); } }
/* * 超时分为乐观超时与悲观超时,乐观超时依赖于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(); }); }
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); }
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))); } }
/// <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>());
//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); } }
/// <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>())); }
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!"); }