1. 程式人生 > >.NET Core微服務之基於Steeltoe使用Hystrix熔斷保護與監控

.NET Core微服務之基於Steeltoe使用Hystrix熔斷保護與監控

一、關於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 Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // Add Steeltoe Discovery Client service
            services.AddDiscoveryClient(Configuration);
            services.AddSingleton<IClientService, ClientService>();
            // Add Steeltoe Hystrix Command
            services.AddHystrixCommand<ClientServiceCommand>("ClientService", Configuration);

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        }

        // 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();
            }

            app.UseMvc();
            // Add Steeltoe Discovery Client service
            app.UseDiscoveryClient();
        }
    }

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
    {
        ......

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // Add Steeltoe Discovery Client service
            services.AddDiscoveryClient(Configuration);
            services.AddSingleton<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的一些更高階的使用,本文沒有涉及,有興趣的原有可以自行檢視官方文件學習。

示例程式碼

參考資料

作者:周旭龍

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連結。