四、Hystrix進行容錯處理
1.Ribbon整合Hystrix
添加pom依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
在啓動類添加@EnableHystrix或@EnableCircuitBreaker註解,修改service層增加@HystrixCommand註解並標明fallbackMethod方法,添加遇到錯誤時返回的缺省方法,這個方法要和fallbackMethod中的方法名一致,參數要和原方法一致:
@Service
public class HelloServiceImpl implements HelloService {
@Autowired
RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "hiError",
//配置具體見https://github.com/Netflix/Hystrix/wiki/Configuration
commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000"),//調用者等待命令執行的超時限制,超過此時間,HystrixCommand被標記爲TIMEOUT,並執行回退邏輯。
@HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "10000"), //統計的滾動窗口的時間段大小。該屬性是線程池保持指標時間長短。
@HystrixProperty(name = "execution.isolation.strategy", value = "THREAD")},//Hystrix隔離策略有THREAD和SENSPHORE兩種,THREAD(線程隔離)HystrixCommand會在單獨線程執行 SENSPHORE(信號量隔離)在調用線程上執行,收到信號量限制
threadPoolProperties = {@HystrixProperty(name = "coreSize", value = "1"),//線程池中核心線程數量
@HystrixProperty(name = "maxQueueSize",value = "10")})//隊列大小
@Override
public String getService() {
return restTemplate.getForObject("http://service-offer/test,String.class);
}
public String error(){
return "get error";
}
}
關掉所有服務提供者後在訪問服務消費者得到的結果是get error。
2.Feign整合Hystrix
Feign是動態代理接口,不能寫fallbackMethod,要新建一個類實現有@FeignClient的接口:
@Component
public class ServiceOfferFeignClientFallback implements ServiceOfferFeignClient {
@Override
public String getService() {
return "get error from feign";
}
}
在@FeignClient的接口上增加fallback屬性:
@FeignClient(name = "service-offer", fallback = ServicehiFeignClientFallback.class)
在application.yml中打開Hystrix的開關:
feign:
hystrix:
enabled: true
這樣Feign就整合了Hystrix。
Feign還可以通過FallbackFactory來整合,新建ServicOfferiFeignClientFallbackFactory類實現FallbackFactory<ServiceOfferFeignClient>接口:
@Component
public class ServiceOfferFeignClientFallbackFactory implements FallbackFactory<ServiceOfferFeignClient> {
@Override
public ServiceOfferFeignClient create(Throwable throwable) {
return new ServiceOfferFeignClient() {
@Override
public String getService() {
return "get from fallback factory";
}
};
}
}
修改FeignClient接口:
@FeignClient(name = "service-hi", fallbackFactory = ServiceOfferFeignClientFallbackFactory.class)
這樣也可以實現斷路器。
如果某個服務要禁用Hystrix,添加如下配置類:
@Configuration
public class FeignDisableHystrixConfiguration {
@Bean
@Scope("prototype")
public Feign.Builder feignBuilder(){
return Feign.builder();
}
}
然後在FeignClient的配置類中指定Feign.Builder的配置類即可:
@FeignClient(name = "service-offer", configuration = FeignDisableHystrixConfiguration.class)
3.Hystrix監控
添加Actuator依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
application.yml中增加actuator暴露的節點hystrix.stream:
management:
endpoints:
web:
exposure:
include: health,info,env,hystrix.stream
重新啓動服務先訪問一次服務消費者的服務,然後訪問localhost:8765/actuator/hystrix.stream,可以看到頁面反覆出先如下內容:
ping: data: {"type":"HystrixCommand","name":"ServicehiFeignClient#hiService(String)","group":"service-hi","currentTime":1551319254509,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":0,"rollingCountBadRequests":0,"rollingCountCollapsedRequests":0,"rollingCountEmit":0,"rollingCountExceptionsThrown":0,"rollingCountFailure":0,"rollingCountFallbackEmit":0,"rollingCountFallbackFailure":0,"rollingCountFallbackMissing":0,"rollingCountFallbackRejection":0,"rollingCountFallbackSuccess":0,"rollingCountResponsesFromCache":0,"rollingCountSemaphoreRejected":0,"rollingCountShortCircuited":0,"rollingCountSuccess":0,"rollingCountThreadPoolRejected":0,"rollingCountTimeout":0,"currentConcurrentExecutionCount":0,"rollingMaxConcurrentExecutionCount":0,"latencyExecute_mean":470,"latencyExecute":{"0":470,"25":470,"50":470,"75":470,"90":470,"95":470,"99":470,"99.5":470,"100":470},"latencyTotal_mean":474,"latencyTotal":{"0":474,"25":474,"50":474,"75":474,"90":474,"95":474,"99":474,"99.5":474,"100":474},"propertyValue_circuitBreakerRequestVolumeThreshold":20,"propertyValue_circuitBreakerSleepWindowInMilliseconds":5000,"propertyValue_circuitBreakerErrorThresholdPercentage":50,"propertyValue_circuitBreakerForceOpen":false,"propertyValue_circuitBreakerForceClosed":false,"propertyValue_circuitBreakerEnabled":true,"propertyValue_executionIsolationStrategy":"THREAD","propertyValue_executionIsolationThreadTimeoutInMilliseconds":1000,"propertyValue_executionTimeoutInMilliseconds":1000,"propertyValue_executionIsolationThreadInterruptOnTimeout":true,"propertyValue_executionIsolationThreadPoolKeyOverride":null,"propertyValue_executionIsolationSemaphoreMaxConcurrentRequests":10,"propertyValue_fallbackIsolationSemaphoreMaxConcurrentRequests":10,"propertyValue_metricsRollingStatisticalWindowInMilliseconds":10000,"propertyValue_requestCacheEnabled":true,"propertyValue_requestLogEnabled":true,"reportingHosts":1,"threadPool":"service-hi"} data: {"type":"HystrixThreadPool","name":"service-hi","currentTime":1551319254509,"currentActiveCount":0,"currentCompletedTaskCount":1,"currentCorePoolSize":10,"currentLargestPoolSize":1,"currentMaximumPoolSize":10,"currentPoolSize":1,"currentQueueSize":0,"currentTaskCount":1,"rollingCountThreadsExecuted":0,"rollingMaxActiveThreads":0,"rollingCountCommandRejections":0,"propertyValue_queueSizeRejectionThreshold":5,"propertyValue_metricsRollingStatisticalWindowInMilliseconds":10000,"reportingHosts":1}
如果出現全是ping,那就是沒有先訪問一次服務。
4.Hystrix Dashboard
新建一個名叫servicehystrix的項目,添加pom依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
啓動類上添加@EnableHystrixDashboard註解,application.yml:
server:
port: 8000
啓動後訪問localhost:8000/hystrix,可看到如下界面:
將之前整合了Hystrix的服務消費者啓動,在URL一欄輸入localhost:8765/actuator/hystrix.stream,然後填寫一個title,點擊Monitor Stream,可以看到下圖的界面。
5.Turbine聚合監控數據
新建一個serviceturbine項目,pom依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-turbine</artifactId>
</dependency>
啓動類上添加@EnableTurbine註解,
application.yml:
server:
port: 8001
spring:
application:
name: serviceturbine
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
turbine:
app-config: service-ribbon,service-consumer
cluster-name-expression: "'default'"
再次啓動一個服務消費者(需要整合Actuator並打開hystrix.stream這個斷點)和一個服務提供者,並將服務消費者名稱修改給servi-consumer,服務提供者名稱改爲servicehi,servi-consumer的service層消費servicehi這個服務提供者,這樣就有兩個服務消費者和服務提供者啓動了。這時候啓動servicehystrix和serviceturbine,將兩個服務消費者都訪問幾次,然後訪問localhost:8001/turbine.stream,得到如下:
訪問localhost:8000/hystrix,然後輸入URLlocalhost:8001/turbine.stream,設置一個title點擊Monitor Stream,得到下面的界面: