ASP.NET Core微服务之基于Steeltoe使用Hystrix熔断保护与监控

释放双眼,带上耳机,听听看~!

Tip: 此篇已加入.NET Core微服务基础系列文章索引

=>  Steeltoe目录快速导航

  1. 基于Steeltoe使用Spring Cloud Eureka
  2. 基于Steeltoe使用Spring Cloud Zuul
  3. 基于Steeltoe使用Spring Cloud Hystrix

一、关于Spring Cloud Hystrix

ASP.NET Core微服务之基于Steeltoe使用Hystrix熔断保护与监控

在微服务架构中,我们将系统拆分为很多个服务,各个服务之间通过注册与订阅的方式相互依赖,由于各个服务都是在各自的进程中运行,就有可能由于网络原因或者服务自身的问题导致调用故障或延迟,随着服务的积压,可能会导致服务崩溃。为了解决这一系列的问题,断路器等一系列服务保护机制出现了。

断路器本身是一种开关保护机制,用于在电路上保护线路过载,当线路中有电器发生短路时,断路器能够及时切断故障电路,防止发生过载、发热甚至起火等严重后果。

针对上述问题,Spring Cloud Hystrix 实现了断路器、线路隔离等一系列服务保护功能。它也是基于 Netflix 的开源框架 Hystrix 实现的,该框架的目标在于通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。Hystrix 具备服务降级、服务熔断、线程和信号隔离、请求缓存、请求合并以及服务监控等强大功能。

ASP.NET Core微服务之基于Steeltoe使用Hystrix熔断保护与监控

二、快速集成Hystrix实现熔断保护

2.1 准备工作

这里仍然基于第一篇的示例进行修改,各个项目的角色如下表所示:

eureka-service
服务发现&注册(Spring Boot)
zuul-service
API网关 (Spring Boot)
agent-service
服务提供者 (ASP.NET Core)
client-service
服务提供者 (ASP.NET Core)
premium-service
服务提供者&服务消费者 (ASP.NET Core)

所有相关服务注册到Eureka之后的服务列表:

ASP.NET Core微服务之基于Steeltoe使用Hystrix熔断保护与监控

这里仍然假设premium-service要调用client-service的接口,我们想要模拟的效果就是针对client-service的调用进行熔断保护。

要使用Hystrix,需要对服务添加依赖包:

PM> Install-Package Steeltoe.CircuitBreaker.HystrixCore

2.2 为PremiumService添加Hystrix相关类与配置

(1)增加一个HystrixCommand : ClientServiceCommand


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
1    public class ClientServiceCommand : HystrixCommand<string>
2    {
3        IClientService _clientService;
4        ILogger<ClientServiceCommand> _logger;
5        private int _clientId;
6
7        public ClientServiceCommand(IHystrixCommandOptions options, IClientService clientService,
8            ILogger<ClientServiceCommand> logger) : base(options)
9        {
10            _clientService = clientService;
11            _logger = logger;
12            IsFallbackUserDefined = true;
13        }
14
15        public async Task<string> GetClientName(int clientId)
16        {
17            _clientId = clientId;
18            return await ExecuteAsync();
19        }
20
21        protected override async Task<string> RunAsync()
22        {
23            var result = await _clientService.GetClientName(_clientId);
24            _logger.LogInformation("Run: {0}", result);
25            return result;
26        }
27
28        protected override async Task<string> RunFallbackAsync()
29        {
30            _logger.LogInformation("RunFallback");
31            return await Task.FromResult<string>("Sorry, the service is unavaliable now. Please try again later.");
32        }
33    }
34

根据Steeltoe官方文档说明,每个Command都必须继承HystrixCommand或HystrixCommand,然后实现这个RunAsync方法与RunFallbackAsync方法。可以看出,RunAsync方法是实现原有业务逻辑,而RunFallbackAsync方法则是受保护降级后的方法,这里简单地输出了一句提示信息“Service is unavaiable. Please try again later.”。

另外,Steeltoe提供了一个快速的HystrixCommand的写法,见下面这个示例代码,全部在构造函数里面搞定:


