Polly+AspectCore实现熔断与降级机制

Polly+AspectCore实现熔断与降级机制

https://www.cnblogs.com/edisonchou/p/9159644.html

一、熔断、降级与AOP
1.1 啥是熔断?

  在广义的解释中,熔断主要是指为控制股票、期货或其他金融衍生产品的交易风险,为其单日价格波动幅度规定区间限制,一旦成交价触及区间上下限,交易则自动中断一段时间(“熔即断”),或就此“躺平”而不得超过上限或下限(“熔而不断”)。

  而对于微服务来说,熔断就是我们常说的“保险丝”,意为当服务出现某些状况时,切断服务,从而防止应用程序不断地常识执行可能会失败的操作造成系统的“雪崩”,或者大量的超时等待导致系统卡死等情况,很多地方也将其成为“过载保护”。

1.2 啥是降级?

  降级的目的就是当某个服务提供者发生故障的时候,向调用方返回一个替代响应或者错误响应。

  例如:假设有一个短信服务,其调用联通接口服务器发送短信服务(假设这里调用联通接口最方便,最省事也最经济)失败之后,会尝试改用移动短信服务器(假设这里调用移动服务器比较不方便也不经济)发送,如果移动服务器调用也失败,那么还会尝试改用电信短信服务器(假设这里调用电信服务器最不省事和最不经济),如果还失败,则返回“失败”响应;

  降级的另一个概念也可以看作是服务的“选择性放弃”,比如在双11或618等大型的电商活动日中,在高峰值的情形下,一般的电商系统都会采用部分服务的优先级降低或者干脆延时或停止服务,以确保主要的服务能够使用最大化的资源为客户提供服务。等待峰值下降之后,再通过处理恢复那些降级的服务的原有优先级。

1.3 啥是AOP?
  AOP(Aspect Oriented Programming)意为面向切面编程,它是指在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。比如说,我们在两个类中,可能都需要在每个方法中做日志。按面向对象的设计方法,我们就必须在两个类的方法中都加入日志的内容。也许他们是完全相同的,但就是因为面向对象的设计让类与类之间无法联系,而不能将这些重复的代码统一起来。而AOP就是为了解决这个问题而生的,一般而言,我们把切入到指定类指定方法的代码片段称为切面,而切入到哪些类、哪些方法则叫切入点。有了AOP,我们就可以把几个类共有的代码,抽取到一个切片中,等到需要时再切入对象中去,从而改变其原有的行为。

  AOP是OOP(Object Oriented Programming)的补充,OOP从横向上区分出一个个的类来,而AOP则从纵向上向对象中加入特定的代码。有了AOP,OOP变得立体了。关于AOP的更多细节和讨论,可以浏览知乎的这篇帖子:《什么是AOP?》

二、Polly的基本使用
2.1 Polly极简介绍

  Polly是一个被.NET基金会认可的弹性和瞬态故障处理库,允许我们以非常顺畅和线程安全的方式来执诸如行重试,断路,超时,故障恢复等策略,其主要功能如下:

功能1:重试(Retry)
功能2:断路器(Circuit-Breaker)
功能3:超时检测(Timeout)
功能4:缓存(Cache)
功能5:降级(Fallback)
  Polly的策略主要由“故障”和“动作”两个部分组成,“故障”可以包括异常、超时等情况,“动作”则包括Fallback(降级)、重试(Retry)、熔断(Circuit-Breaker)等。策略则用来执行业务代码,当业务代码出现了“故障”中的情况时就开始执行“动作”。

2.2 Polly基础使用
  *.这里只介绍几个我们需要用到的功能,其他功能请浏览参考资料关于Polly的部分。

  (1)通过NuGet安装,最新版本:6.0.1

NuGet>Install-Package Polly  

  (2)FallBack => 当出现故障,则进入降级动作

复制代码
public static void Case1()
{
ISyncPolicy policy = Policy.Handle()
.Fallback(() =>
{
Console.WriteLine("Error occured");
});

    policy.Execute(() =>
    {
        Console.WriteLine("Job Start");

        throw new ArgumentException("Hello Polly!");

        Console.WriteLine("Job End");
    });
}

复制代码
  执行结果如下图所示:这里捕捉的是ArgumentException, 如果想捕捉所有的Exception,请设置Policy.Handle,不过这样就扩大了范围。

  

  (3)Retry => 重试,比较容易理解

