Hystrix简介及简单代码示例
生活随笔
收集整理的這篇文章主要介紹了
Hystrix简介及简单代码示例
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Circuit Breaker:Hystrix Clientshttps://cloud.spring.io/spring-cloud-netflix/multi/multi__circuit_breaker_hystrix_clients.html3. Circuit Breaker: Hystrix ClientsNetflix創建了一個實現斷路器模式的名為Hystrix的庫,說明Hystrix是Netflix的一個類庫,Netflix還是挺偉大的,他開源了很多有用的類庫,然后Hystrix他實現了斷路器模式,在微服務架構中呢,通常會有很多層的服務調用,multiple layers,什么叫多層呢,譬如B是A的消費者,C是B的消費者,那這是不是就很多層了,有一個請求請求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.什么叫lower level呢,A相當于B的話他就是lower level,B相當于C/D的話也是lower level,這是更底層的一個服務,他叫lower level,底層失敗可能會造成級聯的失敗,然后一直到用戶的請求,也就是所謂的雪崩效應,當對特定服務的調用,達到了特定的閾值,斷路器他就會打開,然后請求他就不請求了,Hystrix它是5秒鐘失敗20次,他就會打開斷路器,他說在斷路器打開的情況下,一個回退機制可以由開發人員提供,瀏覽器有一個請求,API他依賴了ABCDE,這個服務B掛掉了,開發人員在這里提供一個機制,API就調用fallback的,他就不請求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.他說有一個斷路器,他可以阻止級聯的失敗,就是給出一定的時間,讓服務自己去修復,可以簡單的這樣理解,他這回退機制Hystrix保護的一個調用,或者說一個靜態的數據,或者一個空值,fallback可以是另外一個請求,靜態數據或者干脆給一個空算了,回退可能是chain,像過濾器有filter chain,他可以理解為鏈條一樣的東西,我可以打這樣的一個比方,因此第一個回退機制,它會make other business call,執行一些其它的業務請求,這些業務請求還是變成靜態數據,就是斷路器模式它是怎么樣玩的,這個簡介還是太簡單了,本身懂斷路器的話就不需要這個簡介,如果不懂的話,這邊寫的這么簡單,他還是不懂,3.1 How to Include Hystrixhttps://cloud.spring.io/spring-cloud-netflix/multi/multi__circuit_breaker_hystrix_clients.html我們已經形成了一個規律了,你想有什么,那就加starter,事實也是這樣的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);}}其實就是加@EnableCircuitBreaker這么一個注解@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的一個子項目<dependency><groupId>com.netflix.hystrix</groupId><artifactId>hystrix-javanica</artifactId><version>x.y.z</version>
</dependency>然后加上一個切面<aspects>...<aspect name="com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect"/>...
</aspects>然后通過AOP的語法去切面,然后你調用的時候就可以這么來了@Configuration
public class HystrixConfiguration {@Beanpublic HystrixCommandAspect hystrixAspect() {return new HystrixCommandAspect();}}當你寫的時候也可以寫@HystrixCommandpublic class UserService {
...@HystrixCommandpublic User getUserById(String id) {return userResource.getUserById(id);}
}
...這個東西它是干嘛的呢,他說Java語言有一個非常牛逼的優勢,就是相對于其他的語言,譬如說反射,譬如說注解,都是用注解和反射去實現他,他引入了一個明顯的解決方案,其實就是為Hystrix做了一些改進唄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的首頁,那我們點過去https://github.com/Netflix/Hystrix/wikihttps://github.com/Netflix/Hystrix/wiki/How-To-UseHow To UseHystrix本來是怎么用的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 + "!";}
}他寫一個類實現HystrixCommand,然后加一個泛型,然后他實現觀察者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異步的總的來說這個代碼還是很麻煩的,那javanica他做了一些改進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.他說Spring Cloud自動將Java Bean和注解,封裝到連接斷路器的代理中,斷路器什么時候打開,打開或者關閉這個斷路器,以及在失敗的時候做什么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這個注解,然后用這個注解的屬性,屬性的詳細信息,你看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>啟動類上加注解@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);
}譬如我要對這個方法加注解,那我這邊就得寫一個fallback,注意參數非得是一樣的,public User findByIdFallback(Long id) {User user = new User();user.setId(0L);return user;
}首先你這邊有參數的是Long,那你也得是Long,然后返回值是User,那你這邊也得是User方法名你隨便寫,就是你的參數和返回值一定跟原方法是一致的,10.40.8.152:8761/localhost:8010/movie/1因為hystrix的默認超時時間是1秒,你如果一秒鐘都沒有得到響應的話,他就會認為你的服務有問題,直接給你進fallback方法了,第一次進了Hytrix的fallback方法,這種問題不一定會出現,這可能跟機器的配置,還有網絡都會有關系,原因也有分析過,就是你的請求時間,他默認是1秒鐘,1秒鐘如果都沒有得到響應的話,他就進Hystrix的fallback方法了,現在是正常的狀態,我可以正常的進入到這里,現在我想讓他進怎么辦呢,我把User停掉,User掛掉了,就是所謂的lower levelA service failure in the lower level of services can cause cascading failure all the way up to the user.相對于Movie服務,用戶服務就是他的Lower level,我的lower level掛掉了,斷了一秒鐘他就進這里了,進來,他再轉一秒鐘又進這里了,多試幾次,你會發現他不轉了,根本就不轉,現在根本也不進這里了,localhost:8010/hystrix.stream如果他要是要發請求的話,它是要轉的,說明他就沒有去請求這個遠程的服務
<?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);}
}
?
總結
以上是生活随笔為你收集整理的Hystrix简介及简单代码示例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 超时机制,断路器模式简介
- 下一篇: Hystrix Health Indic