Hystrix简介及简单代码示例
生活随笔
收集整理的這篇文章主要介紹了
Hystrix简介及简单代码示例
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Circuit Breaker:Hystrix Clientshttps://cloud.spring.io/spring-cloud-netflix/multi/multi__circuit_breaker_hystrix_clients.html3. Circuit Breaker: Hystrix ClientsNetflix創(chuàng)建了一個(gè)實(shí)現(xiàn)斷路器模式的名為Hystrix的庫(kù),說(shuō)明Hystrix是Netflix的一個(gè)類庫(kù),Netflix還是挺偉大的,他開(kāi)源了很多有用的類庫(kù),然后Hystrix他實(shí)現(xiàn)了斷路器模式,在微服務(wù)架構(gòu)中呢,通常會(huì)有很多層的服務(wù)調(diào)用,multiple layers,什么叫多層呢,譬如B是A的消費(fèi)者,C是B的消費(fèi)者,那這是不是就很多層了,有一個(gè)請(qǐng)求請(qǐng)求C,大致可以這樣理解Netflix has created a library called Hystrix that implements the circuit breaker pattern. In a microservice architecture, it is common to have multiple layers of service calls, as shown in the following example:A service failure in the lower level of services can cause cascading failure all the way up to the user.When calls to a particular service exceed circuitBreaker.requestVolumeThreshold (default: 20 requests)and the failure percentage is greater than circuitBreaker.errorThresholdPercentage (default: >50%) in a rolling window defined by metrics.rollingStats.timeInMilliseconds (default: 10 seconds), the circuit opens and the call is not made. In cases of error and an open circuit, a fallback can be provided by the developer.什么叫l(wèi)ower level呢,A相當(dāng)于B的話他就是lower level,B相當(dāng)于C/D的話也是lower level,這是更底層的一個(gè)服務(wù),他叫l(wèi)ower level,底層失敗可能會(huì)造成級(jí)聯(lián)的失敗,然后一直到用戶的請(qǐng)求,也就是所謂的雪崩效應(yīng),當(dāng)對(duì)特定服務(wù)的調(diào)用,達(dá)到了特定的閾值,斷路器他就會(huì)打開(kāi),然后請(qǐng)求他就不請(qǐng)求了,Hystrix它是5秒鐘失敗20次,他就會(huì)打開(kāi)斷路器,他說(shuō)在斷路器打開(kāi)的情況下,一個(gè)回退機(jī)制可以由開(kāi)發(fā)人員提供,瀏覽器有一個(gè)請(qǐng)求,API他依賴了ABCDE,這個(gè)服務(wù)B掛掉了,開(kāi)發(fā)人員在這里提供一個(gè)機(jī)制,API就調(diào)用fallback的,他就不請(qǐng)求B了
Having an open circuit stops cascading failures and allows overwhelmed or failing services time to recover. The fallback can be another Hystrix protected call, static data, or a sensible empty value. Fallbacks may be chained so that the first fallback makes some other business call, which in turn falls back to static data.他說(shuō)有一個(gè)斷路器,他可以阻止級(jí)聯(lián)的失敗,就是給出一定的時(shí)間,讓服務(wù)自己去修復(fù),可以簡(jiǎn)單的這樣理解,他這回退機(jī)制Hystrix保護(hù)的一個(gè)調(diào)用,或者說(shuō)一個(gè)靜態(tài)的數(shù)據(jù),或者一個(gè)空值,fallback可以是另外一個(gè)請(qǐng)求,靜態(tài)數(shù)據(jù)或者干脆給一個(gè)空算了,回退可能是chain,像過(guò)濾器有filter chain,他可以理解為鏈條一樣的東西,我可以打這樣的一個(gè)比方,因此第一個(gè)回退機(jī)制,它會(huì)make other business call,執(zhí)行一些其它的業(yè)務(wù)請(qǐng)求,這些業(yè)務(wù)請(qǐng)求還是變成靜態(tài)數(shù)據(jù),就是斷路器模式它是怎么樣玩的,這個(gè)簡(jiǎn)介還是太簡(jiǎn)單了,本身懂?dāng)嗦菲鞯脑捑筒恍枰@個(gè)簡(jiǎn)介,如果不懂的話,這邊寫(xiě)的這么簡(jiǎn)單,他還是不懂,3.1 How to Include Hystrixhttps://cloud.spring.io/spring-cloud-netflix/multi/multi__circuit_breaker_hystrix_clients.html我們已經(jīng)形成了一個(gè)規(guī)律了,你想有什么,那就加starter,事實(shí)也是這樣的To include Hystrix in your project, use the starter with a group ID of org.springframework.cloud and a artifact ID of spring-cloud-starter-netflix-hystrix. See the Spring Cloud Project page for details on setting up your build system with the current Spring Cloud Release Train.https://spring.io/projects/spring-cloud@SpringBootApplication
@EnableCircuitBreaker
public class Application {public static void main(String[] args) {new SpringApplicationBuilder(Application.class).web(true).run(args);}}其實(shí)就是加@EnableCircuitBreaker這么一個(gè)注解@Component
public class StoreIntegration {@HystrixCommand(fallbackMethod = "defaultStores")public Object getStores(Map<String, Object> parameters) {//do stuff that might fail}public Object defaultStores(Map<String, Object> parameters) {return /* something useful */;}
}The @HystrixCommand is provided by a Netflix contrib library called “javanica”.先看一下“javanica”是什么https://github.com/Netflix/Hystrix/tree/master/hystrix-contrib/hystrix-javanica它是hystrix的一個(gè)子項(xiàng)目<dependency><groupId>com.netflix.hystrix</groupId><artifactId>hystrix-javanica</artifactId><version>x.y.z</version>
</dependency>然后加上一個(gè)切面<aspects>...<aspect name="com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect"/>...
</aspects>然后通過(guò)AOP的語(yǔ)法去切面,然后你調(diào)用的時(shí)候就可以這么來(lái)了@Configuration
public class HystrixConfiguration {@Beanpublic HystrixCommandAspect hystrixAspect() {return new HystrixCommandAspect();}}當(dāng)你寫(xiě)的時(shí)候也可以寫(xiě)@HystrixCommandpublic class UserService {
...@HystrixCommandpublic User getUserById(String id) {return userResource.getUserById(id);}
}
...這個(gè)東西它是干嘛的呢,他說(shuō)Java語(yǔ)言有一個(gè)非常牛逼的優(yōu)勢(shì),就是相對(duì)于其他的語(yǔ)言,譬如說(shuō)反射,譬如說(shuō)注解,都是用注解和反射去實(shí)現(xiàn)他,他引入了一個(gè)明顯的解決方案,其實(shí)就是為Hystrix做了一些改進(jìn)唄Java language has a great advantages over other languages such as reflection and annotations. All modern frameworks such as Spring, Hibernate, myBatis and etc. seek to use this advantages to the maximum. The idea of introduction annotations in Hystrix is obvious solution for improvement.https://github.com/Netflix/Hystrix這是Hystrix github的首頁(yè),那我們點(diǎn)過(guò)去https://github.com/Netflix/Hystrix/wikihttps://github.com/Netflix/Hystrix/wiki/How-To-UseHow To UseHystrix本來(lái)是怎么用的public class CommandHelloWorld extends HystrixCommand<String> {private final String name;public CommandHelloWorld(String name) {super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));this.name = name;}@Overrideprotected String run() {// a real example would do work like a network call herereturn "Hello " + name + "!";}
}他寫(xiě)一個(gè)類實(shí)現(xiàn)HystrixCommand,然后加一個(gè)泛型,然后他實(shí)現(xiàn)觀察者public class CommandHelloWorld extends HystrixObservableCommand<String> {private final String name;public CommandHelloWorld(String name) {super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));this.name = name;}@Overrideprotected Observable<String> construct() {return Observable.create(new Observable.OnSubscribe<String>() {@Overridepublic void call(Subscriber<? super String> observer) {try {if (!observer.isUnsubscribed()) {// a real example would do work like a network call hereobserver.onNext("Hello");observer.onNext(name + "!");observer.onCompleted();}} catch (Exception e) {observer.onError(e);}}} ).subscribeOn(Schedulers.io());}
}Synchronous Execution同步的Asynchronous Execution異步的總的來(lái)說(shuō)這個(gè)代碼還是很麻煩的,那javanica他做了一些改進(jìn)Spring Cloud automatically wraps Spring beans with that annotation in a proxy that is connected to the Hystrix circuit breaker. The circuit breaker calculates when to open and close the circuit and what to do in case of a failure.他說(shuō)Spring Cloud自動(dòng)將Java Bean和注解,封裝到連接斷路器的代理中,斷路器什么時(shí)候打開(kāi),打開(kāi)或者關(guān)閉這個(gè)斷路器,以及在失敗的時(shí)候做什么To configure the @HystrixCommand you can use the commandProperties attribute with a list of @HystrixProperty annotations. See here for more details. See the Hystrix wiki for details on the properties available.如果你想配置@HystrixCommand,你可以用@HystrixProperty這個(gè)注解,然后用這個(gè)注解的屬性,屬性的詳細(xì)信息,你看Hystrix wikihttps://github.com/Netflix/Hystrix/tree/master/hystrix-contrib/hystrix-javanica#configurationmicroservice-consumer-movie-ribbon-with-hystrix首先是加上依賴,<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>啟動(dòng)類上加注解@EnableCircuitBreaker@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class ConsumerMovieRibbonApplication {@Bean@LoadBalancedpublic RestTemplate restTemplate() {return new RestTemplate();}public static void main(String[] args) {SpringApplication.run(ConsumerMovieRibbonApplication.class, args);}
}方法上面加注解, @HystrixCommand(fallbackMethod = "defaultStores")@GetMapping("/movie/{id}")
@HystrixCommand(fallbackMethod = "findByIdFallback")
public User findById(@PathVariable Long id) {// http://localhost:7900/simple/// VIP virtual IP// HAProxy Heartbeatreturn this.restTemplate.getForObject("http://microservice-simple-provider-user/simple/" + id, User.class);
}譬如我要對(duì)這個(gè)方法加注解,那我這邊就得寫(xiě)一個(gè)fallback,注意參數(shù)非得是一樣的,public User findByIdFallback(Long id) {User user = new User();user.setId(0L);return user;
}首先你這邊有參數(shù)的是Long,那你也得是Long,然后返回值是User,那你這邊也得是User方法名你隨便寫(xiě),就是你的參數(shù)和返回值一定跟原方法是一致的,10.40.8.152:8761/localhost:8010/movie/1因?yàn)閔ystrix的默認(rèn)超時(shí)時(shí)間是1秒,你如果一秒鐘都沒(méi)有得到響應(yīng)的話,他就會(huì)認(rèn)為你的服務(wù)有問(wèn)題,直接給你進(jìn)fallback方法了,第一次進(jìn)了Hytrix的fallback方法,這種問(wèn)題不一定會(huì)出現(xiàn),這可能跟機(jī)器的配置,還有網(wǎng)絡(luò)都會(huì)有關(guān)系,原因也有分析過(guò),就是你的請(qǐng)求時(shí)間,他默認(rèn)是1秒鐘,1秒鐘如果都沒(méi)有得到響應(yīng)的話,他就進(jìn)Hystrix的fallback方法了,現(xiàn)在是正常的狀態(tài),我可以正常的進(jìn)入到這里,現(xiàn)在我想讓他進(jìn)怎么辦呢,我把User停掉,User掛掉了,就是所謂的lower levelA service failure in the lower level of services can cause cascading failure all the way up to the user.相對(duì)于Movie服務(wù),用戶服務(wù)就是他的Lower level,我的lower level掛掉了,斷了一秒鐘他就進(jìn)這里了,進(jìn)來(lái),他再轉(zhuǎn)一秒鐘又進(jìn)這里了,多試幾次,你會(huì)發(fā)現(xiàn)他不轉(zhuǎn)了,根本就不轉(zhuǎn),現(xiàn)在根本也不進(jìn)這里了,localhost:8010/hystrix.stream如果他要是要發(fā)請(qǐng)求的話,它是要轉(zhuǎn)的,說(shuō)明他就沒(méi)有去請(qǐng)求這個(gè)遠(yuǎn)程的服務(wù)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.learn</groupId><artifactId>microservice-consumer-movie-ribbon-with-hystrix</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>microservice-simple-consumer-movie</name><description>Demo project for Spring Boot</description><parent><groupId>cn.learn</groupId><artifactId>microcloud02</artifactId><version>0.0.1</version></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-hystrix</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
#debug=true
server.port=8010eureka.client.serviceUrl.defaultZone=http://admin:1234@10.40.8.152:8761/eurekaspring.application.name=microservice-consumer-movie-Hystrix
eureka.instance.prefer-ip-address=true
eureka.instance.instance-id=${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
eureka.client.healthcheck.enabled=true
spring.redis.host=10.40.8.152
spring.redis.password=aztech
spring.redis.port=6379microservice-simple-provider-user.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
package com.learn.cloud.controller;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;import com.learn.cloud.entity.User;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;@RestController
public class MovieController {@Autowiredprivate RestTemplate restTemplate;@GetMapping("/movie/{id}")@HystrixCommand(fallbackMethod = "findByIdFallback")public User findById(@PathVariable Long id) {// http://localhost:7900/simple/// VIP virtual IP// HAProxy Heartbeatreturn this.restTemplate.getForObject("http://microservice-simple-provider-user/simple/" + id, User.class);}public User findByIdFallback(Long id) {User user = new User();user.setId(0L);return user;}}
package com.learn.cloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class ConsumerMovieHystrixApplication {@Bean@LoadBalancedpublic RestTemplate restTemplate() {return new RestTemplate();}public static void main(String[] args) {SpringApplication.run(ConsumerMovieHystrixApplication.class, args);}
}
?
總結(jié)
以上是生活随笔為你收集整理的Hystrix简介及简单代码示例的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 超时机制,断路器模式简介
- 下一篇: Hystrix Health Indic