服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - spring cloud 使用Hystrix 实现断路器进行服务容错保护的方法

spring cloud 使用Hystrix 实现断路器进行服务容错保护的方法

2021-04-25 11:37JAVA开发老菜鸟 Java教程

本篇文章主要介绍了spring cloud 使用Hystrix 实现断路器进行服务容错保护的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

在微服务中,我们将系统拆分为很多个服务单元,各单元之间通过服务注册和订阅消费的方式进行相互依赖。但是如果有一些服务出现问题了会怎么样?

比如说有三个服务(abc),a调用b,b调用c。由于网络延迟或c本身代码有问题导致b迟迟得不到回应,这样b调用c的请求就会被挂起,等待。

在高并发的访问的情况下,这些挂起的线程得不到释放,使后续的请求阻塞,最终导致b也挂掉了。依次类推,a可能也会挂掉,进而使整个系统全部崩溃。

为了解决整个问题,spring cloud 使用hystrix进行服务容错保护,包括断路器、线程隔离等一系列的保护功能,今天我们就来看下如何通过hystrix实现断路器。

一、什么是spring cloud hystrix?什么是断路器?

spring cloud hystrix是基于netflix的开源框架hystrix实现的,其目的是为了通过控制那些访问远程系统、服务和第三方的节点,从而对延迟和故障提供强大的容错能力。

断路器类似于我们家里面强电箱里面用到的漏电断路保护器,当服务单元出现故障(类似于电器发生短路),通过断路器的故障监控功能(类似于保险丝),向调用方返回一个错误响应,避免长时间等待,从而避免故障蔓延到整个系统。

二、没有断路器的情况下,页面展示

还记得我们前面写的spring cloud 入门系列二:使用eureka 进行服务治理里面的三个服务(eureka/hello-service/hello-consumer)吗?我们基于这个进行实验。

1.启动eureka服务注册中心,端口号1111

2.启动hello-service服务提供者,这里我们启动两个服务,端口号分别为9090,9091

3.启动hello-consumer服务消费者,端口号为9999;这个时候我们多次访问http://localhost:9999/hello-consumer是没有问题的

4.将hello-service端口号为9091的服务关掉,再去多次访问http://localhost:9999/hello-consumer,报错了

spring cloud 使用Hystrix 实现断路器进行服务容错保护的方法

ps:这里说明下,为什么要多次访问,是因为我们通过ribbon实现了负载均衡,访问http://localhost:9999/hello-consumer的时候,会轮询访问hello-service的两个服务,当访问到端口号是9091的服务时才报错,访问9090的服务就不会有问题。

三、断路器代码实现

接下来我们看下如何进行代码实现,我们不去修改服务注册中心和服务提供者,只需要修改服务消费者hello-consumer。

1.修改pom文件,引入hystrix依赖

?
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<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/xsd/maven-4.0.0.xsd">
  <modelversion>4.0.0</modelversion>
  <groupid>com.sam</groupid>
  <artifactid>hello-consumer</artifactid>
  <version>0.0.1-snapshot</version>
  <parent>
    <groupid>org.springframework.boot</groupid>
    <artifactid>spring-boot-starter-parent</artifactid>
    <version>1.5.1.release</version>
  </parent>
 
  <properties>
    <javaversion>1.8</javaversion>
  </properties>
 
  <dependencymanagement>
    <dependencies>
      <dependency>
        <groupid>org.springframework.cloud</groupid>
        <artifactid>spring-cloud-dependencies</artifactid>
        <version>camden.sr6</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
 
  </dependencymanagement>
 
  <dependencies>
    <!-- 引入eureka 客户端依赖 -->
    <dependency>
      <groupid>org.springframework.cloud</groupid>
      <artifactid>spring-cloud-starter-eureka</artifactid>
    </dependency>
    <!-- 引入ribbon 依赖 ,用来实现负载均衡,我们这里只是使用先不作其他介绍 -->
    <dependency>
      <groupid>org.springframework.cloud</groupid>
      <artifactid>spring-cloud-starter-ribbon</artifactid>
    </dependency>
    <!-- 引入hystrix 依赖 ,用来实现服务容错保护-->
    <dependency>
      <groupid>org.springframework.cloud</groupid>
      <artifactid>spring-cloud-starter-hystrix</artifactid>
    </dependency>
 
  </dependencies>
</project>

2.修改启动类,追加注解@enablecircuitbreaker,开启断路器

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@enablediscoveryclient
@springbootapplication
@enablecircuitbreaker
public class consumerapp {
 
 
  //@bean 应用在方法上,用来将方法返回值设为为bean
  @bean
  @loadbalanced //@loadbalanced实现负载均衡
  public resttemplate resttemplate() {
    return new resttemplate();
  }
  
  public static void main(string[] args) {
    springapplication.run(consumerapp.class, args);
  }
}

这个时候你会发现,这个启动类加了三个注解,这个是不是很麻烦?没关系,我们可以使用注解@springcloudapplication

?
1
2
3
4
5
6
7
8
9
10
11
12
13
@springcloudapplication
public class consumerapp {
  //@bean 应用在方法上,用来将方法返回值设为为bean
  @bean
  @loadbalanced //@loadbalanced实现负载均衡
  public resttemplate resttemplate() {
    return new resttemplate();
  }
  
  public static void main(string[] args) {
    springapplication.run(consumerapp.class, args);
  }
}

@springcloudapplication = @enablediscoveryclient +@springbootapplication+@enablecircuitbreaker,从源码就能看出来:

?
1
2
3
4
5
6
7
8
9
@target(elementtype.type)
@retention(retentionpolicy.runtime)
@documented
@inherited
@springbootapplication
@enablediscoveryclient
@enablecircuitbreaker
public @interface springcloudapplication {
}

3.追加service

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@service
public class consumerservice {
  
  @autowired
  resttemplate resttemplate;
 
  @hystrixcommand(fallbackmethod = "errormsg")
  public string consumer() {
    // 调用hello-service服务,注意这里用的是服务名,而不是具体的ip+port
    resttemplate.getforobject("http://hello-service/hello", string.class);
    return "hello consumer finish !!!";
  }
 
  public string errormsg() {
    return "error!!!";
  }
}

我们把原来controller里面的调用resttemplate的实现放到service里面,并且通过@hystrixcommand来指定回调方法,当出现错误时调用该方法。

4.修改controller 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
 *这里不再直接调用resttemplate,
 *而是通过调用service进行实现
 *
 */
@restcontroller
public class consumercontroller {
 
  @autowired
//  resttemplate resttemplate;
  consumerservice service;
  
  
  @requestmapping("/hello-consumer")
  public string helloconsumer() {
//    //调用hello-service服务,注意这里用的是服务名,而不是具体的ip+port
//    resttemplate.getforobject("http://hello-service/hello", string.class);
    return service.consumer();
  }
}

5.测试,多次访问,当报错的时候,会显示如下内容

 spring cloud 使用Hystrix 实现断路器进行服务容错保护的方法

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:http://www.cnblogs.com/sam-uncle/p/8972281.html

延伸 · 阅读

精彩推荐