前言

上一篇介绍了使用Steeltoe来处理服务熔断,这篇我们将用Polly来处理服务熔断。

不废话了,直接进正题。

简单的例子

同样先定义一个简单的服务。

[Route("api/[controller]")]
public class ValuesController : Controller
{
// GET api/values
[HttpGet]
public string Get()
{
return "service--a";
}
}

再来一个新服务去调用上面的服务。

定义一个用于访问服务的Service接口和实现。

public interface IAService
{
Task<string> GetAsync();
} public class AService : IAService
{
private PolicyWrap<string> _policyWrap; private ILogger _logger; public AService(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<AService>(); //超时
var timeout = Policy
.TimeoutAsync(1, Polly.Timeout.TimeoutStrategy.Pessimistic, (context, ts, task) =>
{
_logger.LogInformation("AService timeout");
return Task.CompletedTask;
}); //熔断
var circuitBreaker = Policy
.Handle<Exception>()
.CircuitBreakerAsync(2, TimeSpan.FromSeconds(5), (ex, ts) =>
{
_logger.LogInformation($"AService OnBreak -- ts = {ts.Seconds}s ,ex.message = {ex.Message}");
}, () =>
{
_logger.LogInformation("AService OnReset");
}); //Fallback + 熔断 + 超时
_policyWrap = Policy<string>
.Handle<Exception>()
.FallbackAsync(GetFallback(), (x) =>
{
_logger.LogInformation($"AService Fallback -- {x.Exception.Message}");
return Task.CompletedTask;
})
.WrapAsync(circuitBreaker)
.WrapAsync(timeout);
} //降级处理
private string GetFallback()
{
return "fallback";
} public async Task<string> GetAsync()
{
return await _policyWrap.ExecuteAsync(() =>
{
return QueryAsync();
});
} private async Task<string> QueryAsync()
{
using (var client = new HttpClient())
{
var res = await client.GetStringAsync("http://localhost:9001/api/values");
return res;
}
}
}

要注意的有几个地方。

Polly没有既包含熔断又包含降级又包含超时的,这个需要自己去组合。相对来说,Hystrix在这一方面似乎好一点点。

但是,各有各的好,Polly分离了每一个模块,让我们自由组合,也是很灵活的。

所以可以看到,我们定义了3个Policy,再把它们Wrap起来。

另外,还在触发每一个Policy的时候,都会输出相应的日记,方便我们后面看效果。

对于写日记这一块,个人认为对比Steeltoe,Polly的方式要更加方便和简单。

下面是控制器的使用。

// GET api/values
[HttpGet]
public async Task<string> A([FromServices]IAService aService)
{
return await aService.GetAsync();
}

还有一个关键的步骤:在Startup注册我们的AService。

services.AddSingleton<IAService, AService>();

切记是Singleton!不然熔断就不会起作用了!!

直接上效果图

简单说明一下这张图,一开始,服务A和调用方都是正常的,后面中断服务A,使其不可用,这个时候调用方就会走降级处理。

调用方多请求几次,就可以看到OnBreak的日记输出,说明断路器已经处于Open状态,不会直接走真正的请求,而是走的Fallback。

最后启动服务A,可以看到OnReset的日记输出,说明断路器已经处于Closed状态了,浏览器显示的也是服务A的返回结果。

再来模拟一下超时的情形。

因为上面设置的超时时间是1秒,所以让其休息1001毫秒就可以模拟了。

// GET api/values
[HttpGet]
public string Get()
{
System.Threading.Thread.Sleep(1001);
return "service--a";
}

再来看看效果图

调用方一直是提示因为超时而降级,而熔断。从日记也可以看出,是因为超时而导致熔断的。

前面还提到一个注册服务的问题,这里解释一下为什么我们要让其注册成Singleton?

我们先把注册服务这一块调整为不是Singleton,这里以Scope为例,Transient也是一样的。

public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IAService, AService>();
//services.AddSingleton<IAService, AService>();
services.AddMvc();
}

效果如下:

可以看到,日记一直输出超时!并没有提示熔断相关的信息!这说明我们设置的熔断并没有起作用!!

这个问题与实例的生命周期有着密不可分的关系!

试想一下,如果每次请求,都创建一个AService的实例,同样的每次都会重新创建一个新的熔断器,那熔断还会生效吗?

反之,如果熔断器只有一个,那么无论发起多少次请求,它都是唯一的,所以它才能统计到有多少次异常,从而去触发熔断。

这也是一个我们需要特别注意的地方。不然一个不小心就入坑了。

总结

