hystrix使用
hystrix介绍
hystrix是什么
hystrix是springCloud的一个容错组件,是有Netflix提供的开源库。实现了超时机制和断路器模式。最新版本的springCloud 2020.0.x 已经不再使用Netflix的hystrix,不过旧版本没有修改,下面我用旧版本是Hoxton。
Netflix的hystrix功能
hystrix做事情就是保证服务之间调用的预防关联服务闪崩影响、可靠性、监控服务状态、调用失败(不可用服务)时提供友好的提示等就是解决服务之间调用问题。
1、保护机制:依赖的服务出现失败或者延迟就会为系统提供控制和保护。
2、预防雪崩:当大量请求过来时,会选择选择部分请求进行响应。
3、请求控制:通过HystrixCommand或HystrixObservableCommand对服务之间的依赖调用,创建一个新的线程进行调用,并且记录运行情况,进行响应处理。
4、熔断机制:如果服务的错误百分比超过阈值,则手动或自动触发断路器以在一段时间内停止对特定服务的所有请求。
5、资源隔离:为每个依赖项维护一个小的线程池(或信号量);如果它已满,则发往该依赖项的请求将立即被拒绝,不会进行排队。
6、快速失败:直接将请求返回标记失败。
7、监控:可以实时地监控指标和配置更改,方便监控、报警、运维控制。
8、回退机制:fallback和FallbackFactory 当请求失败、超时、被拒绝,或当断路器被打开时,执行回退逻辑。回退逻辑我们自定义,提供服务降级。
9、自我修复:断路器打开后可以进入“自动”状态,可以进行打开,关闭,半开状态的转换。
Netflix功能实现方式
依赖引入
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
直接调用
创建一个新的非阻塞线程,然后将具体业务放到新线程中执行。正常执行就不会触发,回调业务,如果一旦触发了规则就会执行回调。
package com.example.eureka_consumer2.controller.hystrix;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
/**
* 本地测试Hystrix主要执行方式
*
* 创建一个新的非阻塞线程,然后将具体业务放到新线程中执行
* 正常执行就不会触发,回调业务,如果一旦触发了规则就会执行回调。
* 规则:可以是异常可以请求时长,请求结果情况,可以响应时长
*/
public class Test extends HystrixCommand {
protected Test(HystrixCommandGroupKey group) {
super(group);
}
@Override
protected Object run() throws Exception {
System.out.println("业务执行");
int i = 1/0;
return null;
}
@Override
protected Object getFallback() {
System.out.println("失败回调");
return super.getFallback();
}
public static void main(String[] args) {
Future<String> futureResult = new Test(HystrixCommandGroupKey.Factory.asKey("ext")).queue();
String str;
try {
str = futureResult.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("程序执行完成");
}
}
Resttemplate请求
创建服务类
package com.example.eureka_consumer2.controller.hystrix.service;
public interface DemoService {
public String toUser();
}
package com.example.eureka_consumer2.controller.hystrix.service.Impl;
import com.example.eureka_consumer2.controller.hystrix.service.DemoService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class DemoServiceImpl implements DemoService {
@Autowired
private RestTemplate restTemplate;
@Override
@HystrixCommand(fallbackMethod="back")
public String toUser() {
String str = restTemplate.getForObject("http://user/toUser",String.class);
return str;
}
public String back(){
System.out.println("请求失败");
return "no back";
}
}
控制层调用
@Autowired
private DemoService demoService ;
@RequestMapping("/demo1")
public String demo1(){
String str = demoService.toUser();
System.out.println(str);
return str;
}
启动类添加
@EnableFeignClients
@EnableCircuitBreaker
public class EurekaConsumer2Application {}
Feign请求
添加配置
feign.hystrix.enabled=true
fallback方式
创建回调处理类
package com.example.common.hystrix.user;
import com.example.common.api.user.server.UserClient;
import org.springframework.stereotype.Component;
@Component
public class AliveBack implements UserClient {
@Override
public String userInfo(long userId) {
System.out.println("userInfo:触发hystrix的处理业务");
return "hystrix info";
}
@Override
public String toUser() {
System.out.println("toUser:触发hystrix的处理业务");
return "toUser";
}
}
@FeignClient注解中添加回调属性
package com.example.common.api.user.server;
import com.example.common.api.user.controller.UserApi;
import com.example.common.hystrix.user.ControllerError;
import org.springframework.cloud.openfeign.FeignClient;
@FeignClient(name="user" ,fallback = AliveBack.class)
public interface UserClient extends UserApi {
}
fallbackFactory方式
这种方式可以更加错误进行响应的业务处理,更新精准。
创建回调处理类
package com.example.common.hystrix.user;
import com.example.common.api.user.server.UserClient;
import feign.FeignException;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class ControllerError implements FallbackFactory<UserClient> {
@Override
public UserClient create(Throwable cause) {
return new UserClient(){
@Override
public String userInfo(long userId) {
return null;
}
@Override
public String toUser() {
System.out.println(cause);
if(cause instanceof IOException){
System.out.println("IOException:流异常");
return "IOException";
}else if(cause instanceof FeignException.InternalServerError){
System.out.println("InternalServerError:远程服务报错");
return "InternalServerError";
}else if(cause instanceof RuntimeException){
System.out.println("RuntimeException:请求时异常");
return "RuntimeException";
}else if(cause instanceof Exception){
System.out.println("Exception:异常");
return "Exception";
}
System.out.println("OK");
return "OK";
}
};
}
}
@FeignClient注解中添加回调属性
package com.example.common.api.user.server;
import com.example.common.api.user.controller.UserApi;
import com.example.common.hystrix.user.ControllerError;
import org.springframework.cloud.openfeign.FeignClient;
@FeignClient(name="user",fallbackFactory = ControllerError.class)
public interface UserClient extends UserApi {
}
信号量隔离与线程隔离
线程池隔离:Hystrix自己根据服务设置线程池,每个服务对应线程洗对应有限的线程数,防止调用某个服务大量消耗线程导致其他服务没有线程用,所有对服务划分线程池。
信号量隔离:使用tomcat创建的线程去调用依赖的服务,只需要维护tomcat的线程就可以了,不需要消耗线程池,更加轻量级,但是tomcat线程数量有限,需要快速连接快速释放,比较适合无网络内部调用。
#隔离策略,默认是Thread, 可选Thread|Semaphore
#thread 通过线程数量来限制并发请求数,可以提供额外的保护,但有一定的延迟。一般用于网络调用
#semaphore 通过semaphore count来限制并发请求数,适用于无网络的高并发请求
hystrix.command.default.execution.isolation.strategy=SEMAPHORE
#命令执行超时时间,默认1000ms
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=2000
#执行是否启用超时,默认启用true
hystrix.command.default.execution.timeout.enabled=true
#发生超时是是否中断,默认true
hystrix.command.default.execution.isolation.thread.interruptOnTimeout=true
#最大并发请求数,默认10,该参数当使用ExecutionIsolationStrategy.SEMAPHORE策略时才有效。
# 如果达到最大并发请求数,请求会被拒绝。
# 理论上选择semaphore size的原则和选择thread size一致,
# 但选用semaphore时每次执行的单元要比较小且执行速度快(ms级别),否则的话应该用thread。
# semaphore应该占整个容器(tomcat)的线程池的一小部分。
hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests=10
因为上面配置文件是没有提示,只能是手写,注意不要写错了。
源码中配置文件加载
hystrix.command.default
hystrix.command.
hystrix配置方式
官方文档中有说明可以,参考官网。
内置全局默认值
就是什么都不用配置自动加载默认值。
动态全局默认属性
就是不指明实例,直接配置全局。
hystrix.command.default.execution.isolation.strategy=SEMAPHORE
实例属性
针对每个服务业务调用设置,也是设置最小粒度。
hystrix.command.UserClient#toUser().execution.isolation.strategy=SEMAPHORE
默认设置
直接在业务方法上添加注解,@HystrixProperty设置属性。
package com.example.common.api.user.controller;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
public interface UserApi {
@RequestMapping("/userInfo")
@HystrixProperty(name="execution.isolation.strategy",value = "SEMAPHORE")
public String userInfo(@RequestBody long userId);
@RequestMapping("/toUser")
public String toUser();
}
开启dashboard
dashboard是方便开发运维人员查看页面功能。
添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
启动添加@EnableHystrixDashboard
@SpringBootApplication
@EnableFeignClients
@EnableCircuitBreaker
@EnableHystrixDashboard
public class EurekaConsumer2Application {}
健康信息查看:http://desktop-9f2ojrc:9001/actuator/hystrix.stream
图形化界面:http://desktop-9f2ojrc:9001/hystrix
再调用接口的接口情况就可以被监控到了。
代码地址
https://gitee.com/zhang798/spring-cloud/tree/hystrix
分支:hystrix
git clone https://gitee.com/zhang798/spring-cloud.git -b hystrix