Hystrix服务保护框架

Hystrix简介

基于Hystrix解决服务雪崩效应原理:

  1. 服务降级:在高并发情况下防止一直等待,而使用降级的方式(返回一个友好提示给客户端,不会去处理请求,调用fallBack本地方法),在tomcat没有线程处理请求的时候,不应该让用户一直等待。目的是为了用户体验。
  2. 服务熔断:目的为了保护服务。在高并发情况下,如果请求达到一定极限(可以自己设置阈值),如果流量超出了设置的阈值,自动开启服务保护功能,使用服务降级方式返回一个友好提示。服务熔断和服务降级一般是一起使用的
  3. 服务隔离:线程池隔离和信号量隔离。每个服务接口有自己独立的线程池,每个线程池互不影响,缺点CPU占用率非常高。不是所有的接口都采用线程隔离,核心关键接口隔离

依赖

springcloud-parent 中引入 pom依赖:



 org.springframework.cloud
 spring-cloud-starter-netflix-hystrix

image.png

springcloud-api-order-service-impl 中开启断路器

####开启hystrix断路器
feign:
  hystrix:
    enabled: true  # 在feign中开启 hystrix

image.png

Feign 调用同一个接口模拟雪崩效应,一个是没加了 @HystrixCommand 注解的,一个是加了 @HystrixCommand 注解的。并创建一个方法,验证开启 @HystrixCommand 注解会 默认开启:

  1. 默认开启服务隔离,以线程池隔离方式
  2. 默认开启服务降级执行方法
  3. 默认开启服务服务熔断机制
package com.baba.api.service.impl;
import com.baba.api.entity.UserEntity;
import com.baba.api.feign.MemberServiceFeign;
import com.baba.api.service.IOrderService;
import com.baba.wlb.base.BaseResponse;
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;
/**
 * @Author wulongbo
 * @Date 2021/1/22 13:51
 * @Version 1.0
 */
@RestController
public class OrderServiceImpl implements IOrderService {
    //订单服务集成会员服务接口,用来实现feign 客户端 减少接口重复代码
 @Autowired
 private MemberServiceFeign memberServiceFeign;
 @Override
 @RequestMapping("/getOrderByMember")
    public String getOrderByMember(String name) {
        UserEntity userEntity = memberServiceFeign.getMember(name);
 return userEntity == null ? "没有找到用户信息!" : userEntity.toString();
 }
    // 没有解决服务雪崩效应
 @Override
 @RequestMapping("/getUserInfoByMember")
    public BaseResponse getUserInfoByMember() {
        return memberServiceFeign.getUserInfo();
 }
    // 解决服务雪崩效应
 /***
 * fallbackMethod 方法作用:服务降级执行。
 * @HystrixCommand 默认开启服务隔离,以线程池隔离方式
 * 默认开启服务降级执行方法 getUserInfoByMemberHystrixFallbackMethod
 * 默认开启服务服务熔断机制
 */
 @HystrixCommand(fallbackMethod = "getUserInfoByMemberHystrixFallbackMethod")
    @RequestMapping("/getUserInfoByMemberHystrix")
    public BaseResponse getUserInfoByMemberHystrix() {
        System.out.println("getUserInfoByMemberHystrix-->线程池名称:" + Thread.currentThread().getName());
 return memberServiceFeign.getUserInfo();
 }
    public BaseResponse getUserInfoByMemberHystrixFallbackMethod() {
        return new BaseResponse(500, "返回一个友好提示", "服务降级,服务器繁忙,请稍后重试!");
 }
    // 订单服务接口
 @Override
 @RequestMapping("/getOrderInfo")
    public String getOrderInfo() {
        System.out.println("getOrderInfo-->线程池名称:" + Thread.currentThread().getName());
 return "订单服务接口调用成功!";
 }
    // Hystrix有两种方式配置保护服务,通过注解和接口形式
}

IOrderService 接口类:

package com.baba.api.service;
import com.baba.wlb.base.BaseResponse;
import org.springframework.web.bind.annotation.RequestMapping;
/**
 * @Author wulongbo
 * @Date 2021/1/22 13:46
 * @Version 1.0
 */public interface IOrderService {
    // 订单服务调用会员服务接口 feign @RequestMapping("/getOrderByMember")
    String getOrderByMember(String name);
 // 订单服务调用会员服务接口 feign @RequestMapping("/getUserInfoByMember")
    BaseResponse getUserInfoByMember();
 // 订单服务调用会员服务接口 feign @RequestMapping("/getOrderInfo")
    String getOrderInfo();
}

启动测试

测试线程池隔离

依次启动 Eureka Server,Member 和 order 服务:
访问:http://localhost:8200/getUserInfoByMemberHystrixhttp://localhost:8200/getOrderInfo
image.png
image.png
image.png
证明 @HystrixCommand 注解会默认开启服务隔离,以线程池隔离方式。

测试服务熔断降级

打开测试工具,Apache JMeter,开200个线程,循环100组,测试20000个并发

访问http://localhost:8200/getUserInfoByMemberHystrix 接口测试
image.png

image.png
可以看到只执行了10次,默认并发请求数为10,说明服务熔断生效,而我们测试普通接口 http://localhost:8200/getOrderInfo
image.png
image.png
可以看到没有做降级处理。

浏览器测试熔断接口

现在我们使用浏览器访问 http://localhost:8200/getUserInfoByMemberHystrix
image.png
image.png
image.png
可以发现 Feign 客户端 getUserInfo()接口能访问到,但是走的是服务降级方法,原因是因为浏览器(默认1s,可以配置)在1s内没有拿到请求结果就会走服务降级方法(即响应时间,而非调用接口时间)。

解决方案,因为我们在会员接口设置了休眠时间,而我们 hystrix 是默认开启超时时间的,所以想要我们接口可以正常访问,需要关闭超时配置:

hystrix:
  command:
    default:
      execution:
        timeout:
          enabled:
            false

image.png

重启后再次访问 http://localhost:8200/getUserInfoByMemberHystrix
等待1.5s后,接口能够正常访问!
image.png
注意:这里只是演示效果,正常线上是一定要开始超时时间的

你可能感兴趣的:(javaspringboot)