Hystrix是一個實現斷路器模式的庫。什么是斷路器模式呢?就像我們家庭中的電閘一樣,如果有那一處出現意外,那么電閘就會立刻跳閘來防止因為這一處意外而引起更大的事故,直到我們確認處理完那一處意外后才可以再打開電閘。而Hystrix的存在就是為了預防程序中出現這種問題而導致程序不可用的情況。
比如說我們有三個微服務 A、B、C,其中A依賴於B,B依賴於C,如果這時候C出現了問題,那么就導致B不可用,緊接着A也不可用,更有可能導致整個系統不可用。我們接下來就來看看如何利用Hystrix預防這種情況
創建項目
首先我們復制一份cloud-demo-consumer項目,改名為cloud-demo-consumer-hystrix
引入Hystrix的依賴
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
application.xml不用變
spring:
application: name: consumer-demo-hystrix server: port: 8090 eureka: client: healthcheck: enabled: true serviceUrl: defaultZone: http://root:root@localhost:8761/eureka instance: prefer-ip-address: true
CloudDemoConsumerApplication改名為CloudDemoConsumerHystrixApplication,並且它的注解應該是
@SpringBootApplication
@EnableEurekaClient @EnableCircuitBreake
上方我們不認識的這個@EnableCircuitBreake注解就是表示開啟斷路器模式的注解
然后我們看一下controller
@RestController
@RequestMapping("/user") public class UserController { @Autowired private RestTemplate restTemplate; @GetMapping("/getUser/{id}") @HystrixCommand(fallbackMethod = "getUserFallback") public User getUser(@PathVariable Long id){ return restTemplate.getForObject("http://provider-demo/user/getUser/"+id,User.class); } public User getUserFallback(Long id) { User user = new User(); user.setName("王五"); return user; } }
它相比較於原先的controller僅僅是多了一個@HystrixCommand(fallbackMethod = "getUserFallback")注解和一個方法,這個注解呢就是指定Hystrix在此方法超時時調用的方法。
測試
首先啟動我們代表Eureka服務的項目,然后啟動cloud-demo-provider項目,緊接着啟動我們現在的項目。
項目啟動以后我們打開瀏覽器訪問localhost:8088/user/getUser/2的時候發現一切正常,網頁上返回了張三這個用戶。如果我們沒有引入Hystrix的時候如果這時候把服務提供者停掉的話在訪問會出現什么情況呢,是不是會報錯,或者超時呀。
但是現在不一樣了,我們引入了Hystrix,所以我們現在停掉提供者訪問的時候會發現程序走了注解指定的fallbackMethod,也就是方法getUserFallBack,這個時候我們瀏覽器得到的結果是王五。
Hystrix默認的超時時間是1秒,也就是說它在等待服務提供者1秒后如果得不到結果的話就會認為提供者掛了,緊接着調用fallbackMethod。
這個時間其實我們可以控制,只需要在yml文件中配置一個屬性就可以自定義這個時間
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 1000 #1000毫秒
Feign的支持
接下來我們看一下Feign是怎么使用Hystrix,
這次我們改造cloud-demo-consumer-feign項目,項目名稱改為cloud-demo-consumer-feign-hystrix,同樣向上述 方式一樣引入Hystrix的依賴,
接着 CloudDemoConsumerFeignApplication類名改為 CloudDemoConsumerFeignHystrixApplication,同樣的加入@EnableCircuitBreaker注解
有一點不一樣的地方是我們需要在yml文件中配置一下來開啟Hystrix
feign.hystrix.enabled: true
這里controller中需要改造的不再是指定單個方法,而是指定接口的實現類
@FeignClient(name = "provider-demo", fallback = HystrixClientFallback.class)
來看一下這個實現類
@Component
public class HystrixClientFallback implements UserFeignClient { @Override public User getUser(Long id) { User user = new User(); user.setName("王五"); return user; } }
這樣的話如果接口中有多個方法的話我們就不必為每一個方法取指定了。
現在我們已經解決了服務提供者掛掉的事情了,但是有點不好的是,我們現在還不能知道服務提供者到底是咋掛的,要是能捕獲到服務提供者
拋的異常就好了,其實Hystrix對這個是支持的,我們接下來看一下
fallbackFactory
UserFeignClient上方的注解需要變一下
@FeignClient(name = "provider-demo", fallbackFactory = HystrixClientFactory.class)
這次使用的是fallbackFactory這個屬性,我們看一下它指定的這個類又是怎么實現的呢
@Component
public class HystrixClientFactory implements FallbackFactory<UserFeignClient> { private static final Logger LOGGER = LoggerFactory.getLogger(HystrixClientFactory.class); @Override public UserFeignClient create(Throwable cause) { HystrixClientFactory.LOGGER.info("the provider error is: {}", cause.getMessage()); return new UserFeignClient() { @Override public User getUser(Long id) { User user = new User(); user.setName("王五"); return user; } }; } }
我們可以看到,在這個create的工廠方法中,它的入參就是服務提供者的異常,得到了這個異常以后才會去做實現。這樣是不是更加靈活了呢?
GitHub:https://github.com/shiyujun/spring-cloud-demo
如果對您有所幫助,請記得幫忙點一個star哦
本文出自https://zhixiang.org.cn,轉載請保留。