Hystrix

在分布式系统中,单个应用通常会有多个不同类型的外部依赖服务,内部通常依赖于各种RPC服务,外部则依赖于各种HTTP服务。这些依赖服务不可避免的会出现调用失败,比如超时、异常等情况,如何在外部依赖出问题的情况,仍然保证自身应用的稳定,就是Hystrix这类服务保障框架的工作了。常见的服务依赖如下图所示,应用X依赖于服务A、B和C,A和B正常提供服务,C服务出错,这是如何避免C服务对A、B服务产生影响,也引出了一个隔离的概念。

服务熔断:

熔断机制是应对服务雪崩效应的一种微服务链路保护机制,当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回”错误”的响应信息。当检测到该节点微服务响应正常后恢复调用链路,在SpringCloud框架机制通过Hystrix实现,Hystrix会监控微服务见调用的状况,当失败的调用到一个阈值,缺省是5秒内20次调用失败就会启动熔断机制,熔断机制的注解是**@HystrixCommand**

在分布式的环境或者微服务中,不可避免的会出现一些错误,一个服务的失败或许会导致整个项目的失败。而Hystrix是一个库,它可以通过添加容错逻辑来保护或者控制你的分布式服务之间的交互。Hystrix通过隔离服务之间的访问点,阻止它们之间的级联故障以及提供后备选项来实现这一目标,所有这些都可以提高系统的整体弹性。

分布式系统环境下,服务间类似依赖非常常见,一个业务调用通常依赖多个基础服务。如下图,对于同步调用,当库存服务不可用时,商品服务请求线程被阻塞,当有大批量请求调用库存服务时,最终可能导致整个商品服务资源耗尽,无法继续对外提供服务。并且这种不可用可能沿请求调用链向上传递,这种现象被称为雪崩效应。

img

服务熔断使用在服务端;provider-8001

试用hystrix

添加依赖

1
2
3
4
5
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>

编写一个方法,当我们的原来的方法抛出异常的时候,就调用这个方法实现数据的输出,实现错误是后台的,但是前台该返回的还是一样的返回数据;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.saxon.springcloud.controller;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.saxon.springcloud.pojo.Dept;
import com.saxon.springcloud.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;



@RestController
public class DeptCotroller {
@Autowired
DeptService deptService;

@GetMapping ("/get/{id}")
@HystrixCommand(fallbackMethod = "defaultDept")
public Dept queryDeptById (@PathVariable ("id") long id) {
Dept dept = deptService.queryDeptById (id);
if (dept==null){
throw new RuntimeException ();
}
return dept;
}

public Dept defaultDept(@PathVariable("id") long id){
return new Dept ().setDeptno (id).setDb_source ("没有这个数据").setDeptname ("没有这个数据====》@hystrix");
}
}

使用的注解 @HystrixCommand(fallbackMethod = “defaultDept”)

里面的数值就是我们的失败返回的函数;

主函数启动类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.saxon.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableCircuitBreaker
public class springcloudHystrix {
public static void main (String[] args) {
SpringApplication.run (springcloudHystrix.class,args);
}
}

添加的注解:**@EnableCircuitBreaker**

服务降级

这个是处于客户端的服务:例如api

服务降级:

服务压力剧增的时候根据当前的业务情况及流量对一些服务和页面有策略的降级,以此环节服务器的压力,以保证核心任务的进行。

同时保证部分甚至大部分任务客户能得到正确的相应。也就是当前的请求处理不了了或者出错了,给一个默认的返回。

服务熔断:在股票市场,熔断这个词大家都不陌生,是指当股指波幅达到某个点后,交易所为控制风险采取的暂停交易措施。相应的,服务熔断一般是指软件系统中,由于某些原因使得服务出现了过载现象,为防止造成整个系统故障,从而采用的一种保护措施,所以很多地方把熔断亦称为过载保护。

从整个网站的负载考虑,并且服务消失后,我们的客户端还是会给出消息,而不是直接断开

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.saxon.springcloud.service;

import com.saxon.springcloud.pojo.Dept;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;

@Component
public class DeptClientServiceFallBackFactory implements FallbackFactory {
@Override
public Object create (Throwable throwable) {
return (FeignService) id -> new Dept ().setDeptno (9999).setDeptname ("该服务已经降级");
}
}

当我们的某一个方法或者服务出现异常的时候,我们就会调用这个里面的方法来实现我们的服务降级,达到和我们的服务熔断一样的效果;

客户端代码 api:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.saxon.springcloud.service;


import com.saxon.springcloud.pojo.Dept;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;


@Component
@FeignClient(value = "SAXON",fallbackFactory = DeptClientServiceFallBackFactory.class)
public interface FeignService {
@GetMapping("/get/{id}")
Dept queryDeptById (@PathVariable("id") long id);

}

image-20201027152239716

基本上我们可以使用feign功能的属性就在这了。要在application.yaml里面使用一个属性开启服务降级

1
2
3
feign:
hystrix:
enabled: true

监控页面 Hystrix-Dashboard:

依赖

监控功能(需要监控的服务就要使用这个包):

1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.3.4.RELEASE</version>
</dependency>

界面操作台功能:

1
2
3
4
5
6
7
8
9
10
11
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix-dashboard -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>

使用服务监控需要版本的统一,最高的H版本有问题,需要降一个版本,在降springcloud版本的同时,需要把spring boot的版本也降一下,这样才可以使用;附版本号:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR6</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--springboot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>

要监控的服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.saxon.springcloud;

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableCircuitBreaker
public class springcloudHystrix {
public static void main (String[] args) {
SpringApplication.run (springcloudHystrix.class, args);
}

@Bean
public ServletRegistrationBean hystrixMetricsStreamServlet () {
ServletRegistrationBean hystrixMetricsStreamServlet = new ServletRegistrationBean (new HystrixMetricsStreamServlet ());
hystrixMetricsStreamServlet.addUrlMappings ("/actuator/hystrix.stream");
return hystrixMetricsStreamServlet;
}
}

1.先使用http://localhost:8001/actuator/hystrix.stream 看看抓不抓得到包,可以的话,在往下一步,等一下成功以后就把这个IP填在dashboard里面就可以直接使用了

2.建立一个项目(port:9001)。里面就专注于监控页面,只要出现下面的情况就符合要求了

image-20201027182549869

出现这个界面就对了;

至于作用,如下: