天天看點

Dubbo + Hystrix 實作服務熔斷熔斷器簡介

熔斷器簡介

在微服務架構中,根據業務來拆分成一個個的服務,服務與服務之間可以通過 RPC 互相調用。為了保證其高可用,單個服務通常會叢集部署。由于網絡原因或者自身的原因,服務并不能保證 100% 可用,如果單個服務出現問題,調用這個服務就會出現線程阻塞,此時若有大量的請求湧入,Servlet 容器的線程資源會被消耗完畢,導緻服務癱瘓。服務與服務之間的依賴性,故障會傳播,會對整個微服務系統造成災難性的嚴重後果,這就是服務故障的 “雪崩” 效應。

為了解決這個問題,業界提出了熔斷器模型。

Netflix 開源了 Hystrix 元件,實作了熔斷器模式,Spring Cloud 對這一元件進行了整合。在微服務架構中,一個請求需要調用多個服務是非常常見的,如下圖:

Dubbo + Hystrix 實作服務熔斷熔斷器簡介

較底層的服務如果出現故障,會導緻連鎖故障。當對特定的服務的調用的不可用達到一個閥值(Hystrix 是 5 秒 20 次) 熔斷器将會被打開。

Dubbo + Hystrix 實作服務熔斷熔斷器簡介

熔斷器打開後,為了避免連鎖故障,通過 fallback 方法可以直接傳回一個固定值。

Dubbo Provider 中使用熔斷器

在 pom.xml 中增加依賴

<groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    <version>2.0.1.RELEASE</version>
</dependency>           

在 Application 中增加 @EnableHystrix 注解

import com.alibaba.dubbo.container.Main;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;

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

在 Service 中增加 @HystrixCommand 注解

在調用方法上增加 @HystrixCommand 配置,此時調用會經過 Hystrix 代理

import com.alibaba.dubbo.config.annotation.Service;
import com.funtl.hello.dubbo.service.user.api.UserService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.beans.factory.annotation.Value;

@Service(version = "${user.service.version}")
public class UserServiceImpl implements UserService {

    @Value("${dubbo.protocol.port}")
    private String port;

    @HystrixCommand(commandProperties = {
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
    })
    @Override
    public String sayHi() {
//        return "Hello Dubbo, i am from port:" + port;
        throw new RuntimeException("Exception to show hystrix enabled.");
    }
}           

測試熔斷器

此時我們再次請求服務提供者,浏覽器會報 500 異常

Dubbo Consumer 中使用熔斷器

<groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    <version>2.0.1.RELEASE</version>
</dependency>           
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;

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

在調用方法上增加 @HystrixCommand 注解,并指定 fallbackMethod 方法

import com.alibaba.dubbo.config.annotation.Reference;
import com.funtl.hello.dubbo.service.user.api.UserService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

   @Reference(version = "${user.service.version}")
   private UserService userService;

   @HystrixCommand(fallbackMethod = "hiError")
   @RequestMapping(value = "hi")
   public String sayHi() {
       return userService.sayHi();
   }

   public String hiError() {
       return "Hystrix fallback";
   }
}           

此時我們再次請求服務提供者,浏覽器會顯示:

Hystrix fallback