簡單的搭建的流程:第一,eureka注冊中心;第二,在eureka上注冊的服務;第三,在eureka消費服務的用戶端,hystrix,是在用戶端上的使用,在調用端嵌入jar包,以jar包的方式使用hystrix,不需要額外的安裝,在項目中添加如下依賴。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
@EnableCircuitBreaker或@EnableHystrix開啟hystrix的使用,由于這是在服務調用端的添加,是以一般還需要添加@EnableDiscoveryClient注解,還可以使用@SpringCloudApplication,進去這個注解可以發現這個注解包括以下注解,是以@SpringCloudApplication注解可以使用hystrix
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}
hystrix提供5部分的服務,分别是降級、隔離、熔斷器、異常和緩存,對于緩存,個人認為是雞肋的功能,在這裡不做說明。在網上看到很多使用代碼的方式進行降級等操作,個人認為并不好,這些屬于非功能的業務使用注解的方式會更好,是以在這裡主要介紹注解的方式。
降級:
/**
* 同步的方式實作
* @return
*/
@HystrixCommand(fallbackMethod = "fallback")
public String consumer() {
return restTemplate.getForObject("http://COMPUTE-SERVICE/add?a=10&b=20", String.class);
}
/**
* 異步的方式實作
* @return
*/
@HystrixCommand(
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value ="40000"),
}
)
public Future<String> consumerA(){
return new AsyncResult<String>() {
@Override
public String invoke() {
return restTemplate.getForObject("http://COMPUTE-SERVICE/add?a=10&b=20", String.class);
}
};
}
public String fallback() {
return "fallbck";
}
有兩種實作的方式,一種同步一種異步,當服務調用失敗的時候,便會直接調用fallback方法,異步需要調用端按照以下方式處理才能擷取相關資料
Future<String> result = consumerService.consumerA();
return result.get();
降級處理的時候可以連續降級,fallback方法是可以繼續使用HystrixCommand指令指定降級方法,直到處理完畢
隔離:
/**
* @return
*/
@HystrixCommand(
//表示所屬的group,一個group共用線程池,預設使用類名作為一個組,
//同一個分組,使用相同的線程池,線程池的個數按照最小的定義限定,是以線程池定義一次就可以了,再次使用的時候直接定義分組
//同一個分組,不同的線程池,按照不同的線程池來限定
groupKey = "GroupOne",
//線程池的名稱
threadPoolKey = "groupOnePoolE",
fallbackMethod = "fallbackTest",
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value ="20000"),
},
//以下這些值,在分組的情況下有效
threadPoolProperties = {
//核心線程數
@HystrixProperty(name = "coreSize", value = "3"),
//超過隊列的個數會直接失敗
@HystrixProperty(name = "maxQueueSize", value = "10"),
//隊列小于最大值,拒絕請求
@HystrixProperty(name = "queueSizeRejectionThreshold", value = "3")
//總結:請求數目大于核心線程數+隊列的拒絕數的時候就會失敗,配置降級方法的時候,不會失敗直接調用降級方法
//預設的情況下,以service的名稱作為線程池的名稱,使用HystrixCommand預設情況下coreSize為10,maxQueueSize使用LinkedBlockingQueue動态拓展,queueSizeRejectionThreshold預設大小值5
}
)
public String consumerPN() {
try{
Thread.sleep(10000);
}catch (Exception e){
}
return restTemplate.getForObject("http://COMPUTE-SERVICE/add?a=10&b=20", String.class);
}
public String fallbackTest(){
return "十次使用者請求并發後,超過設定會觸發這個降級,否則會出現失敗頁面";
}
熔斷器:
@HystrixCommand(
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value ="11000"),
//是否開啟熔斷器
@HystrixProperty(name = "circuitBreaker.enabled", value ="true"),
//請求的失敗數目超過這個之後,就會打開熔斷器
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value ="5"),
//熔斷器工作時間,預設5秒,超過這個時間便會放流量進去
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value ="50000"),
//出錯率超過75%,啟動熔斷器,預設50%
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value ="75"),
}
)
public String fuse() {
try{
Thread.sleep(10000);
}catch (Exception e){
}
return restTemplate.getForObject("http://COMPUTE-SERVICE/add?a=10&b=20", String.class);
}
異常:
/**
* 以下方式抛出RuntimeException異常的時候不會降級,而是直接按照異常進行處理,将異常抛給調用端
* 如果沒有在ignoreExceptions中添加RuntimeException,則會将異常按照降級方法進行處理
* @return
*/
@HystrixCommand(ignoreExceptions = {RuntimeException.class},fallbackMethod = "fallback")
public String consumerAT() {
String result = null;
try {
result = restTemplate.getForObject("http://add?a=10&b=20", String.class);
}catch (Exception e){
throw new RuntimeException();
}
return result;
}