Hystrix [hɪst'rɪks],中文含义是豪猪,因其背上长满棘刺,从而拥有了自我保护的能力。本文所说的Hystrix是Netflix开源的一款容错框架,同样具有自我保护能力。
一、Hystrix简介
Hystrix是由Netflix开源的一个延迟和容错库,用于隔离访问远程系统、服务或者第三方库,防止级联失败,从而提升系统的可用性、容错性与局部应用的弹性,是一个实现了超时机制和断路器模式的工具类库。
二、Hystrix的设计原则
三、Hystrix的工作原理
四、Ribbon中使用熔断器
a.引入依赖
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-hystrix'
b.添加注解(@EnableHystrix)
@SpringBootApplication
@EnableEurekaClient
@EnableHystrix //开启hystrix功能
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
c.编写代码(直接采用最简单的RestTemplate)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("/hystrix")
public class HystrixController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping("info")
public String test2() {
return restTemplate.getForObject("http://CLIENT-SERVICE/order/info", String.class);
}
}
//订单信息模块返回
@RestController
@RequestMapping("/order")
public class OrderController {
private Log LOGGER = LogFactory.getLog(OrderController.class);
@GetMapping("/info")
public String test(HttpServletRequest request) {
LOGGER.info("address:" + request.getRemoteAddr());
return "来自订单模块的信息返回:服务端口是9005,调用者的IP来自" + request.getRemoteAddr();
}
}
正常访问的结果:
d.@HystrixCommand,属性fallbackMethod是熔断时返回的方法。
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("/hystrix")
public class HystrixController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping("info")
@HystrixCommand(fallbackMethod="getDefaultMethod")
public String test2() {
return restTemplate.getForObject("http://CLIENT-SERVICE/order/info", String.class);
}
public String getDefaultMethod() {
return "this is the hystrix default method";
}
}
关闭订单的服务的返回结果是:
五、参数详解之@HystrixCommand
@HystrixCommand不但可以在方法,也可以直接使用在类上面,并且参数对于超时等等可以进行配置,当然也可以直接进行配置文件进行配置。
a.@DefaultProperties()和@HystrixCommand进行配套使用,进行类全局配置使用。
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("/hystrix")
@DefaultProperties(defaultFallback = "calssDefaultFallBack")
public class HystrixController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping("info")
//@HystrixCommand(fallbackMethod="getDefaultMethod")
@HystrixCommand
public String test2() {
return restTemplate.getForObject("http://CLIENT-SERVICE/order/info", String.class);
}
public String getDefaultMethod() {
return "this is the hystrix default method";
}
public String calssDefaultFallBack() {
return "this is the hystrix class default method";
}
}
HystrixCommandProperties定义参数类的了解,在Hystrix配置的项都在这个类里面,并且有许多的缺省项。
b.超时问题
在Order模块添加睡眠时间为2s
@RestController
@RequestMapping("/order")
public class OrderController {
private Log LOGGER = LogFactory.getLog(OrderController.class);
@GetMapping("/info")
public String test(HttpServletRequest request) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
LOGGER.info("address:" + request.getRemoteAddr());
return "来自订单模块的信息返回:服务端口是9005,调用者的IP来自" + request.getRemoteAddr();
}
}
进行请求发送,结果是返回默认方法
可以直接从HystrixCommandProperties类中看到,默认时间是1s,所以出现服务降级了。
private static final Integer default_executionTimeoutInMilliseconds = 1000; // default => executionTimeoutInMilliseconds: 1000 = 1 second
进行配置,就可以正常访问
@HystrixCommand(commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
})
c.断路器模式配置
private final HystrixProperty circuitBreakerRequestVolumeThreshold; // number of requests that must be made within a statisticalWindow before open/close decisions are made using stats
private final HystrixProperty circuitBreakerSleepWindowInMilliseconds; // milliseconds after tripping circuit before allowing retry
private final HystrixProperty circuitBreakerEnabled; // Whether circuit breaker should be enabled.
private final HystrixProperty circuitBreakerErrorThresholdPercentage; // % of 'marks' that must be failed to trip the circuit
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("/hystrix")
@DefaultProperties(defaultFallback = "calssDefaultFallBack")
public class HystrixController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping("info")
//@HystrixCommand(fallbackMethod="getDefaultMethod")
@HystrixCommand(commandProperties = {
@HystrixProperty(name = "circuitBreaker.enabled", value = "true"), //设置熔断
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),//断路器的最小请求数
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"),//时间窗口
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60")//错误百分比条件
})
public String test2(@RequestParam("number") Integer number) {
if (number % 2 == 0) {
return "success";
}
return restTemplate.getForObject("http://CLIENT-SERVICE/order/info", String.class);
}
public String getDefaultMethod() {
return "this is the hystrix default method";
}
public String calssDefaultFallBack() {
return "this is the hystrix class default method";
}
}
当错误率在一定时间范围内达到一定的比例是会出现这样的结果,这就是断路器的作用了
在配置文件配置这些也是一样的
六、Feign中使用熔断器
# feign熔断器开关
feign:
hystrix:
enabled: true
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient(name = "CLIENT-SERVICE",fallback = IClientServiceImpl.class)//服务名称
public interface ClientService {
//请求方式 和 请求地址
@GetMapping("/order/info")
String getOrderInfo();
}
@Component//@todo 注解不可少
public class IClientServiceImpl implements ClientService{
@Override
public String getOrderInfo() {
return "this is the feign default method";
}
}
import com.example.demo.client.ClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/test")
public class FeignController {
@Autowired
private ClientService clientService;
@RequestMapping("/orderInfo")
public String test() {
return clientService.getOrderInfo();
}
}
@FeignClient注解参数说明:
name:指定FeignClient的名称,如果项目使用了Ribbon,name属性会作为微服务的名称,用于服务发现。
fallback: 定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口。
fallbackFactory: 工厂类,用于生成fallback类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码
path: 定义当前FeignClient的统一前缀,类似于注解到类上的@RequestMapping的功能
停掉order服务,打开浏览器访问http://localhost:8080/test/orderInfo,服务正常,截图如下:
七、可视化界面的使用
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-hystrix-dashboard'
在程序的启动类上加上@EnableHystrixDashboard注解,开启Hystrix Dashboard的功能,2.x的版本有一些区别,需要额外配置这里就不在赘述。
在浏览器上访问http://127.0.0.1:8080/hystrix,浏览器显示的界面如下图所示: