7.Spring-Cloud服务容错保护之Hystrix初探

Posted 盲目的拾荒者

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了7.Spring-Cloud服务容错保护之Hystrix初探相关的知识,希望对你有一定的参考价值。

      在微服务架构中,存在着多个服务单元,若一个单元出现故障,就很容易因依赖关系而出现故障的蔓延,最终导致整个系统的瘫痪,这样的架构相较传统的架构更加不稳定,为了解决这样的问题,产生了断路器等一系列的服务保护机制。

    "断路器"本身是一种开关装置,用于在电路上保护线路过载,当线路中有电器发生短路,"断路器"能够及时切断故障电路,防止发生过载、发热甚至起火等严重后果。

      分布式架构中,断路器模式的作用也是类似的,当某个服务单元发生故障(类似于用电器发生短路)之后,通过断路器的故障监控(l类似熔断器保险丝),向调用方返回一个错误响应,而不是长时间的等待。这样就不会使得线程因调用故障服务被长时间占用不释放,避免了故障在分布式系统的蔓延。

      针对上述问题,SpringCloudHystrix实现了断路器、线程隔离等一系列服务保护功能。它也是基于Netflix的开源框架Hystrix实现的,该框架的目标在于通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供强大的容错能力。Hystrix具备服务降级、服务熔断、线程和信号隔离、请求缓存合并以及服务监控等强大的功能。                                                                                           -----来自《SpringCloud微服务实战》

技术图片技术图片?

                                                 上图为正常的微服务调用

技术图片技术图片?

      当某个服务出现故障Hystrix回退防止级联故障,较低级别的服务中的服务故障可能导致用户级联故障。当对特定服务的检测达到一定阈值时(Hystrix中的默认值为5秒内的20次故障),电路打开,不进行响应。在错误和开路的情况下,开发人员可以提供后备(即服务降级)。

演示未加入熔断器

启动高可用注册中心

启动服务提供者(port=8081,port=8082)

启动消费者(通过Robbin负载均衡访问)

之前的博客已经演示过了,在两个服务提供者都正常使用的情况,停用端口8082的服务提供者,当消费者负载均衡轮训访问到8082端口的时候就会报如下错误:

技术图片技术图片?加入熔断器

1.pom.xml中引入依赖hystrix依赖

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>6.spring-cloud-hystrix-consumer</groupId>
<artifactId>hystrix-consumer</artifactId>
<packaging>jar</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>spring-cloud Maven Webapp</name>
<url>http://maven.apache.org</url>
<!--springboot采用1.5.x 对应springcloud版本为 Dalston -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
<relativePath />
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Dalston.RELEASE</spring-cloud.version>
</properties>
<dependencies>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>


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


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


<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--引入ribbon 负载均衡 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<!-- 搞了好久踩的坑,就是在复制上面代码的时候 顺手把scope test复制了,其意思为紧参与junit类似的测试工作,所以一直报找不到服务或者或者拒绝连接 -->
<!-- <scope>test</scope> -->
</dependency>
<!--引入hystrix熔断器 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 这样变成可执行的jar -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

 

技术图片


2.在springboot启动类中添加开启熔断器的注解

package com.niugang;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.client.RestTemplate;


/**
 * 负责服务的发现与消费
 * 
 * @author niugang
 *
 */
@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix//这个注解就@EnableCircuitBreaker的代替
/*
 * @SpringCloudApplication
 * 包含了
 * @SpringBootApplication
 * @EnableDiscoveryClient
 * @EnableCircuitBreaker
 * 着三个注解
 */
@ComponentScan
public class Application {

   //负载均衡
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

 

技术图片


3.controller

package com.niugang.controller;
import org.slf4j.Logger;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.niugang.service.HelloService;
@RestController
public class HelloController {
private final Logger logger = org.slf4j.LoggerFactory.getLogger(HelloController.class);

        @Resource

private HelloService helloService;
@RequestMapping(value = "/ribbon-consumer", method = RequestMethod.GET)
public String ribbon() {
return helloService.helloService();
}
}

 

技术图片


4.service

package com.niugang.service;


import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
@Service
public class HelloService {
private final Logger logger = org.slf4j.LoggerFactory.getLogger(HelloService.class);
@Autowired
    private RestTemplate restTemplate;
    /**
     * @HystrixCommand:指定一些方法,这些方法应该是作为hystrix命令的进程
     * fallbackMethod:指定回退方法,降级处理,此方法应该和@HystrixCommand在一个类中,用来实现服务降级处理逻辑
     * 
     */

      @HystrixCommand(fallbackMethod="helloBackMethodFirst")
public String  helloService() {
logger.info("start invoke service");
//URI需要使用虚拟主机名(即服务名称,而不是主机名)
return restTemplate.getForEntity("http://service-provide/hello", String.class).getBody();
}
/**
* 通用降级函数
* @return
*/
@HystrixCommand(fallbackMethod="helloBackMethodSecond")
public  String  helloBackMethodFirst(){
//此处可能是另外一个网络请求,所以也可能出现错误
return  "error1";
}
/**
* 二次降级
* @return
*/
@HystrixCommand(fallbackMethod="helloBackMethodSecond")
public  String  helloBackMethodSecond(){
return  "error2";
}
}

 

技术图片

启动消费者,正常访问返回如下:

技术图片技术图片?

停用一个服务提供者,当负载均衡讯轮到停用的服务提供者时,返回如下:

技术图片技术图片?

这样的话熔断器起作用了,进行了服务的降级。

健康指标
连接断路器的状态也暴露在呼叫应用程序的/health端点中。


{
    "hystrix": {
        "openCircuitBreakers": [
            "StoreIntegration::getStoresByLocationLink"
        ],
        "status": "CIRCUIT_OPEN"
    },
    "status": "UP"
}
Hystrix指标流
要使Hystrix指标流包含对spring-boot-starter-actuator的依赖。这将使/hystrix.stream作为管理端点。

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

 

                                                                           微信公众号: 

                                               技术图片技术图片?

                                                                             JAVA程序猿成长之路

                          分享资源,记录程序猿成长点滴。专注于Java,Spring,SpringBoot,SpringCloud,分布式,微服务。 

以上是关于7.Spring-Cloud服务容错保护之Hystrix初探的主要内容,如果未能解决你的问题,请参考以下文章

分布式系统的延时和故障容错之Spring Cloud Hystrix

Spring Cloud:服务容错保护 HystrixFinchley 版

Spring Cloud构建微服务架构 服务容错保护(Hystrix断路器)Dalston版

第五章 服务容错保护:Spring Cloud Hystrix

服务容错保护断路器Hystrix之五:配置

服务容错与保护方案 — Hystrix