【SpringCloud组件学习笔记系列】(2)Hystrix组件

SpringCloud组件学习笔记系列

【SpringCloud组件学习笔记系列】(1)Eureka组件
【SpringCloud组件学习笔记系列】(2)Hystrix组件
【SpringCloud组件学习笔记系列】(3)OpenFeign组件
【SpringCloud组件学习笔记系列】(4)Gateway组件
【SpringCloud组件学习笔记系列】(5)Config组件

完整代码已在Github开源:
https://github.com/Aliang99/SpringCloud_Bill

2、SpringCloud Netflix Hystrix的使用以及讲解

Hystirx的作用主要有:服务降级、服务熔断

服务器支持的线程并发数有限,请求会一直阻塞,会导致服务器资源耗尽,从而致使所有服务都不可用,形成雪崩效应

hystrix解决雪崩问题的手段,主要有:线程隔离、服务降级、服务熔断

hystrix会为每一个依赖服务调用分配一个小的线程池,如果线程池已满,调用将被立即拒绝。

默认不采用排队,加速失败判定时间,减少请求的等待时间。

用户的请求,将不再直接访问服务,而是通过线程池中的空闲线程来访问服务,如果线程池已满,或者请求超时,则会进行服务降级处理,服务降级可以优先保证核心服务正常运行。

用户的请求故障时,不会被阻塞,更不会无休止的等待或者看到系统崩溃,至少可以看到一个执行结果,比如友好的提示信息。

服务降级虽然会导致请求失败,但是不会导致阻塞,而且最多会影响这个依赖服务对应的线程池中的资源,对其它服务没有响应。

触发服务降级的情况分为:线程池已满、请求超时

2.1、Hystrix的使用

2.1.1、导入依赖

在需要远程调用的服务模块中导入Hystrix依赖,即消费者微服务中。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2.1.2、添加注解

在启动类上,添加@EnableCircuitBreaker 注解,开启熔断

@SpringBootApplication
@EnableDiscoveryClient //开启Eureka客户端发现
@EnableCircuitBreaker // 开启熔断
public class SpringCloud_Consumer_80_Application {

    public static void main(String[] args) {
        SpringApplication.run(SpringCloud_Consumer_80_Application.class,args);
    }
    /**
     * 创建远程调用模板对象
     * @return
     */
    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}
2.1.3、@SpringCloudApplication注解

一般的,可以使用**@SpringCloudApplication** 注解替代以上的三个注解,即如下方式

@SpringCloudApplication // 该注解为组合注解,包含@SpringBootApplication、@EnableDiscoveryClient以及@EnableCircuitBreaker三个注解
public class SpringCloud_Consumer_80_Application {
    public static void main(String[] args) {
        SpringApplication.run(SpringCloud_Consumer_80_Application.class,args);
    }
    /**
     * 创建远程调用模板对象
     * @return
     */
    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
 }

2.2、编写服务降级

当目标服务的调用出现故障,我们希望快速失败,给用户一个友好的提示,因此需要提前编写好失败时的降级处理逻辑,需要用到**@HystrixCommand**来完成。

实现示例:

@RestController
@RequestMapping("consumer")
public class UserController {
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private DiscoveryClient discoveryClient;

    @GetMapping("queryById/{id}")
    @HystrixCommand(fallbackMethod = "queryByIdFallback") // 声明服务降级的处理方法
    public CommonVo<User> queryById(@PathVariable("id") Long id){
        ServiceInstance serviceInstance = discoveryClient.getInstances("user-service").get(0);
        String hostName = serviceInstance.getHost(); 
        int hostPort = serviceInstance.getPort(); 
        String url = "http://"+hostName+":"+hostPort; 
        CommonVo<User> resp = restTemplate.getForObject(url + "/user/queryById/" + id, CommonVo.class);
        return resp;
    }
		
