引入依赖
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-hystrixartifactId>
dependency>
启动类上添加注解
@EnableHystrix
使用Hystrix保护接口,在接口方法上添加注解 @HystrixCommand(fallbackMethod = “fallback”),其中fallback是当接口调用发生异常时,执行的降级方法。如下两种情况都会触发降级。
@SpringBootApplication
@RestController
@EnableHystrix // 启动类上要添加注解
public class Micro4App {
public static void main(String[] args) {
SpringApplication.run(Micro4App.class);
}
@HystrixCommand(fallbackMethod = "fallback")
@GetMapping("/test1")
public String test1() throws InterruptedException {
// int i = 1/0;
TimeUnit.SECONDS.sleep(3);
return "Micro4App test1";
}
public String fallback(){
return "fallback : Micro4App test1 方法故障了";
}
}
全局配置 默认不设置是1秒
# 方法调用超过5秒则触发降级
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 5000
在某个具体的接口上,通过@HystrixCommand配置
@HystrixCommand(fallbackMethod = "fallback",commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "2000")
})
@GetMapping("/test1")
public String test1() throws InterruptedException {
// int i = 1/0;
TimeUnit.SECONDS.sleep(3);
return "Micro4App test1";
}
马丁福勒断路器论文:https://martinfowler.com/bliki/CircuitBreaker.html
在调用指定服务时,如果说这个服务的失败率达到你输入的一个阈值,将断路器从closed状态,转变为open状态,指定服务是无法被访问的,如果你访问就直接走fallback方法,在一定的时间内,open状态会再次转变为half open状态,允许一个请求发送到我的指定服务,如果成功,转变为closed,如果失败,服务再次转变为open状态,会再次循环到half open,直到断路器回到一个closed状态。
配置断路器的监控界面
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboardartifactId>
dependency>
启动类中加注解
@EnableHystrixDashboard
开启Hystirx的监控Servlet,用于提供监控数据
@WebServlet("/hystrix.stream")
public class HystrixServlet extends HystrixMetricsStreamServlet {
}
//------------------------------------------------------------
// 在启动类上,添加扫描Servlet的注解
@ServletComponentScan("com.qf.servlet")
配置文件中设置允许监控localhost
hystrix:
dashboard:
proxy-stream-allow-list: localhost
测试直接访问http://host:port/hystrix 他只监控加了 降级的 方法
断路器的属性(默认10s秒中之内至少有20个请求,50%的请求出现异常或超时,断路器开。)
配置信息 | name | value |
---|---|---|
断路器的开关 | circuitBreaker.enabled | true |
至少有20个请求才进行errorThresholdPercentage错误百分比计算 | circuitBreaker.requestVolumeThreshold | 20 |
请求总数失败率达到%多少时 | circuitBreaker.errorThresholdPercentage | 50 |
断路器open状态后,多少秒是拒绝请求的 | circuitBreaker.sleepWindowInMilliseconds | 5000 |
强制让服务拒绝请求 | circuitBreaker.forceOpen | false |
强制让服务接收请求 | circuitBreaker.forceClosed | false |
@GetMapping("/test2/{flag}")
@HystrixCommand(fallbackMethod = "test2fallback",commandProperties = {
@HystrixProperty(name = "circuitBreaker.enabled",value = "true"),
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "70"),
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "5000")
})
public String test2(@PathVariable("flag") String flag) throws InterruptedException {
System.out.println("进入test2 方法了。。。。");
if (flag.equals("1")){
int i = 1/0;
}
System.out.println(Thread.currentThread().getName());
return "test2 ok";
}
//fallbackMethod 中设置的是降级方法的名字
@GetMapping("/test1")
@HystrixCommand(fallbackMethod = "test1fallback",commandProperties = {
//设置该接口的超时时间,一旦超时返回降级方法中的结果
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "2000")
})//加了这个注解超时时间不超过1秒,超过就降级
public String test1() throws InterruptedException {
System.out.println("test还没熔断");
int a=1/0;
// Thread.sleep(3000);
return "hello hystrix";
}
public String test1fallback() throws InterruptedException{
System.out.println("-------------");
return "test1()降级方法返回的数据";
}
Hystrix通过线程池配置可以进行请求限流。
@GetMapping("/test3")
@HystrixCommand(
fallbackMethod = "fallback",
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
},
threadPoolKey = "mypool",
threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "5"),
@HystrixProperty(name = "maxQueueSize", value = "5")
}
)
public String test3() throws InterruptedException {
System.out.println(Thread.currentThread().getName());
TimeUnit.SECONDS.sleep(1);
return "test3 ok";
}
@GetMapping("/tt/{num}")
public String tt(@PathVariable("num") Integer num) throws InterruptedException {
RestTemplate restTemplate = new RestTemplate();
CountDownLatch countDownLatch = new CountDownLatch(num);
for (int i=0;i<num;i++){
new Thread(new Runnable() {
@Override
public void run() {
String s = restTemplate.getForObject("http://localhost:9300/test3", String.class);
System.out.println(Thread.currentThread().getName()+s);
countDownLatch.countDown();
}
}).start();
}
countDownLatch.await();
return "ok";
}
自己: 限流超出的请求不会 开启 断路器 ,不记录失败数!
@GetMapping("/test2")
public String test2(){
System.out.println("处理请求的线程名字为"+Thread.currentThread().getName());
return Thread.currentThread().getName();
}
@GetMapping("/test3")
/**
* 限制 test3的最大并发度为10 ,即最多可以同时处理10个请求,
* 超出的请求会被降级
* @return
*/
@HystrixCommand(fallbackMethod = "test3fallback",
threadPoolKey = "mypool",
threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "5"),
@HystrixProperty(name = "maxQueueSize", value = "5")
}
)
public String test3(){
System.out.println("处理请求的线程名字为"+Thread.currentThread().getName());
return Thread.currentThread().getName();
}
public String test3fallback(){
return "这是test3的降级方法";
}
}