复制代码
public static void Case2()
{
ISyncPolicy policy = Policy.Handle().Retry(3);

    try
    {
        policy.Execute(() =>
        {
            Console.WriteLine("Job Start");
            if (DateTime.Now.Second % 10 != 0)
            {
                throw new Exception("Special error occured");
            }
            Console.WriteLine("Job End");
        });
    }
    catch (Exception ex)
    {
        Console.WriteLine("There's one unhandled exception : " + ex.Message);
    }
}

复制代码
  执行结果如下图所示:可以看到,这里重试了三次,仍然没有满足条件(DateTime.Now.Second % 10 == 0),因此进入了外部的未处理异常catch块中。

  

  (4)CircuitBreaker => 短路保护,当一块业务代码/服务 出现了N次错误,则把“熔断器”(保险丝)熔断,等待一段时间后才允许再次执行,在这段等待的时间内如果再执行则直接抛出BrokenCircuitException异常。这个也很好理解,比如我们的手机屏幕密码,如果输错了N次之后,手机会拒绝我们再次输入,而是让我们等待20 ~ 30s 之后再输入,如果等待之后再输错N次,则再次进入等待。

  这里假设我们设置一个短路保护策略:当发生了故障的时候,则重试了5次还是有故障(代码中的6代表的是在执行短路保护策略之前允许6次故障),那么久停止服务10s钟,10s之后再允许重试。

复制代码
public static void Case3()
{
// Stop for 10s after retry 6 times
ISyncPolicy policy = Policy.Handle()
.CircuitBreaker(6, TimeSpan.FromSeconds(10));

    while (true)
    {
        try
        {
            policy.Execute(() =>
            {
                Console.WriteLine("Job Start");
                throw new Exception("Special error occured");
                Console.WriteLine("Job End");
            });
        }
        catch (Exception ex)
        {
            Console.WriteLine("There's one unhandled exception : " + ex.Message);
        }

        Thread.Sleep(500);
    }
}

复制代码
  执行结果如下图所示:出现了6次故障之后,直接给我们跑出了短路保护的异常,“The circuit is now open and is not allowing calls”.

  

  (5)Timeout 与 Wrap => Wrap是指策略封装,可以把多个ISyncPolicy合并到一起执行。Timeout则是指超时处理,但是超时策略一般不能直接使用,而是其其他策略封装到一起使用。

  这里我们封装两个策略,一个是基本的Fallback,另一个则是超时策略,如果调用执行时间超过2s则触发Fallback。

  这里涉及到Polly中关于超时的两个策略:一个是悲观策略(Pessimistic),一个是乐观策略(Optimistic)。其中,悲观策略超时后会直接抛异常,而乐观策略则不会,而只是触发CancellationTokenSource.Cancel函数,需要等待委托自行终止操作。一般情况下,我们都会用悲观策略。

复制代码
public static void Case4()
{
try
{
ISyncPolicy policyException = Policy.Handle()
.Fallback(() =>
{
Console.WriteLine("Fallback");
});
ISyncPolicy policyTimeout = Policy.Timeout(3, Polly.Timeout.TimeoutStrategy.Pessimistic);
ISyncPolicy mainPolicy = Policy.Wrap(policyTimeout, policyException);
mainPolicy.Execute(() =>
{
Console.WriteLine("Job Start...");
Thread.Sleep(5000);
//throw new Exception();
Console.WriteLine("Job End...");
});
}
catch (Exception ex)
{
Console.WriteLine($"Unhandled exception : {ex.GetType()} : {ex.Message}");
}
}
复制代码
  执行结果如下图所示:

  

  除此之外,Polly还提供了一些异步方法供调用以实现以上介绍的功能,比如在业务代码中有一些Http的调用或者IO操作时,不妨用用异步操作来提高一点效率,可以看下面这个例子:

复制代码
public static async void Case5()
{
Policy policy = Policy.Handle()
.FallbackAsync(async c =>
{
Console.WriteLine("Executed Error!");
return new byte[0];
}, async r =>
{
Console.WriteLine(r.Exception);
});

    policy = policy.WrapAsync(Policy.TimeoutAsync(20, TimeoutStrategy.Pessimistic,
        async (context, timespan, task) =>
        {
            Console.WriteLine("Timeout!");
        }));

    var bytes = await policy.ExecuteAsync(async ()=>
    {
        Console.WriteLine("Start Job");
        HttpClient httpClient = new HttpClient();
        var result = await httpClient.GetByteArrayAsync("https://images2018.cnblogs.com/blog/381412/201806/381412-20180606230929894-145212290.png");
        Console.WriteLine("Finish Job");

        return result;
    });

    Console.WriteLine($"Length of bytes : {bytes.Length}");
}