1
2
3
4
5
6
7
8
9
10
1public class HelloWorldCommand : HystrixCommand<string>
2{
3    public HelloWorldCommand(string name)
4        : base(HystrixCommandGroupKeyDefault.AsKey("HelloWorldGroup"),
5                () => { return "Hello" + name; },
6                () => { return "Hello" + name + " via fallback"; })
7    {
8    }
9}
10

但是,这里不得不吐槽一下,在Java中对HystrixCommand的封装是注解级别,工作量小的不是真的不是太多,见下例Java代码:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1@RestController
2public class MovieController {
3    ......
4
5    @HystrixCommand(fallbackMethod = "findByIdFallback")
6    @GetMapping(value = "/user/{id}")
7    public User findById(@PathVariable Long id) {
8        return restTemplate.getForObject("http://user-service/" + id, User.class);
9    }
10
11    public User findByIdFallback(Long id){
12        User user = new User();
13        user.setId(-1L);
14        user.setUsername("Default User");
15
16        return user;
17    }
18}
19

(2)改写Controller,使用ClientServiceCommand类替换原有ClientService


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1    [Route("api/[controller]")]
2    [ApiController]
3    public class ValuesController : ControllerBase
4    {
5        private ClientServiceCommand _clientServiceCommand;
6        private ILogger<ValuesController> _logger;
7
8        public ValuesController(ClientServiceCommand clientServiceCommand, ILogger<ValuesController> logger)
9        {
10            _clientServiceCommand = clientServiceCommand;
11            _logger = logger;
12        }
13
14        ......
15
16        // GET api/values/5
17        [HttpGet("{id}")]
18        public async Task<string> Get(int id)
19        {
20            _logger?.LogInformation($"api/values/{id}");
21            return await _clientServiceCommand.GetClientName(id);
22        }
23    }
24

这里不再直接使用ClientService实例,改为使用ClientServiceCommand实例,实际上是一个代理模式的应用。

(3)在启动类中添加Hystrix相关配置


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
1    public class Startup
2    {
3        public Startup(IConfiguration configuration)
4        {
5            Configuration = configuration;
6        }
7
8        public IConfiguration Configuration { get; }
9
10        // This method gets called by the runtime. Use this method to add services to the container.
11        public void ConfigureServices(IServiceCollection services)
12        {
13            // Add Steeltoe Discovery Client service
14            services.AddDiscoveryClient(Configuration);
15            services.AddSingleton<IClientService, ClientService>();
16            // Add Steeltoe Hystrix Command
17            services.AddHystrixCommand<ClientServiceCommand>("ClientService", Configuration);
18
19            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
20        }
21
22        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
23        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
24        {
25            if (env.IsDevelopment())
26            {
27                app.UseDeveloperExceptionPage();
28            }
29
30            app.UseMvc();
31            // Add Steeltoe Discovery Client service
32            app.UseDiscoveryClient();
33        }
34    }
35

2.3 快速验证  

(1)同时启动所有微服务,然后访问PremiumService的相关接口,正常情况下,能够正常返回调用ClientService接口的结果

ASP.NET Core微服务之基于Steeltoe使用Hystrix熔断保护与监控

(2)关闭ClientService,然后再次PremiumService的相关接口,这时会返回受保护降级后的Fallback结果

ASP.NET Core微服务之基于Steeltoe使用Hystrix熔断保护与监控

三、快速集成Hystrix Dashboard实现指标监控

_摘抄一句蟋蟀的话:_在实际应用中,我们需要对 Hystrix 断路器进行监控,比如熔断请求有多少等等,Spring Cloud 中的实现有 Turbine 进行收集,数据展示的话使用 Hystrix Dashboard。

3.1 快速构建一个Hystrix Dashboard服务

(1)创建一个Spring Boot项目:这里版本是Spring Boot 1.5.15.RELEASE,Spring Cloud Edgware.SR3

(2)pom.xml中添加相关依赖包


1
2
3
4
5
1    <dependency>
2    <groupId>org.springframework.cloud</groupId>
3    <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
4    </dependency>
5

(3)启动类中添加EnableHystrixDashboard注解


1
2
3
4
5
6
7
8
1@SpringBootApplication
2@EnableHystrixDashboard
3public class DashboardServiceApplication {
4    public static void main(String[] args) {
5        SpringApplication.run(DashboardServiceApplication.class, args);
6    }
7}
8

