BililiveRecorder/BililiveRecorder.Core/PollyPolicy.cs

83 lines
3.5 KiB
C#
Raw Normal View History

using System;
using System.Net.Http;
using BililiveRecorder.Core.Api;
using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json;
using Polly;
using Polly.Caching.Memory;
using Polly.CircuitBreaker;
using Polly.Registry;
using Serilog;
namespace BililiveRecorder.Core
{
public class PollyPolicy : PolicyRegistry
{
private static readonly ILogger logger = Log.ForContext<PollyPolicy>();
public PollyPolicy()
{
this.IpBlockedHttp412CircuitBreakerPolicy = Policy
.Handle<Http412Exception>()
.CircuitBreakerAsync(
exceptionsAllowedBeforeBreaking: 1,
2021-04-21 23:18:23 +08:00
durationOfBreak: TimeSpan.FromMinutes(2),
onBreak: (_, _) =>
{
2021-05-01 17:57:43 +08:00
logger.Warning("检测到被屏蔽(HTTP 412),暂停发送请求");
},
onReset: () =>
{
logger.Information("屏蔽解除,恢复发送请求");
},
onHalfOpen: () =>
{
logger.Debug(nameof(this.IpBlockedHttp412CircuitBreakerPolicy) + " onHalfOpen");
});
this.RequestFailedCircuitBreakerPolicy = Policy
.Handle<HttpRequestException>()
.Or<JsonException>()
.Or<BilibiliApiResponseCodeNotZeroException>(x =>
{
return x.Code is not 19002005 // 19002005: 房间已加密
and not 19002000 // 19002000: 房间不存在(获取初始化数据失败)
;
})
.AdvancedCircuitBreakerAsync(
failureThreshold: 0.8,
samplingDuration: TimeSpan.FromSeconds(30),
minimumThroughput: 6,
durationOfBreak: TimeSpan.FromMinutes(1),
onBreak: (_, _) =>
{
logger.Warning("大部分请求出错,暂停发送请求");
},
onReset: () =>
{
logger.Information("恢复正常发送请求");
},
onHalfOpen: () =>
{
logger.Debug(nameof(this.RequestFailedCircuitBreakerPolicy) + " onHalfOpen");
});
var retry = Policy.Handle<Exception>().RetryAsync();
2021-04-21 23:18:23 +08:00
var bulkhead = Policy.BulkheadAsync(maxParallelization: 5, maxQueuingActions: 200);
this.memoryCache = new MemoryCache(new MemoryCacheOptions());
var memoryCacheProvider = new MemoryCacheProvider(this.memoryCache);
var cachePolicy = Policy.CacheAsync(memoryCacheProvider, TimeSpan.FromMinutes(2));
this[PolicyNames.PolicyRoomInfoApiRequestAsync] = Policy.WrapAsync(bulkhead, retry, this.IpBlockedHttp412CircuitBreakerPolicy, this.RequestFailedCircuitBreakerPolicy);
this[PolicyNames.PolicyDanmakuApiRequestAsync] = Policy.WrapAsync(cachePolicy, bulkhead, retry, this.IpBlockedHttp412CircuitBreakerPolicy, this.RequestFailedCircuitBreakerPolicy);
this[PolicyNames.PolicyStreamApiRequestAsync] = Policy.WrapAsync(bulkhead, retry, this.IpBlockedHttp412CircuitBreakerPolicy, this.RequestFailedCircuitBreakerPolicy);
}
public readonly MemoryCache memoryCache;
public readonly AsyncCircuitBreakerPolicy IpBlockedHttp412CircuitBreakerPolicy;
public readonly AsyncCircuitBreakerPolicy RequestFailedCircuitBreakerPolicy;
}
}