复制代码
  执行结果如下图所示:

  

  至于Polly更多的功能和用法,可以参阅官方文档,这里不再赘述。

三、AspectCore的基本使用
3.1 为什么要用AOP框架
  从上面的例子可以看出,如果直接使用Polly,那么就会造成我们的业务代码中混杂大量的业务无关的代码。所以,我们会使用AOP的方式来封装Polly,嗯,首先我们先找一个支持的.NET Core的AOP框架吧,目前大家都在用AspectCore(国产,作者Lemon),它采用动态动态代理/织入,并且支持异步方法的拦截。

  快快通过NuGet安装一个吧:

NuGet>Install-Package AspectCore.Core  

3.2 AspectCore的极简使用
  这里假设我们要针对一个类的某些类的某些方法进行拦截,我们一般会经过一下几个步骤:

  (1)编写一个拦截器,一般继承自AbstractInterceptorAttribute

复制代码
///

/// 自定义拦截器
///

public class CustomInterceptorAttribute : AbstractInterceptorAttribute
{
///

/// 每个被拦截的方法中执行
///

///
///
///
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");
}
}
}
复制代码
  这里我们通过为被拦截方法增加一些处理前和处理后的logic来实现AOP。

  (2)编写需要被代理拦截的类

复制代码
///

/// 实现AoP的两个要求:
/// 1.public 类
/// 2.virtual 方法
///

public class Person
{
[CustomInterceptor]
public virtual void Say(string message)
{
Console.WriteLine($"Service calling ... => {message}");
}
}
复制代码
  可以看到我们在要拦截的方法Say()的声明之上加了一个Attribute:CustomInterceptor,正是我们之前新增的。

  (3)通过AspectCore创建代理对象实现AOP

复制代码
public class Program
{
public static void Main(string[] args)
{
ProxyGeneratorBuilder proxyGeneratorBuilder = new ProxyGeneratorBuilder();
using (IProxyGenerator proxyGenerator = proxyGeneratorBuilder.Build())
{
Person p = proxyGenerator.CreateClassProxy();
p.Say("edisonchou.cnblogs.com");
}
Console.ReadKey();
}
}
复制代码
  执行结果如下图所示:

  

  代码很清晰,不再解释。直到这里,我们看到了不管是Polly的使用,还是AspectCore的使用,都存在一些业务无关的声明代码,而且我们需要结合Polly和AspectCore才能完整地实现适合ASP.NET Core的熔断降级组件,下面我们就来模仿Spring Cloud中的Hystrix(可以参考这一篇文章来了解Spring Cloud Hystrix是个啥玩意儿)

四、Polly+AspectCore的结合使用
4.1 封装一个Hystrix
NuGet>Install-Package Polly

NuGet>Install-Package AspectCore.Core

NuGet>Install-Package Microsoft.Extensions.Caching.Memory  

复制代码
[AttributeUsage(AttributeTargets.Method)]
public class HystrixCommandAttribute : AbstractInterceptorAttribute
{
///

/// 最多重试几次:如果为0,则不重试
///

public int MaxRetryTimes { get; set; }

    /// <summary>
    /// 重试间隔(单位:毫秒):默认100ms
    /// </summary>
    public int RetryIntervalMilliseconds { get; set; } = 100;

    /// <summary>
    /// 是否启用熔断
    /// </summary>
    public bool IsEnableCircuitBreaker { get; set; } = false;

    /// <summary>
    /// 熔断前出现允许错误几次
    /// </summary>
    public int ExceptionsAllowedBeforeBreaking { get; set; } = 3;

    /// <summary>
    /// 熔断时间(单位:毫秒):默认1000ms
    /// </summary>
    public int MillisecondsOfBreak { get; set; } = 1000;

    /// <summary>
    /// 执行超过多少毫秒则认为超时(0表示不检测超时)
    /// </summary>
    public int TimeOutMilliseconds { get; set; } = 0;

    /// <summary>
    /// 缓存时间(存活期,单位:毫秒):默认为0,表示不缓存
    /// Key:类名+方法名+所有参数ToString
    /// </summary>
    public int CacheTTLMilliseconds { get; set; } = 0;

