.net core 3.1 基於AspectCore+Polly 實現熔斷降級


這次學習主要參考了Edison zhou 的這篇文章:https://www.cnblogs.com/edisonchou/p/9159644.html,相關的概念也做了解釋,有興趣的可以了解一下 

本次實現需要引用以下包,版本也有要求(包括Autofac),稍后會進行解釋。 我先把實現邏輯講完,再分享其中遇到的坑

 

如果對AspectCore不太了解的,可以下載查看AspectCoreDemo ,了解AspectCore攔截器設置。

使用AspectCore前,把原來的Castle相關引用刪除,避免沖突,同時前文提到的 LogInterceptor , MyInterceptor 先注釋相關代碼,后續會使用 AspectCore 實現基於方法的攔截

 

首先新建自定義攔截類CustomInterceptorAttribute ,這里要using AspectCore.DynamicProxy;

/// <summary>
/// 自定義攔截器
/// </summary>
public class CustomInterceptorAttribute : AbstractInterceptorAttribute
{
/// <summary>
/// 每個被攔截的方法中執行
/// </summary>
/// <param name="context"></param>
/// <param name="next"></param>
/// <returns></returns>
public override async Task Invoke(AspectContext context, AspectDelegate next)
{
try
{
Console.WriteLine("Before service call");
await next(context); // 執行被攔截的方法
}
catch (Exception)
{
Console.WriteLine("Service threw an exception");
throw;
}
finally
{
Console.WriteLine("After service call");
}
}
}

 

依賴注入是借助Autofac ,在Program.cs 增加如下代碼 .UseServiceProviderFactory(new AutofacServiceProviderFactory())

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory()) //autofac 依賴注入
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});

 

在Startup.cs 的ConfigureContainer 方法最后加入一行代碼 添加引用 AspectCore.Extensions.Autofac

builder.RegisterDynamicProxy();

 

AspectCore 配置完成了,接下來是 Polly+AspectCore 結合使用

這里引用楊中科老師封裝的 RuPeng.HystrixCore ,里面定義好了相關Polly配置和執行邏輯,后續只要添加相關屬性值就可以實現動態配置。

同步引用 AspectCore.Core, Microsoft.Extensions.Caching.Memory(對熔斷后操作數據做緩存)

接下來是調用方法。

新建IProductService.cs

在相關的接口添加Polly屬性配置,具體的屬性含義可以查看 RuPeng.HystrixCore 源代碼,GetAllProductsFallBackAsync 是Fallback接口

public interface IProductService
{
[HystrixCommand(nameof(GetAllProductsFallBackAsync),
EnableCircuitBreaker = true, CacheTTLMilliseconds =1000*6,
ExceptionsAllowedBeforeBreaking = 2,
MillisecondsOfBreak = 1000 * 6)]
string GetAllProductsAsync(string productType);

string GetAllProductsFallBackAsync(string productType);
}

ProductService.cs

public class ProductService : IProductService
{
public string GetAllProductsAsync(string productType)
{
NLogHelper.logger.Info("test for GetAllProductsAsync:" + productType);
string str = null;
str.ToString();

// to do : using HttpClient to call outer service to get product list
return $"OK {productType}";
}

public string GetAllProductsFallBackAsync(string productType)
{
NLogHelper.logger.Info("test for GetAllProductsFallBackAsync:"+productType);
return $"OK for FallBack {productType}";
}
}

新建ProductController.cs

[Route("api/[controller]/[action]")]
[ApiController]
public class ProductController : ControllerBase
{
private readonly IProductService _baseService;
public ProductController(IProductService baseService)
{
_baseService = baseService;
}

[HttpGet]
public async Task<string> Get(string productType="A")
{
var product = _baseService.GetAllProductsAsync(productType);
return product;
}
}

注意,Get方法用異步線程

 

最后調試:

調試完,接着說說版本號的問題以及遇到的坑

最初引用 AspectCore.Extensions.Autofac 注入匿名代理時,無法編譯通過,提示Method not found: 'Autofac.Builder.DeferredCallback Autofac.ContainerBuilder.RegisterCallback(System.Action`1<Autofac.Core.IComponentRegistry>)'.

后來 在AspectCore-Framwork 項目提交issues ,解釋說已處理但沒發布,暫時可以先降級Autofac到4.9 版本,於是把相關的引用降級,編譯通過

在引用 RuPeng.HystrixCore 調試時有個bug,fallback接口沒有把參數傳過來,導致每次傳不同參數調用接口都是返回之前的參數值,后來下載源碼修改

Object fallBackResult = fallBackMethod.Invoke(context.Implementation, context.Parameters); 

改為

Object fallBackResult = fallBackMethod.Invoke(context.Implementation, aspectContext.Parameters); 

編譯后替換,問題解決

此外RuPeng.HystrixCore 不兼容Polly 7 ,所以要把Polly 版本降為6.0.1


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM