/// <summary> /// 超时 /// </summary> /// <param name="wrappolicy"></param> /// <returns></returns> private AsyncPolicy SetTimeout(AsyncPolicy wrappolicy) { //超时异常,采用Pessimistic悲观策略 if (TimeOutMilliseconds > 0 && wrappolicy != null) { wrappolicy = wrappolicy.WrapAsync(Policy.TimeoutAsync(() => TimeSpan.FromMilliseconds(TimeOutMilliseconds), Polly.Timeout.TimeoutStrategy.Pessimistic)); } return(wrappolicy); }
private AsyncPolicy BuildPolicy(AspectContext context, AsyncPolicy policy) { if (policy != null) { return(policy); } policy = Policy.NoOpAsync(); if (IsEnableCircuitBreaker) { policy = policy.WrapAsync(Policy.Handle <Exception>().CircuitBreakerAsync( ExceptionsAllowedBeforeBreaking, TimeSpan.FromMilliseconds(MillisecondsOfBreak))); } if (TimeOutMilliseconds > 0) { policy = policy.WrapAsync(Policy.TimeoutAsync(() => TimeSpan.FromMilliseconds(TimeOutMilliseconds), Polly.Timeout.TimeoutStrategy.Pessimistic)); } if (MaxRetryTimes > 0) { policy = policy.WrapAsync(Policy.Handle <Exception>().WaitAndRetryAsync(MaxRetryTimes, i => TimeSpan.FromMilliseconds(RetryIntervalMilliseconds))); } var policyFallBack = Policy .Handle <Exception>() .FallbackAsync((ctx, t) => { var aspectContext = (AspectContext)ctx["aspectContext"]; var fallBackMethod = context.ServiceMethod?.DeclaringType?.GetMethod(FallBackMethod); var fallBackResult = fallBackMethod?.Invoke(context.Implementation, context.Parameters); aspectContext.ReturnValue = fallBackResult; return(Task.FromResult(fallBackResult)); }, async(ex, t) => throw ex); policy = policyFallBack.WrapAsync(policy); policies.TryAdd(context.ServiceMethod, policy); return(policy); }
public void Generic_wraps_generic_using_instance_wrap_syntax_should_set_outer_inner() { AsyncPolicy <int> policyA = Policy.NoOpAsync <int>(); AsyncPolicy <int> policyB = Policy.NoOpAsync <int>(); AsyncPolicyWrap <int> wrap = policyA.WrapAsync(policyB); wrap.Outer.Should().BeSameAs(policyA); wrap.Inner.Should().BeSameAs(policyB); }
public AsyncPolicy <HttpResponseMessage> Build() { if (!this.policies.Any()) { return(null); } AsyncPolicy <HttpResponseMessage> policy = this.policies[0]; for (int i = 1; i < this.policies.Count; i++) { policy = policy.WrapAsync(this.policies[i]); } return(policy); }
/// <summary> /// 熔断 /// </summary> /// <param name="wrappolicy"></param> /// <returns></returns> private AsyncPolicy SetCircuitBreaker(AsyncPolicy wrappolicy) { if (IsEnableCircuitBreaker == E_Hystrix.Enable) { //异常ExceptionsAllowedBeforeBreaking次后进行熔断,熔断MillisecondsOfBreak后恢复 var _wrappolicy = Policy.Handle <Exception>().CircuitBreakerAsync(ExceptionsAllowedBeforeBreaking, TimeSpan.FromMilliseconds(MillisecondsOfBreak)); if (wrappolicy == null) { wrappolicy = _wrappolicy; } else { wrappolicy = wrappolicy.WrapAsync(_wrappolicy); } } return(wrappolicy); }
/// <summary> /// 重试 /// </summary> /// <param name="wrappolicy"></param> /// <returns></returns> private AsyncPolicy SetRetry(AsyncPolicy wrappolicy) { if (MaxRetryTimes > 0) { //重试策略,RetryIntervalMilliseconds标识间隔多久重试一次 var _wrappolicy = Policy.Handle <Exception>().WaitAndRetryAsync(MaxRetryTimes, i => TimeSpan.FromMilliseconds(RetryIntervalMilliseconds)); if (wrappolicy == null) { wrappolicy = _wrappolicy; } else { wrappolicy = wrappolicy.WrapAsync(_wrappolicy); } } return(wrappolicy); }
/// <summary> /// Initializes a new instance. /// </summary> /// <param name="onBreak">The on break.</param> /// <param name="onReset">The on reset.</param> /// <param name="onHalfOpen">The on half open.</param> /// <param name="onRetry">The on retry.</param> public ResiliencePolicies( Action <Exception, CircuitState, TimeSpan, Context>?onBreak = null, Action <Context>?onReset = null, Action?onHalfOpen = null, Func <Exception, TimeSpan, int, Context, Task>?onRetry = null ) { var onBreak_ = (onBreak ?? ((ex, state, duration, ctx) => { })); var onReset_ = onReset ?? ((Action <Context>)((ctx) => { })); var onHalfOpen_ = onHalfOpen ?? (() => { }); var onRetry_ = onRetry ?? ((ex, duration, retryCount, ctx) => Task.CompletedTask); //_onBreak = onBreak_; //_onReset = onReset_; //_onHalfOpen = onHalfOpen_; //_onRetry = onRetry_; //BatchReading = DefaultReadingPolicy; AsyncPolicy retryReading = Policy.Handle <Exception>() .RetryForeverAsync((ex, i, c) => onRetry_(ex, TimeSpan.Zero, i, c)); AsyncPolicy breaker = Policy.Handle <Exception>() //.CircuitBreakerAsync( // 10, // TimeSpan.FromSeconds(20), // onBreak_, // onReset_, // onHalfOpen_); .AdvancedCircuitBreakerAsync( failureThreshold: 0.5, // Break on >=50% actions result in handled exceptions... samplingDuration: TimeSpan.FromSeconds(20), // ... over any 10 second period minimumThroughput: 8, // ... provided at least 8 actions in the 10 second period. durationOfBreak: TimeSpan.FromSeconds(30), // Break for 30 seconds. onBreak_, onReset_, onHalfOpen_); BatchReading = retryReading.WrapAsync(breaker); }
private async Task <HttpResponseMessage> ExecuteWithRetryAndCircuitBreakerAsync(string uri, string authToken, Func <Task <HttpResponseMessage> > func) { var res = await _retryPolicy.WrapAsync(_circuitBreakerPolicy).ExecuteAsync(func); return(res); }
private AsyncPolicy <object> GetPolicy(string route, Type returnValueType) { return(Policies.GetOrAdd(route, (key) => { var service = ServiceFactory.Get(route); var serviceCircuitBreakerOptions = service.ServiceCircuitBreakerOptions; var circuitBreakerEvent = ServiceProvider.GetService <ICircuitBreakerEvent>(); AsyncPolicy <object> policy = Policy <object> .Handle <Exception>().FallbackAsync( async ct => { if (circuitBreakerEvent != null) { await circuitBreakerEvent.OnFallback(route, service.MethodInfo); } if (returnValueType == null) { return null; } if (service.ServiceCircuitBreakerOptions.HasInjection) { return await ScriptInjection.Run(route); } return returnValueType.IsValueType ? Activator.CreateInstance(returnValueType) : null; }); if (serviceCircuitBreakerOptions.ExceptionsAllowedBeforeBreaking > 0) { policy = policy.WrapAsync(Policy.Handle <Exception>().CircuitBreakerAsync(serviceCircuitBreakerOptions.ExceptionsAllowedBeforeBreaking, serviceCircuitBreakerOptions.DurationOfBreak, async(ex, state, ts, ctx) => { if (circuitBreakerEvent != null) { await circuitBreakerEvent.OnBreak(route, service.MethodInfo, ex, ts); } }, async ctx => { if (circuitBreakerEvent != null) { await circuitBreakerEvent.OnRest(route, service.MethodInfo); } }, async() => { if (circuitBreakerEvent != null) { await circuitBreakerEvent.OnHalfOpen(route, service.MethodInfo); } })); } if (serviceCircuitBreakerOptions.Retry > 0) { policy = policy.WrapAsync(Policy.Handle <Exception>().RetryAsync(serviceCircuitBreakerOptions.Retry, async(ex, times) => { if (circuitBreakerEvent != null) { await circuitBreakerEvent.OnRetry(route, service.MethodInfo, ex, times); } })); } if (serviceCircuitBreakerOptions.Timeout.Ticks > 0) { policy = policy.WrapAsync(Policy.TimeoutAsync(serviceCircuitBreakerOptions.Timeout, TimeoutStrategy.Pessimistic, async(ctx, ts, task, ex) => { if (circuitBreakerEvent != null) { await circuitBreakerEvent.OnTimeOut(route, service.MethodInfo, ex); } })); } return policy; })); }
public override async Task Invoke(AspectContext context, AspectDelegate next) { //一个HystrixCommand中保持一个policy对象即可 //其实主要是CircuitBreaker要求对于同一段代码要共享一个policy对象 //根据反射原理,同一个方法的MethodInfo是同一个对象,但是对象上取出来的HystrixCommandAttribute //每次获取的都是不同的对象,因此以MethodInfo为Key保存到policies中,确保一个方法对应一个policy实例 policies.TryGetValue(context.ServiceMethod, out AsyncPolicy policy); lock (policies) //因为Invoke可能是并发调用,因此要确保policies赋值的线程安全 { if (policy == null) { policy = Policy.NoOpAsync(); //创建一个空的Policy if (IsEnableCircuitBreaker) { policy = policy.WrapAsync(Policy.Handle <Exception>().CircuitBreakerAsync(ExceptionsAllowedBeforeBreaking, TimeSpan.FromMilliseconds(MillisecondsOfBreak))); } if (TimeOutMilliseconds > 0) { policy = policy.WrapAsync(Policy.TimeoutAsync(() => TimeSpan.FromMilliseconds(TimeOutMilliseconds), TimeoutStrategy.Pessimistic)); } if (MaxRetryTimes > 0) { policy = policy.WrapAsync(Policy.Handle <Exception>().WaitAndRetryAsync(MaxRetryTimes, i => TimeSpan.FromMilliseconds(RetryIntervalMilliseconds))); } AsyncPolicy policyFallBack = Policy .Handle <Exception>() .FallbackAsync(async(ctx, t) => { AspectContext aspectContext = (AspectContext)ctx["aspectContext"]; var fallBackMethod = context.ServiceMethod.DeclaringType.GetMethod(this.FallBackMethod); Object fallBackResult = fallBackMethod.Invoke(context.Implementation, context.Parameters); //不能如下这样,因为这是闭包相关,如果这样写第二次调用Invoke的时候context指向的 //还是第一次的对象,所以要通过Polly的上下文来传递AspectContext //context.ReturnValue = fallBackResult; aspectContext.ReturnValue = fallBackResult; }, async(ex, t) => { //t.Add("error", ex.Message); }); policy = policyFallBack.WrapAsync(policy); //放入 policies.TryAdd(context.ServiceMethod, policy); } } //把本地调用的AspectContext传递给Polly,主要给FallbackAsync中使用,避免闭包的坑 Context pollyCtx = new Context(); pollyCtx["aspectContext"] = context; //Install-Package Microsoft.Extensions.Caching.Memory if (CacheTTLMilliseconds > 0) { //用类名+方法名+参数的下划线连接起来作为缓存key string cacheKey = "HystrixMethodCacheManager_Key_" + context.ServiceMethod.DeclaringType + "." + context.ServiceMethod + string.Join("_", context.Parameters); //尝试去缓存中获取。如果找到了,则直接用缓存中的值做返回值 if (memoryCache.TryGetValue(cacheKey, out var cacheValue)) { context.ReturnValue = cacheValue; } else { //如果缓存中没有,则执行实际被拦截的方法 await policy.ExecuteAsync(ctx => next(context), pollyCtx); //存入缓存中 using (var cacheEntry = memoryCache.CreateEntry(cacheKey)) { cacheEntry.Value = context.ReturnValue; cacheEntry.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMilliseconds(CacheTTLMilliseconds); } } } else //如果没有启用缓存,就直接执行业务方法 { await policy.ExecuteAsync(ctx => next(context), pollyCtx); } }