    private Policy policy;
    private static readonly IMemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions());

    /// <summary>
    /// 降级的方法名称
    /// </summary>
    public string FallBackMethod { get; set; }

    public HystrixCommandAttribute(string fallBackMethod)
    {
        FallBackMethod = fallBackMethod;
    }

    public override async Task Invoke(AspectContext context, AspectDelegate next)
    {
        // CircuitBreaker要求对于同一段代码要共享一个policy对象
        lock (this) // 线程安全考虑
        {
            if (policy == null)
            {
                policy = Policy.Handle<Exception>().FallbackAsync(async (ctx, t) =>
                {
                    AspectContext aspectContext = (AspectContext)ctx["aspectContext"];
                    var fallBackMethod = context.ServiceMethod.DeclaringType.GetMethod(FallBackMethod);
                    var fallBackResult = fallBackMethod.Invoke(context.Implementation, context.Parameters);
                    aspectContext.ReturnValue = fallBackResult;
                }, async (ex, t) => { });
            }

            // 设置 最大重试次数限制
            if (MaxRetryTimes > 0)
            {
                policy = policy.WrapAsync(Policy.Handle<Exception>()
                    .WaitAndRetryAsync(MaxRetryTimes,
                    i => TimeSpan.FromMilliseconds(RetryIntervalMilliseconds)));
            }

            // 启用熔断保护(CircuitBreaker)
            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));
            }
        }

        Context pollyContext = new Context();
        pollyContext["aspectContext"] = context;

        // 设置缓存时间
        if (CacheTTLMilliseconds > 0)
        {
            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), pollyContext);
                // 存入缓存中以便后面快速复用
                using (var cacheEntry = memoryCache.CreateEntry(cacheKey))
                {
                    cacheEntry.Value = context.ReturnValue;
                    cacheEntry.AbsoluteExpiration = DateTime.Now
                        + TimeSpan.FromMilliseconds(CacheTTLMilliseconds); // 设置缓存过期时间
                }
            }
        }
        else
        {
            // 如果没有启用缓存,则直接执行业务方法
            await policy.ExecuteAsync(ctx => next(context), pollyContext);
        }
    }
}

复制代码
  这个HystrixCommand并非我原创,而是引用的杨中科老师在.NET微服务中的代码,大家也可以直接通过NuGet安装这个封装好的Package:

NuGet>Install-Package RuPeng.HystrixCore

  这里不再多讲解代码,因为都有注释,大家通过一个案例调试以下就了解流程了。

4.2 在ASP.NET Core的使用
  (1)为了简化代理类对象的注入,不用在ASP.NET Core中再通过ProxyGeneratorBuilder进行注入,我们引入一个AspectCore的DI扩展包:

NuGet>Install-Package AspectCore.Extensions.DependencyInjection

  (2)改写Startup类的ConfigureService方法,把返回值从void改为IServiceProvider

复制代码
// This method gets called by the runtime. Use this method to add services to the container.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc();
.......
// AoP - AspectCore
RegisterServices(this.GetType().Assembly, services);
return services.BuildAspectCoreServiceProvider();
}
复制代码
  这里BuildAspectCoreServiceProvider就是让AspectCore接管注入。RegisterService方法如下所示:

复制代码
private static void RegisterServices(Assembly asm, IServiceCollection services)
{
foreach (var type in asm.GetExportedTypes())
{
bool hasHystrixCommand = type.GetMethods().Any(m =>
m.GetCustomAttribute(typeof(HystrixCommandAttribute)) != null);
if (hasHystrixCommand)
{
services.AddSingleton(type);
}
}
}
复制代码
  这里使用反射,筛选出那些带有HystrixCommandAttribute的类进行注入,从而减少一行一行注入的代码工作量。

  (3)这里假设我们需要进行熔断保护的方法所在类是一个ProductService类,它主要的功能就是通过HttpClient去调用ProductService的某个API,它的定义如下:

复制代码
public class ProductService
{
[HystrixCommand(nameof(GetAllProductsFallBackAsync),
IsEnableCircuitBreaker = true,
ExceptionsAllowedBeforeBreaking = 3,
MillisecondsOfBreak = 1000 * 5)]
public virtual async Task GetAllProductsAsync(string productType)
{
Console.WriteLine($"-->>Starting get product type : {productType}");
string str = null;
str.ToString();

        // to do : using HttpClient to call outer service to get product list

        return $"OK {productType}";
    }