(4)必要的配置(application.yml)


1
2
3
4
5
6
7
1server:
2  port: 5010
3
4spring:
5  application:
6    name: hystrix-dashboard-service
7

3.2 快速在ASP.NET Core中集成Hystrix Metrics

(1)安装Hystrix Dashboard相关包

PM>Install-Package Steeltoe.CircuitBreaker.Hystrix.MetricsEventsCore

(2)改写PremiumService启动类添加相关的Metrics配置


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
1    public class Startup
2    {
3        ......
4
5        // This method gets called by the runtime. Use this method to add services to the container.
6        public void ConfigureServices(IServiceCollection services)
7        {
8            // Add Steeltoe Discovery Client service
9            services.AddDiscoveryClient(Configuration);
10            services.AddSingleton<IClientService, ClientService>();
11            // Add Steeltoe Hystrix Command
12            services.AddHystrixCommand<ClientServiceCommand>("ClientService", Configuration);
13
14            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
15
16            // Add Hystrix Metrics to container
17            services.AddHystrixMetricsStream(Configuration);
18        }
19
20        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
21        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
22        {
23            if (env.IsDevelopment())
24            {
25                app.UseDeveloperExceptionPage();
26            }
27
28            // Add Steeltoe Discovery Client service
29            app.UseDiscoveryClient();
30
31            app.UseMvc();
32            
33            // Start Hystrix metrics stream service
34            app.UseHystrixMetricsStream();
35        }
36    }
37

(3)启动Premium-Service,查看URL:http://localhost:8030/hystrix/hystrix.stream

ASP.NET Core微服务之基于Steeltoe使用Hystrix熔断保护与监控

上图中我们会看到不断实时刷新的 Hystrix 指标监控数据了,但显示并不友好,我咋知道这些指标是啥玩意儿啊!因此,还是让我们在仪表盘中来看看吧。

3.3 快速验证

(1)启动Hystrix Dashboard服务,输入URL:http://localhost:8030/hystrix/hystrix.stream,然后点击按钮“Monitor Stream”

ASP.NET Core微服务之基于Steeltoe使用Hystrix熔断保护与监控

(2)由于ClientServiceCommand尚未起任何作用,所以第一次得到的数据如下:

ASP.NET Core微服务之基于Steeltoe使用Hystrix熔断保护与监控

(3)多次请求ClientService,然后关闭ClientService,再多次请求,这时熔断保护已启动

(4)再次查看Hystrix Dashboard,可以看到以下数据:触发了3次熔断保护

ASP.NET Core微服务之基于Steeltoe使用Hystrix熔断保护与监控

关于Hystrix Dashboard的仪表盘数据属性说明,可以参考下面这张图(From 园友寻找风口的猪 的《Hystrix Dashboard仪表盘》):

ASP.NET Core微服务之基于Steeltoe使用Hystrix熔断保护与监控

四、小结

本文简单介绍了一下Spring Cloud Hystrix这个熔断保护组件,并演示了如何基于Steeltoe OSS使用Hystrix实现熔断保护,并基于Hystrix Dashboard演示了如何收集和可视化地查看ASP.NET Core的熔断监控数据。对于Steeltoe OSS提供的Hystrix的组件的使用,相对于Java的Hystrix的注解封装,代码量稍微大一些。另外,关于Hystrix的一些更高级的使用,本文没有涉及,有兴趣的原有可以自行查看官方文档学习。

示例代码

Click => https://github.com/EdisonChou/Microservice.PoC.Steeltoe/tree/master/src/Chapter2-CircuitBreaker

参考资料

Steeltoe官方文档:《Steeltoe Doc》

Steeltoe官方示例:https://github.com/SteeltoeOSS/Samples

蟋蟀,《.NET Core 微服务架构 Steeltoe的使用》

周立,《Spring Cloud与Docker 微服务架构实战》

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

寻找风口的猪 的《Hystrix Dashboard仪表盘》

给TA打赏
共{{data.count}}人
人已打赏
安全网络

CDN安全市场到2022年价值76.3亿美元

2018-2-1 18:02:50

安全技术

使用Rust从零写操作系统 (3) —— 格式化输出

2022-1-12 12:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索