在微服务架构中,我们将系统拆分为很多个服务,各个服务之间通过注册与订阅的方式相互依赖,由于各个服务都是在各自的进程中运行,就有可能由于网络原因或者服务自身的问题导致调用故障或延迟,随着服务的积压,可能会导致服务崩溃。为了解决这一系列的问题,断路器等一系列服务保护机制出现了。
断路器本身是一种开关保护机制,用于在电路上保护线路过载,当线路中有电器发生短路时,断路器能够及时切断故障电路,防止发生过载、发热甚至起火等严重后果。
在分布式架构中,断路器模式的作用也是类似的。
针对上述问题,Spring Cloud Hystrix 实现了断路器、线路隔离等一系列服务保护功能。它也是基于 Netflix 的开源框架 Hystrix 实现的,该框架的目标在于通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。Hystrix 具备服务降级、服务熔断、线程和信号隔离、请求缓存、请求合并以及服务监控等强大功能。
简单直白的介绍:
当A调用B服务时,B服务不太稳定,经常挂掉。那么在A调用的方法里加入Hystrix方法,并写一个fallbackMethod方法;在A服务多次调用B服务失败后,将不在调用B服务,而是直接返回fallbackMethod方法.
一、添加依赖
由于spring-cloud-starter-netflix-hystrix这个新版依赖的springboot版本是2.0.3,然而dubbo-spring-boot-starter最新版依赖的springboot是1.5.10,如果强行集成会有jar包冲突,启动不了,因此决定不再使用dubbo-spring-boot-starter,修改依赖如下:
ext {
springboot= "2.1.1.RELEASE"
libs = [
springboot: [
"org.springframework.boot:spring-boot-starter-web:${springboot}",
],
dubbo:[
"com.101tec:zkclient:0.9",
"com.alibaba:dubbo:2.6.5",
"com.alibaba.spring:spring-context-support:1.0.2",
"org.apache.curator:curator-framework:2.9.1"
],
commons: [
"org.springframework.cloud:spring-cloud-starter-netflix-hystrix:${springboot}",
"redis.clients:jedis:3.0.0",
"com.alibaba:fastjson:1.2.4",
"com.alibaba:druid:1.1.9",
"dom4j:dom4j:1.6.1",
"ch.qos.logback:logback-classic:1.2.3",
"ch.qos.logback:logback-core:1.2.3",
"com.sun.mail:mailapi:1.6.0",
"com.sun.mail:smtp:1.6.0",
"mysql:mysql-connector-java:5.1.39",
"cn.easyproject:ojdbc7:12.1.0.2.0",
"org.formcept:sqljdbc42:4.2",
"net.sourceforge.jtds:jtds:1.3.1",
"org.slf4j:slf4j-api:1.7.13",
"cn.afterturn:easypoi-base:3.0.3",
"cn.afterturn:easypoi-web:3.0.3",
"cn.afterturn:easypoi-annotation:3.0.3",
]
]
}
二、修改入口,加上@EnableHystrix 注解启用Hystrix
三、为需要断路器的服务添加注解
Consumer:
package cn.ktp.auth.api;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.dubbo.config.annotation.Reference;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import cn.ktp.auth.iservice.IAuthService;
@RestController
@RequestMapping(value = "ktp/api/auth")
public class KtpAuthApi {
@Reference(timeout=4000)
private IAuthService authService;
@RequestMapping(value="hello")
@HystrixCommand(fallbackMethod="helloFallBack")
public String hello() {
return authService.hello();
}
public String helloFallBack() {
return "fallback";
}
}
Provider:
package cn.ktp.auth.service;
import java.util.Random;
import com.alibaba.dubbo.config.annotation.Service;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import cn.ktp.auth.iservice.IAuthService;
@Service
@org.springframework.stereotype.Service
public class AuthService implements IAuthService {
@HystrixCommand(commandProperties = {
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000") })
@Override
public String hello() {
int nextInt = new Random().nextInt(4000);
System.out.println("sleep " + nextInt + "ms");
try {
Thread.sleep(nextInt);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "HELLO " + nextInt + " from Dubbo Spring Boot";
}
}
集成就这么简单!
看看效果,当请求时间小于2秒时
当请求时间大于2秒时
项目已经上传至https://gitee.com/krisdevhome/ktp-main
四、hystrix简单教程
1.如上面的示例添加@HystrixCommand
定义服务降级,这里的fallbackMethod是
服务调用失败后调用的方法。
2.@HystrixCommand
注解源码可以发现里面有个ignoreExceptions
参数。该参数是定义忽略指定的异常功能。
@HystrixCommand(fallbackMethod = "fallback",ignoreExceptions = {NullPointerException.class})
上面的注解表示当方法抛出NullPointerException
时会将异常抛出,而不触发降级服务。
3.在自定义的服务降级方法中可以使用Throwable 获取异常信息,如
public String helloFallBack(Throwable throwable) {
return throwable.getMessage();
}
4.在高并发的场景下,Hystrix中提供了请求缓存的功能,可以方便的开启和使用请求缓存来优化系统,达到减轻高并发时的请求线程消耗、降低请求相应时间。
在SpringCloudHystrix中与缓存有关的三个注解:
- @CacheResult:用来标记其你去命令的结果应该被缓存,必须与@HystrixCommand注解结合使用;
- @CacheRemove:该注解用来让请求命令的缓存失败,失效的缓存根据定义的Key决定;
- @CacheKey:该注解用来在请求命令的参数上标记,是其作文缓存的Key值,如果没有标注则会使用所有参数。如果同时使用了@CacheResult和 @CacheRemove注解的cacheKeyMethod方法指定缓存Key生成,那么该注解将不会起作用。