    public virtual async Task<string> GetAllProductsFallBackAsync(string productType)
    {
        Console.WriteLine($"-->>FallBack : Starting get product type : {productType}");

        return $"OK for FallBack  {productType}";
    }
}

复制代码
  这里假设我们主要针对GetAllProductsAsync这个方法进行熔断保护,假设它会调用另一个Service的获取产品的接口,这个接口会访问核心数据库,其每天的访问量很大,我们对此接口进行熔断保护,设置在启用熔断保护前允许两次故障(这里主要指异常),熔断保护时间为5s。

  在Controller中,通过构造函数注入:

复制代码
[Produces("application/json")][Route("api/Client")]
public class ClientController : Controller
{
private readonly IClientService clientService;
private readonly ProductService productService;

    public ClientController(IClientService _clientService, ProductService _productService)
    {
        clientService = _clientService;
        productService = _productService;
    }

    [HttpGet("{id}")]
    public async Task<string> Get(int id)
    {
        var product = await productService.GetAllProductsAsync("B");

        return product;
    }
}

复制代码
  为了能够在控制台中看到熔断的信息,我们增加一句Console.WriteLine到HystrixCommandAttribute中:

复制代码
// 启用熔断保护(CircuitBreaker)
if (IsEnableCircuitBreaker)
{
policy = policy.WrapAsync(Policy.Handle()
.CircuitBreakerAsync(ExceptionsAllowedBeforeBreaking,
TimeSpan.FromMilliseconds(MillisecondsOfBreak), (ex, ts) =>
{
// assuem to do logging
Console.WriteLine($"Service API OnBreak -- ts = {ts.Seconds}s, ex.message = {ex.Message}");
}, () => {}));
}
复制代码
  这样当Polly启用熔断时便会在控制台中输出一段消息,实际使用中可以往日志中写一段日志信息。

  (4)开起内置服务器进行测试

  Step1.借助命令行启动一个WebAPI程序

  Step2.借助Postman/SoapUI等API测试工具,输入我们的URL,测试结果如下图所示:

  

  可以看到我们通过在Postman中访问这个URL从而触发Service中的异常,两次异常之后,便进入了熔断保护时间,此后5s内的访问都没有再进行实际代码的执行,而直接进入了Fallback方法执行降级后的逻辑。5s保护时间之后,则再次进入实际代码的执行。目前,这个Hystrix还存在一些问题,需继续完善,还无法正式投入使用,后续会结合Polly和Ocelot,在API网关处做统一熔断保护。

五、小结
  本篇首先介绍了一下熔断、降级以及AOP的基本概念,然后从两个流行的库Polly和AspectCore的基本使用开始了解如何在.NET Core代码中实现熔断机制和AOP,最后通过结合Polly+AspectCore封装了一个Hystrix来介绍了一下如何在ASP.NET Core程序中如何做到标签式地快速实现熔断降级机制。后续,会将Polly与Ocelot结合实践API网关,在Ocelot网关处做统一熔断保护。

参考资料
杨中科,《.NET微服务直播课课件(第二版)》

guwei,《谈谈我对服务熔断、服务降级的理解》

Jeffcky,《已被.NET基金会认可的弹性和瞬态故障处理库Polly介绍》

Lemon,《Asp.Net Core轻量级Aop解决方案:AspectCore》

Sunday_Xiao,《服务熔断保护Spring Cloud Hystrix》

Catcher Wong, 《再谈Circuit Breaker之使用Polly》

Polly官方文档,https://github.com/App-vNext/Polly

AspectCore官方文档,https://github.com/dotnetcore/AspectCore-Framework

作者:周旭龙

出处:http://edisonchou.cnblogs.com

原文地址:https://www.cnblogs.com/Leo_wl/p/9170425.html

时间: 2024-10-09 21:55:16

Polly+AspectCore实现熔断与降级机制的相关文章

.NET Core微服务之基于Polly+AspectCore实现熔断与降级机制

一.熔断.降级与AOP 1.1 啥是熔断? 在广义的解释中,熔断主要是指为控制股票.期货或其他金融衍生产品的交易风险,为其单日价格波动幅度规定区间限制,一旦成交价触及区间上下限,交易则自动中断一段时间("熔即断"),或就此"躺平"而不得超过上限或下限("熔而不断"). 而对于微服务来说,熔断就是我们常说的"保险丝",意为当服务出现某些状况时,切断服务,从而防止应用程序不断地常识执行可能会失败的操作造成系统的"雪崩&q

