概述
文章目录
- 雪崩问题
- Hystrix解决雪崩问题
- 开启Hystrix
- 环境准备
- controller改写
- 测试
雪崩问题
微服务中,服务间调用关系错综复杂,一个请求,可能需要调用多个微服务接口才能实现,会形成非常复杂的调用链路:
如图,一次业务请求,需要调用A、P、 H、I 四个服务,这四个服务又可能调用其它服务。如果此时,某个服务出现问题。例如微服务 I 发生异常,请求阻塞,用户不会得到响应,则tomcat的这个线程不会释放,于是越来越多的用户请求到来,越来越多的线程会阻塞:
服务器支持的线程和并发数有限,请求一直阻塞, 会导致服务器资源耗尽,从而导致所有其它服务都不可用,形成雪崩效应。
这就好比,一个汽车生产线,生产不同的汽车,需要使用不同的零件,如果某个零件因为种种原因无法使用,那么就会造成整台车无法装配,陷入等待零件的状态,直到零件到位,才能继续组装。此时如果有很多 个车型都需要这个零件,那么整个工厂都将陷入等待的状态,导致所有生产都陷入瘫疾。一个零件的波及范围不断扩大。
Hystrix解决雪崩问题
Hystrix解决雪崩问题的手段有两个
- 线程隔离
- 服务熔断
- Hystrix为每个依赖服务调用分配一个小的线程池, 如果线程池已满调用将被立即拒绝,默认不采用排队加速失败判定时间。
用户的请求将不再直接访问服务,而是通过线程池中的空闲线程来访问服务,如果线程池已满,或者请求超时,则会进行降级处理,什么是服务降级? - 服务降级:优先保证核心服务,而非核心服务不可用或弱可用。
用户的请求故障时,不会被阻塞,更不会无休止的等待或者看到系統崩溃,至少可以看到一个执行结果(例如返回友好的提示信息:服务器正忙等)。
服务降级虽然会导致请求失败,但是不会导致阻塞,而且最多会影响这个依赖服务对应的线程池中的资源,对其它服务没有响应。 - 触发Hystix服务降级的情况:
线程池已满
请求超时
开启Hystrix
首先在做降级处理之前,应该明确是给那个服务降级,是服务的提供方还是消费方?一般情况是服务的消费方去调用服务的提供方的,服务的提供方出现问题,才会导致服务的消费方出现问题。所以应该是对服务的消费方进行服务的降级处理,例如在调用一个服务时,出现了问题,消费方可以快速的给用户处理响应或一个友好提示。
服务的消费方进行降级处理,不会让服务提供方的的错误影响自己错误,这样自己就不会出现错误了,当然用户在调用服务的消费方时就不会出现错误。
环境准备
<!--hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
启动类中,开启@EnableCircuitBreaker
功能
//@EnableCircuitBreaker
//@EnableDiscoveryClient
//@SpringBootApplication
@SpringCloudApplication
public class ConsumerApplication {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){return new RestTemplate();}
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class);
}
}
@SpringCloudApplication
注解源码
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}
controller改写
编写降级逻辑当目标服务的调用出现故障,我们希望快速失败,给用户一个友好提示。 因此需要提前编写好失败时的降级处理逻辑,要使用@HystixCommond
来完成:要注意,因为熔断的降级逻辑方法必须跟正常逻辑方法保证:相同的参数列表和返回值声的。返回User对象没有太大意义,一 般会返回友好提示。所以我们把findById
的方法改造为返回String
, 反正也是Json数据。这样失败逻辑中返回一个错误说明会比较方便。
@HystrixCommand(fallbackMethod = "findByIdFallback")
用来声明一一个降级逻辑的方法当user-service正常提供服务时,访问与以前一致。但是当我们将user-service停机时,会发现页面返回了降级处理
@RestController
@RequestMapping("/consumer")
@DefaultProperties(defaultFallback = "findByIdFallback")
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("{id")
//失败容错指令,开启服务降级线程隔离的处理,要求这两个方法返回值和参数列表必须相同,因为服务降级的处理逻辑必须和原因的处理保持一致
//@HystrixCommand(fallbackMethod = "findByIdFallback")
//不同接口不同方法的超时等待时长应该是不一样的,@HystrixCommand可以设置,配置在类上,则是此类的所有方法生效,要想全局起作用,那就在application.yml中配置
@HystrixCommand(fallbackMethod = "findByIdFallback",
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "2000")
})
public String findById(@PathVariable("id")Integer id){
String url="http://user-service/user/findById/"+id;
String user = restTemplate.getForObject(url, String.class);
return user;
}
public String findByIdFallback(Integer id){
return "不好意思!服务器正忙!!!!";
}
//默认fallback方法,不需要再有参数了
public String findByIdFallback(){
return "不好意思!服务器正忙!!!!";
}
}
application.yaml配置失败容错指令
# 配置全局等待超时时长为3秒,默认是1秒
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000
# 只针对某个服务或方法进行配置等待超时时长,这样就不用在方法中或类中配置
user-service:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000
默认配置如图所示,可以根据这个类进行自定义配置。
明确:线程隔离是在内部实现,内部已经利用线程池进行了处理,我们只需要去配置他的超时时长,并且开启他的功能即可。
测试
服务提供方user-service线程休眠,模拟线程出现异常。
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User findById(Integer id){
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}//模拟等待时长2秒
return userMapper.selectByPrimaryKey(id);
}
public List<User> findAll(){ return userMapper.selectAll(); }
}
启动服务,一切正常。
显示一个友好的提示信息。
最后
以上就是妩媚早晨为你收集整理的SpringCloud(三)Hystrix解决雪崩问题-服务降级雪崩问题Hystrix解决雪崩问题开启Hystrix测试的全部内容,希望文章能够帮你解决SpringCloud(三)Hystrix解决雪崩问题-服务降级雪崩问题Hystrix解决雪崩问题开启Hystrix测试所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复