  	//服务降级的方法,返回提示信息
    public CommonVo<User> queryByIdFallback(Long id){
        return new CommonVo<>(400,"抱歉,网络拥堵,请稍后再试!!!",null);
    }
}

留意带有注释的地方。

@HystrixCommand(fallbackMethod = “queryByIdFallback”) // 声明服务降级的处理方法

注意:

熔断的降级逻辑方法 必须和正常逻辑方法的参数列表和返回值类型一致。

2.3、测试案例

2.3.1、启动微服务

image-20220119145735760

2.3.2、访问controller

正常显示查询数据

image-20220119145808363

2.3.3、停止8001

模拟请求失败的场景

image-20220119145903361

2.3.4、再次访问

服务发生降级,调用了降级处理方法响应请求

image-20220119145924661

2.4、默认的Fallback方法

@RestController
@RequestMapping("consumer")
@DefaultProperties(defaultFallback = "defaultFallback") //指定默认服务降级方法
public class UserController {
    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;

    @GetMapping("queryById/{id}")
		//@HystrixCommand(fallbackMethod = "queryByIdFallback") // 声明服务降级的处理方法
    @HystrixCommand // 指定了默认的服务降级方法,这里就不需要再指定了
    public CommonVo<User> queryById(@PathVariable("id") Long id){
        ServiceInstance serviceInstance = discoveryClient.getInstances("User-Service").get(0);
        String hostName = serviceInstance.getHost(); 
        int hostPort = serviceInstance.getPort();
        String url = "http://"+hostName+":"+hostPort;
        CommonVo<User> resp = restTemplate.getForObject(url + "/user/queryById/" + id, CommonVo.class);
        return resp;
    }
    //服务降级的方法,返回提示信息
    public CommonVo<User> queryByIdFallback(Long id){
        return new CommonVo<>(400,"抱歉,网络拥堵,请稍后再试!!!",null);
    }

    //默认服务降级方法
    public CommonVo<User> defaultFallback(){
        return new CommonVo<>(400,"中国移动提醒您,你请求的服务太拥堵,请稍后再试",null);
    }
}

注意:

  • 在controller上添加@DefaultProperties,并指定该注解的属性defaultFallback的值为默认服务降级方法名
  • 注释掉原来的//@HystrixCommand(fallbackMethod = “queryByIdFallback”) // 声明服务降级的处理方法
  • 但依然需要添加 @HystrixCommand,表示该方法需要Hystrix提供服务降级功能
  • 编写默认服务降级方法
  • 被@DefaultProperties修饰的Controller的所有方法的返回值类型必须要与defaultFallback的返回值类型一致。参数可以不一致。

2.5、超时设置

默认情况下,请求超时1秒后,会触发服务降级,这个时间可以在配置文件中进行修改。

hystrix: 
	command: 
		default: 
			execution: 
				isolation: 
					thread: 
						timeoutInMilliseconds: 2000 # 单位是ms 默认请求超时时间是1000ms

这个值会作用于全局所有方法。

2.6、测试超时设置

2.6.1、修改配置文件

将上面的超时设置加入到consumer的配置文件中

2.6.2、修改Controller

修改consumer调用的服务型微服务的controller,模拟超时2秒的场景,让它睡两秒即可

@GetMapping("queryById/{id}")
public CommonVo<User> queryById(@PathVariable("id") Long id) {
    try {
      	Thread.sleep(2000); //睡眠2秒
    } catch (InterruptedException e) {
      	e.printStackTrace();
    }
    User user = userService.queryById(id);
    if (user==null){
      	return new CommonVo<>(400,"数据库中暂无此数据",null);
    }else{
      	return new CommonVo<User>(200,"OK",user);
    }
}
2.6.3、启动服务
2.6.4、访问

image-20220119154332800

2.7、服务熔断

在分布式系统中应用服务熔断,服务调用方可以自己进行判断哪些服务反应慢或存在大量超时,可以针对这些服务进行主动熔断,防止整个系统被拖垮。

