zoukankan      html  css  js  c++  java
  • .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

  • 相关阅读:
    关于网络字节序(network byte order)和主机字节序(host byte order)
    关于垃圾回收,我来解释下为什么LocalConnection可以实现垃圾回收
    解决Form中ExternalInterface的Bug问题
    AS3里var aa:String是null还是""?
    IE并发连接限制(as)
    tar
    mysql默认端口号3306
    flex经验
    这个游戏不错
    nginx介绍
  • 原文地址:https://www.cnblogs.com/redo/p/12575592.html
Copyright © 2011-2022 走看看