压力测试术语之熔断、降级、限流

1.熔断.降级.限流 概念 目的 触发方 触发场景 解决方 处理方案 所有用户表现一致 用户表现 熔断 从可用性可靠性着想,为防止系统的整体缓慢甚至崩溃 某个服务(下游服务)不可用 当失败的调用到一定阈值,如缺省是5秒内20次调用失败,就会启动熔断机制,自动触发 调用方 开启熔断之后,如何实现自动恢复?每隔一段时间,释放一个请求到服务端进行探测,如果后端服务已经恢复,则自动恢复 不一致 用户体验到的是某些功能暂时不可达或不可用 降级 为防止系统的整体缓慢甚至崩溃 服务出问题或者影响到核心流程的性

spring-cloud-hystrix服务熔断与降级

Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时,异常等,Hystrix能保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性. “断路器” 本身是一种开关设置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的,可处理的备选相应(fallBack),而不是长时间的等待或者抛出调用方法无法处理的异常,这样就保证了服务调用方的线程不会长时间,不必要的占用

springcloud hystrix(监控、熔断、降级)

spring cloud hystrix 简介 hystrix通过服务隔离.熔断(也可以称为断路).降级等手段控制依赖服务的延迟与失败. netflix hystrix 本篇中主要讲解对spring cloud 对hystrix的集成,至于如何单独使用hystrix可以参考我分享的pdf. spring cloud hystrix 引入依赖 ----------------------------------------------------------------- <!--hystrix-

使用Polly让程序有Retry的机制

有时候我们需要调用其他API的时候出现暂时连接不通超时的情况,那这时候可以通过Polly进行Retry. 1.从nuget引用polly, 2.定义需要处理的异常有哪些,比如 Policy.Handle<TimeoutException>().Or<FormatException>() 3.异常发生时候需要定义重试几次,等多久后再重试,比如 var policy = Policy.Handle<TimeoutException>().RetryAsync(3, (exc

.NET Core微服务之基于Ocelot实现API网关服务(续)

一.负载均衡与请求缓存 1.1 负载均衡 为了验证负载均衡,这里我们配置了两个Consul Client节点,其中ClientService分别部署于这两个节点内(192.168.80.70与192.168.80.71). 为了更好的展示API Repsonse来自哪个节点,我们更改一下返回值: [Route("api/[controller]")] public class ValuesController : Controller { // GET api/values [Http

.NET Core微服务系列基础文章

今年从原来的Team里面被抽出来加入了新的Team,开始做Java微服务的开发工作,接触了Spring Boot, Spring Cloud等技术栈,对微服务这种架构有了一个感性的认识.虽然只做了两个月的开发工作,但是对微服务架构的兴趣却没有结束,又因为自己的.NET背景(虽然对.NET的生态有点恨铁不成钢),想要探索一下在.NET平台下的微服务架构的可行性,也准备一些材料作为分享的素材. 幸运的是,在.NET Core首届在线峰会上,看到了很多前辈的分享,也增强了自己要摸索和实践.NET Co

【Spring Cloud】全家桶介绍(一)

摘自:https://www.cnblogs.com/iUtopia/p/11492072.html 一.微服务架构# 1.微服务架构简介# 1.1.分布式:不同的功能模块部署在不同的服务器上,减轻网站高并发带来的压力. 1.2.集群:多台服务器上部署相同应用构成一个集群,通过负载均衡共同向外提供服务. 1.3.微服务:微服务架构模式就是将web应用拆分为一系列小的服务模块,这些模块可以独立地编译.部署,并通过各自暴露的API接口通讯,共同组成一个web应用. 1.4.SpringCloud是基

SpringCloud系列七:Hystrix 熔断机制(Hystrix基本配置、服务降级、HystrixDashboard服务监控、Turbine聚合监控)

1.概念:Hystrix 熔断机制 2.具体内容 所谓的熔断机制和日常生活中见到电路保险丝是非常相似的,当出现了问题之后,保险丝会自动烧断,以保护我们的电器, 那么如果换到了程序之中呢? 当现在服务的提供方出现了问题之后整个的程序将出现错误的信息显示,而这个时候如果不想出现这样的错误信息,而希望替换为一个错误时的内容. 一个服务挂了后续的服务跟着不能用了,这就是雪崩效应 对于熔断技术的实现需要考虑以下几种情况: · 出现错误之后可以 fallback 错误的处理信息: · 如果要结合 Feign