Hystrix的熔断机制,可以实现弹性容错;当服务请求情况好转之后,自动重连。服务无法响应时,通过断路的方式,将后续请求直接拒绝,一段时间(默认5秒)后,允许部分请求通过,如果这部分请求能调用成功,则回到断路器关闭状态正常接收所有服务请求,否则继续打开,拒绝所有服务请求。

熔断器的三个状态:关闭(默认)、开启、半开

2.7.1、服务熔断器的执行过程

熔断器的执行过程:

1、默认是关闭的状态

2、当失败的请求数量达到了阈值**(请求次数20次以上,其中失败的请求达到50%以上)**,熔断器会打开,将服务降级,当前服务拒绝所有请求

3、熔断器开启5秒之后,熔断器自动变成半开状态,半开状态下,允许部分请求访问,如果能够正常访问,就进入关闭状态,如果不能,就又进入开启状态,等再过5秒,又变成半开状态,一次又一次的尝试。

4、自动打开、自动重连、自动关闭

2.7.2、测试熔断器的现象
2.7.2.1、修改consumer的controller
@RestController
@RequestMapping("consumer")
@DefaultProperties(defaultFallback = "defaultFallback") //指定默认服务降级方法
public class UserController {
    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;

    @GetMapping("queryById/{id}")
    @HystrixCommand
    public CommonVo<User> queryById(@PathVariable("id") Long id){
			 // 添加判断,每次请求参数为1 ,都抛出异常,表示请求失败	
        if (id == 1L){
            throw new RuntimeException("太忙了"); //注意这部分
        }
        ServiceInstance serviceInstance = discoveryClient.getInstances("User-Service").get(0);
        String hostName = serviceInstance.getHost(); // 获取主机名称
        int hostPort = serviceInstance.getPort(); //获取端口
        String url = "http://"+hostName+":"+hostPort; //拼接远程调用地址
        CommonVo<User> resp = restTemplate.getForObject(url + "/user/queryById/" + id, CommonVo.class);
        return resp;
    }

    //默认服务降级方法
    public CommonVo<User> defaultFallback(){
        return new CommonVo<>(400,"中国移动提醒您,你请求的服务太拥堵,请稍后再试",null);
    }
}
2.7.2.2、重启微服务
2.7.2.3、测试请求

先将参数为1的请求,请求20次,由于测试代码中的if,会导致服务降级,失败20次,此时Hystrix便会开启熔断器

image-20220119193222073

熔断器开启的5s内接着再请求相同地址,携带参数为2的请求,会发现,无法访问,也出现了服务降级

image-20220119193157467

5s后再访问,可以正常访问,因为此时熔断器已经进入了半开状态,允许部分访问。

注意:

熔断器从开启状态到半开状态这段时间默认5s。即5s后会重新连接,并等待下一次请求,如果请求能通过,则从半开状态变为关闭状态。否则又进入开启与半开的循环。

image-20220119192103189

当参数为2的请求访问成功后,熔断器会进入关闭状态,此时所有请求都可以访问。

**注意:**以上测试为了模拟熔断器开启的场景,代码中写死了错误,所以再次访问参数1,依旧是无法访问的,始终抛出异常进入默认的服务降级处理。

2.7.3、服务熔断的参数

如下:

hystrix: 
	command: 
		default: 
			execution: 
				isolation: 
					thread: 
						timeoutInMilliseconds: 2000 #服务降级超时时间 
       circuitBreaker: 
       	 errorThresholdPercentage: 50 # 触发熔断错误比例阈值,默认值50% 
       	 sleepWindowInMilliseconds: 10000 # 熔断后休眠时长,默认值5秒 
       	 requestVolumeThreshold: 10 # 熔断触发最小请求次数,默认值是20次

参数的设置项,可以参考HystrixCommandProperties类。

image-20220119194249345

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值