服务间的隔离及断路器-Hystrix


服务降级是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心
任务的正常运行。
Hystrix主要是为了解决服务雪崩问题:

  1. 降级机制:当你的某一个服务出现超时时,资源不足,出现了异常,可以执行一个降级方法,返回一个托底数据
  2. 隔离:提供了一个Hystrix线程池,信号量,和tomcat的线程池相互隔离。
  3. 熔断:当你的某一个服务的失败率达到一定的阈值时,自动触发降级
  4. 缓存:请求缓存的功能
1、降级机制实现

导入依赖 customer

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

添加一个注解(启动类)

@EnableCircuitBreaker

针对某一个接口去编写他的降级方法

@GetMapping("/customer/{id}")
@HystrixCommand(fallbackMethod = "findByIdFallBack")
public Customer findById(@PathVariable Integer id){
    int i = 1/0;
    return searchClient.findById(id);
}

// findById的降级方法  方法的描述要和接口一致
public Customer findByIdFallBack(Integer id){
    return new Customer(-1,"",0);
} 

在接口上添加注解

@HystrixCommand(fallbackMethod = "findByIdFallBack")

2、线程隔离(线程池隔离,信号量)

如果使用Tomcat的线程池去接收用户的请求,使用当前线程去执行其他服务的功能,如果某一个服务出现了故障,导致tomcat的线程大量的堆积,导致Tomcat无法处理其他业务功能。

  • Hystrix的线程池(只要加上注解hystrixcommand默认),接收用户请求采用tomcat的线程池,执行业务代码,调用其他服务时,采用Hystrix的线程池。
  • 信号量,使用的还是Tomcat的线程池,帮助我们去管理Tomcat的线程池。

Hystrix的线程池的配置

配置信息namevalue
线程隔离策略execution.isolation.strategyTHREAD ,SEMAPHORE
指定超时时间execution.isolation.thread.timeoutInMilliseconds1000
是否开启超时时间配置execution.timeout.enabledtrue
超时之后是否中断线程execution.isolation.thread.interruptOnTimeouttrue
取消任务后知否execution.isolation.thread.interruptOnCancelfalse

代码实现

@GetMapping("/customer/{id}")
@HystrixCommand(fallbackMethod = "findByIdFallBack",commandProperties = {
        @HystrixProperty(name = "execution.isolation.strategy",value = "THREAD"),
        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
})
public Customer findById(@PathVariable Integer id) throws InterruptedException {
    System.out.println(Thread.currentThread().getName());
    Thread.sleep(300);
    return searchClient.findById(id);
}

信号量的配置信息

@GetMapping("/customer/{id}")
@HystrixCommand(fallbackMethod = "findByIdFallBack",commandProperties = {
        @HystrixProperty(name = "execution.isolation.strategy",value = "SEMAPHORE")
})
public Customer findById(@PathVariable Integer id) throws InterruptedException {
    System.out.println(Thread.currentThread().getName());
    return searchClient.findById(id);
}

3、断路器

3.1 断路器介绍

马丁福勒断路器论文:https://martinfowler.com/bliki/CircuitBreaker.html
在调用指定服务时,如果说这个服务的失败率达到你输入的一个阈值,将断路器从closed状态,转变为open状态,指定服务时无法被访问的,如果你访问就直接走fallback方法,在一定的时间内,open状态会再次转变为half open状态,允许一个请求发送到我的指定服务,如果成功,转变为closed,如果失败,服务再次转变为open状态,会再次循环到half open,直到断路器回到一个closed状态。

3.2 配置断路器的监控界面

导入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

在启动类中添加注解

@EnableHystrixDashboard

配置一个Servlet路径,指定上Hystrix的Servlet

@WebServlet("/hystrix.stream")
public class HystrixServlet extends HystrixMetricsStreamServlet {
}

//------------------------------------------------------------
// 在启动类上,添加扫描Servlet的注解
@ServletComponentScan("com.qf.servlet")

添加yml文件配置

hystrix:
  dashboard:
    proxy-stream-allow-list: "localhost"

测试直接访问http://host:port/hystrix

在当前位置输入映射好的servlet路径

3.3 配置断路器的属性

断路器的属性(默认10s秒中之内请求数)

配置信息namevalue
断路器的开关circuitBreaker.enabledtrue
失败阈值的总请求数circuitBreaker.requestVolumeThreshold20
请求总数失败率达到%多少时circuitBreaker.errorThresholdPercentage50
断路器open状态后,多少秒是拒绝请求的circuitBreaker.sleepWindowInMilliseconds5000
强制让服务拒绝请求circuitBreaker.forceOpenfalse
强制让服务接收请求circuitBreaker.forceClosedfalse

具体配置方式

@GetMapping("/customer/{id}")
@HystrixCommand(fallbackMethod = "findByIdFallBack",commandProperties = {
    @HystrixProperty(name = "circuitBreaker.enabled",value = "true"),
    @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),
    @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "70"),
    @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "5000")
})

4 请求缓存

4.1 请求缓存介绍 相当于我们的学习的mybatis session 缓存
  • 请求缓存的声明周期是一次请求
  • 请求缓存是缓存当前线程中的一个方法,将方法参数作为key,方法的返回结果作为value
  • 在一次请求中,目标方法被调用过一次,以后就都会被缓存。


4.2 请求缓存的实现

创建一个Service,在Service中调用Search服务。

@Service
public class CustomerService {

    @Autowired
    private SearchClient searchClient;


    @CacheResult
    @HystrixCommand(commandKey = "findById")
    public Customer findById(@CacheKey Integer id) throws InterruptedException {
        return searchClient.findById(id);
    }

    @CacheRemove(commandKey = "findById")
    @HystrixCommand
    public void clearFindById(@CacheKey Integer id){
        System.out.println("findById被清空");
    }

}

使用请求缓存的注解
@CacheResult:帮助我们缓存当前方法的返回结果(必须@HystrixCommand配合使用)
@CacheRemove:帮助我们清楚某一个缓存信息(基于commandKey)
@CacheKey:指定哪个方法参数作为缓存的标识

编写Filter,去构建HystrixRequestContext

@WebFilter("/*")
public class HystrixRequestContextInitFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HystrixRequestContext.initializeContext();
        filterChain.doFilter(servletRequest,servletResponse);
    }
}

修改Controller

public Customer findById(@PathVariable Integer id) throws InterruptedException {
    System.out.println(customerService.findById(id));
    System.out.println(customerService.findById(id));
    customerService.clearFindById(id);
    System.out.println(customerService.findById(id));
    System.out.println(customerService.findById(id));
    return searchClient.findById(id);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值