Polly用起来还是比较简单,比较灵活的,我们可以组合多种不同的Policy来达到我们想要的结果。

本文的示例代码:

CircuitBreakerDemo

再探Circuit Breaker之使用Polly的更多相关文章

  1. Circuit Breaker Pattern(断路器模式)

    Handle faults that may take a variable amount of time to rectify when connecting to a remote service ...

  2. Circuit Breaker模式

    Circuit Breaker模式会处理一些需要一定时间来重连远程服务和远端资源的错误.该模式可以提高一个应用的稳定性和弹性. 问题 在类似于云的分布式环境中,当一个应用需要执行一些访问远程资源或者是 ...

  3. 【再探backbone 02】集合-Collection

    前言 昨天我们一起学习了backbone的model,我个人对backbone的熟悉程度提高了,但是也发现一个严重的问题!!! 我平时压根没有用到model这块的东西,事实上我只用到了view,所以昨 ...

  4. ViewPager+Fragment再探:和TAB滑动条一起三者结合

    Fragment前篇: <Android Fragment初探:静态Fragment组成Activity> ViewPager前篇: <Android ViewPager初探:让页面 ...

  5. 再探jQuery

    再探jQuery 前言:在使用jQuery的时候发现一些知识点记得并不牢固,因此希望通过总结知识点加深对jQuery的应用,也希望和各位博友共同分享. jQuery是一个JavaScript库,它极大 ...

  6. [老老实实学WCF] 第五篇 再探通信--ClientBase

    老老实实学WCF 第五篇 再探通信--ClientBase 在上一篇中,我们抛开了服务引用和元数据交换,在客户端中手动添加了元数据代码,并利用通道工厂ChannelFactory<>类创 ...

  7. Spark Streaming揭秘 Day7 再探Job Scheduler

    Spark Streaming揭秘 Day7 再探Job Scheduler 今天,我们对Job Scheduler再进一步深入一下,对一些更加细节的源码进行分析. Job Scheduler启动 在 ...

  8. 再探ASP.NET 5(转载)

    就在最近一段时间,微软又有大动作了,在IDE方面除了给我们发布了Viausl Studio 2013 社区版还发布了全新的Visual Studio 2015 Preview. Visual Stud ...

  9. 再探java基础——break和continue的用法

    再探java基础——break和continue的用法 break break可用于循环和switch...case...语句中. 用于switch...case中: 执行完满足case条件的内容内后 ...

随机推荐

  1. org/w3c/dom/ElementTraversal 错误解决办法

    org/w3c/dom/ElementTraversal 错误解决办法 不记得之前几天把什么maven依赖包删除了,今天利用htmlunit运行代码的时候报了下面的错误: Exception in t ...

  2. (三十七)从私人通讯录引出的细节I -Notification -Segue -HUD -延时

    细节1:账号和密码都有值的时候才可以点击登录按钮,因此应该监听文本框的文本改变. 因为文本框的文本改变代理不能处理,因此应该使用通知Notification. 文本框文本改变会发出通知:通知的前两个参 ...

  3. H5的学习之旅-H5的实体(14)

    H5有些关键字比如<等等是显示不出来的,这时候,就需要用实体来表示,实体我理解就是最初的编码 代码实例 <!DOCTYPE html> <html lang="en& ...

  4. json进阶(一)js读取解析JSON类型数据

    js读取解析JSON类型数据 一.什么是JSON? JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,是理想的数据交换格式,同 ...

  5. Cocos2D中的Framerate状态

    对于额外绘制调试物理引擎的支持,Cocos2D同样可以绘制概述计数器,尤其是帧速率(framerate)显示. 为了启用这些概述计数器标签,你只需添加如下一行代码,比如说在AppDelegate.m里 ...

  6. hadoop学习大纲

  7. PDA开发数据由DB下载至PDA本地

    public string DownFile = "\\下载.txt";//下载路径 public string LoadFile = "\\上传.txt";/ ...

  8. HTTPSQS 队列

    http://blog.csdn.net/21aspnet/article/details/7467812 http://hi.baidu.com/caoxin_rain/item/5282770cd ...

  9. AngularJS进阶(十四)AngularJS灵异代码事件

    AngularJS灵异代码事件 注:请点击此处进行充电! 事情原委 router_sys.js源代码如下: 自己在html路由跳转的代码如下: 但是在实际路由过程中,却路由到了下面的状态,相应的页面中 ...

  10. 【面试笔试算法】Program 6: 字符消除(hiho题库)

    时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi最近在玩一个字符消除游戏.给定一个只包含大写字母"ABC"的字符串s,消除过程是如下进行的: 1) ...