zoukankan      html  css  js  c++  java
  • .NET Core微服务之基于Steeltoe使用Hystrix熔断保护与监控

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

    =>  Steeltoe目录快速导航

    1. 基于Steeltoe使用Spring Cloud Eureka

    2. 基于Steeltoe使用Spring Cloud Zuul

    3. 基于Steeltoe使用Spring Cloud Hystrix

    4. 基于Steeltoe使用Spring Cloud Config

    5. 基于Steeltoe使用Zipkin

    一、关于Spring Cloud Hystrix

      

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

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

      针对上述问题,Spring Cloud Hystrix 实现了断路器、线路隔离等一系列服务保护功能。它也是基于 Netflix 的开源框架 Hystrix 实现的,该框架的目标在于通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。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之后的服务列表:

      

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

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

    PM> Install-Package Steeltoe.CircuitBreaker.HystrixCore

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

      (1)增加一个HystrixCommand : ClientServiceCommand

        public class ClientServiceCommand : HystrixCommand<string>
        {
            IClientService _clientService;
            ILogger<ClientServiceCommand> _logger;
            private int _clientId;
    
            public ClientServiceCommand(IHystrixCommandOptions options, IClientService clientService, 
                ILogger<ClientServiceCommand> logger) : base(options)
            {
                _clientService = clientService;
                _logger = logger;
                IsFallbackUserDefined = true;
            }
    
            public async Task<string> GetClientName(int clientId)
            {
                _clientId = clientId;
                return await ExecuteAsync();
            }
    
            protected override async Task<string> RunAsync()
            {
                var result = await _clientService.GetClientName(_clientId);
                _logger.LogInformation("Run: {0}", result);
                return result;
            }
    
            protected override async Task<string> RunFallbackAsync()
            {
                _logger.LogInformation("RunFallback");
                return await Task.FromResult<string>("Sorry, the service is unavaliable now. Please try again later.");
            }
        }

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

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

    public class HelloWorldCommand : HystrixCommand<string>
    {
        public HelloWorldCommand(string name)
            : base(HystrixCommandGroupKeyDefault.AsKey("HelloWorldGroup"),
                    () => { return "Hello" + name; },
                    () => { return "Hello" + name + " via fallback"; })
        {
        }
    }

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

    @RestController
    public class MovieController {
        ......
    
        @HystrixCommand(fallbackMethod = "findByIdFallback")
        @GetMapping(value = "/user/{id}")
        public User findById(@PathVariable Long id) {
            return restTemplate.getForObject("http://user-service/" + id, User.class);
        }
    
        public User findByIdFallback(Long id){
            User user = new User();
            user.setId(-1L);
            user.setUsername("Default User");
    
            return user;
        }
    }

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

        [Route("api/[controller]")]
        [ApiController]
        public class ValuesController : ControllerBase
        {
            private ClientServiceCommand _clientServiceCommand;
            private ILogger<ValuesController> _logger;
    
            public ValuesController(ClientServiceCommand clientServiceCommand, ILogger<ValuesController> logger)
            {
                _clientServiceCommand = clientServiceCommand;
                _logger = logger;
            }
    
            ......
    
            // GET api/values/5
            [HttpGet("{id}")]
            public async Task<string> Get(int id)
            {
                _logger?.LogInformation($"api/values/{id}");
                return await _clientServiceCommand.GetClientName(id);
            }
        }

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

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

        public class Startup
        {
            ......
    
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddSingleton<IClientService, ClientService>();
                // Add Steeltoe Discovery Client service
                services.AddDiscoveryClient(Configuration);
                // Add Steeltoe handler to container
                services.AddTransient<DiscoveryHttpMessageHandler>();
                // Configure a HttpClient
                services.AddHttpClient("client-api-values", c =>
                {
                    c.BaseAddress = new Uri(Configuration["Services:Client-Service:Url"]);
                })
                .AddHttpMessageHandler<DiscoveryHttpMessageHandler>()
                .AddTypedClient<IClientService, ClientService>();
                // Add Steeltoe Hystrix Command
                services.AddHystrixCommand<ClientServiceCommand>("ClientService", Configuration);
    
                services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
            }
        }

    2.3 快速验证  

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

      

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

      

    三、快速集成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中添加相关依赖包

        <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>

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

    @SpringBootApplication
    @EnableHystrixDashboard
    public class DashboardServiceApplication {
        public static void main(String[] args) {
            SpringApplication.run(DashboardServiceApplication.class, args);
        }
    }

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

    server:
      port: 5010
    
    spring:
      application:
        name: hystrix-dashboard-service

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

      (1)安装Hystrix Dashboard相关包

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

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

        public class Startup
        {
            ......
    
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddSingleton<IClientService, ClientService>();
                // Add Steeltoe Discovery Client service
                services.AddDiscoveryClient(Configuration);
                // Add Steeltoe handler to container
                services.AddTransient<DiscoveryHttpMessageHandler>();
                // Configure a HttpClient
                services.AddHttpClient("client-api-values", c =>
                {
                    c.BaseAddress = new Uri(Configuration["Services:Client-Service:Url"]);
                })
                .AddHttpMessageHandler<DiscoveryHttpMessageHandler>()
                .AddTypedClient<IClientService, ClientService>();
                // Add Steeltoe Hystrix Command
                services.AddHystrixCommand<ClientServiceCommand>("ClientService", Configuration);
    
                services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    
                // Add Hystrix Metrics to container
                services.AddHystrixMetricsStream(Configuration);
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
    
                // Add Steeltoe Discovery Client service
                app.UseDiscoveryClient();
    
                app.UseMvc();
                
                // Start Hystrix metrics stream service
                app.UseHystrixMetricsStream();
            }
        }

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

      

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

    3.3 快速验证

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

      

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

      

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

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

      

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

      

    四、小结

      本文简单介绍了一下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仪表盘

  • 相关阅读:
    文件处理(记录经典代码及相关逻辑)
    python与pip在widow下cmd命令行操作问题收集:python、pip不是内部或外部命令,也不是可运行程序
    python—函数中存在的部分问题
    python —匿名函数(lambda)
    Python—递归函数
    python-函数参数
    python代码运行过程
    String类练习
    String类的常用方法
    死锁与进程通信
  • 原文地址:https://www.cnblogs.com/edisonchou/p/dotnet_core_microservice_integrate_with_springcloud_hystrix.html
Copyright © 2011-2022 走看看