Hystrix
- 搭建项目
- 服务降级
- 服务熔断
- 请求合并
- 如何和Feign一起使用
搭建项目
–|eureka-registry --注册中心
–|hystrix-service – 调用用户服务
–|user-service --用户服务
- hystrix-service
server:
port: 9002
spring:
application:
name: hystrix-service
eureka:
instance:
hostname: 127.0.0.1
client:
register-with-eureka: true #默认值是true,是否将自己注册到注册中心
fetch-registry: true #默认值是true,是否从注册中心拉取服务
service-url: #注册中信对外暴露的注册中心地址
defaultZone: http://localhost:8761/eureka/
feign:
hystrix:
enabled: true #在Feign中开启Hystrix
- user-service
server:
port: 9001
spring:
application:
name: user-service
datasource: # 数据源
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/springcloud?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: root
password: root
eureka:
instance:
hostname: 127.0.0.1
client:
register-with-eureka: true #默认值是true,是否将自己注册到注册中心
fetch-registry: false # 默认值是true,是否从注册中心拉取服务
service-url: #注册中信对外暴露的注册中心地址
defaultZone: http://localhost:8761/eureka/
服务降级
- 在 pom.xml 文件中引入hystrix的起步依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
- 在应用的启动类上使用@EnableCircuitBreaker开启hystrix的功能
@SpringBootApplication
@EnableCircuitBreaker
@MapperScan("user.service.provider.mapper")
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
- 使用注解 @HystrixCommand 标记调用失败时需要熔断的方法,fallbackMethod 属性指定降级方法,注意:指定的降级方法需要和降级方法相同入参
@RestController
@RequestMapping(value = "/user")
public class UserController {
@Autowired
private UserMapper userMapper;
/*
* 查询所有用户信息
* 当该方法出现异常等信息,会返回兜底数据,
* 不会直接将错误信息返回,导致服务不可用
*/
@GetMapping(value = "/selectUserInfo")
@HystrixCommand(fallbackMethod = "fallbackMethod")
public List<UserInfo> selectUserInfo() {
//int i = 1/0;
return userMapper.selectAll();
}
/**
* 兜底数据
*/
public List<UserInfo> fallbackMethod(){
List<UserInfo> list = new ArrayList<>();
UserInfo userInfo = new UserInfo();
userInfo.setName("兜底数据");
userInfo.setAge(20);
userInfo.setAddress("兜底数据");
list.add(userInfo);
return list;
}
}
服务熔断
- 服务熔断就是,当在单位时间内触发了超过N次服务降级,并且服务降级占比超过阈值之后,就会触发服务熔断。当服务过来的时候,直接拒绝尝试服务调用,直接让服务降级处理。之后再慢慢尝试恢复。就相当于家里面的电路熔断器,当电流超负荷时,熔断器就会起作用烧断保险丝,将电停掉,导致全家断点
@HystrixCommand(fallbackMethod = "hystrixMethod",commandProperties = {
//是否开启断路器
@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
//请求次数,默认20次
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "2"),
//时间窗口期,默认5s
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000"),
//失败率达到多少后跳闸,默认50%
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),
})
@GetMapping(value = "/selectUserInfoByName")
public UserInfo selectUserInfoByName(@RequestParam("name") String name){
UserInfo userInfo = userMapper.selectUserInfoByName(name);
if (null == userInfo){
throw new RuntimeException("用户信息为空");
}
return userInfo;
}
/**
* 兜底数据
*/
public UserInfo hystrixMethod(String name){
UserInfo userInfo = new UserInfo();
userInfo.setName(name + "托底用户");
userInfo.setAge(20);
userInfo.setAddress("杭州市");
return userInfo;
}
请求合并
- 请求合并:是将在指定的时间内的请求或者是指定时间内请求达到设置值,将多次请求合并为一次请求
@HystrixCollapser(
batchMethod = "selectUserByListId",
scope = com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL,
collapserProperties = {
//隔离多久会进行请求合并,默认10ms
@HystrixProperty(name = "timerDelayInMilliseconds", value = "5000"),
//最大请求条数
@HystrixProperty(name = "maxRequestsInBatch", value = "2")
})
@GetMapping(value = "/selectUserInfoById")
public UserInfo selectUserInfoById(@RequestParam("id") Integer id) {
return userMapper.selectUserInfoById(id);
}
/**
* 处理合并后的请求方法
*/
@HystrixCommand
public List<UserInfo> selectUserByListId(List<Integer> ids) {
System.out.println("请求合并入参:" + ids);
ArrayList<UserInfo> list = new ArrayList<>();
for (Integer id : ids) {
UserInfo userInfo = userMapper.selectUserInfoById(id);
list.add(userInfo);
}
System.out.println("请求合并处理结果:" + list);
return list;
}
如何和Feign一起使用
- 上面的例子中,都是在服务端做的,消费者是通过feign远程调用,那如何实现,首先需要在配置文件中开启,hystrix-service模块的配置文件
feign:
hystrix:
enabled: true #在Feign中开启Hystrix
- Feign的远程调用接口,就是调用user-service服务
@FeignClient(name = "user-service", fallback = UserFallBackService.class)
public interface UserServiceApi {
@GetMapping(value = "user/selectUserInfo")
List<UserInfo> selectUserInfo();
@GetMapping(value = "user/selectUserInfoByName")
UserInfo selectUserInfoByName(@RequestParam("name") String name);
@GetMapping(value = "user/selectUserInfoById")
UserInfo selectUserInfoById(@RequestParam("id") Integer id);
}
- 针对Feign接口,需要写一个实现类,上面feignClient注解中的fallback对应的就是该实现类
@Component
public class UserFallBackService implements UserServiceApi{
@Override
public List<UserInfo> selectUserInfo() {
ArrayList<UserInfo> userInfos = new ArrayList<>();
UserInfo userInfo = new UserInfo();
userInfo.setName("托底用户");
userInfo.setAge(20);
userInfo.setAddress("杭州市");
userInfos.add(userInfo);
return userInfos;
}
@Override
public UserInfo selectUserInfoByName(String name) {
UserInfo userInfo = new UserInfo();
userInfo.setName(name + "托底用户");
userInfo.setAge(20);
userInfo.setAddress("杭州市");
return userInfo;
}
@Override
public UserInfo selectUserInfoById(Integer id) {
UserInfo userInfo = new UserInfo();
userInfo.setName("托底用户");
userInfo.setAge(20);
userInfo.setAddress("杭州市");
return userInfo;
}