原文:https://howtodoinjava.com/spring-cloud/spring-hystrix-circuit-breaker-tutorial/

了解如何利用称为 HystrixSpring cloud Netflix 堆栈组件之一来实现断路器,同时调用基础微服务。 通常需要在某些基础服务永久关闭/抛出错误的应用程序中启用容错功能,我们需要自动退回到程序执行的不同路径。 这与使用大量底层微服务的生态系统的分布式计算风格有关。 这是断路器模式的帮助之处,Hystrix 是构建此断路器的工具。

Hystrix 示例

Hystrix 配置通过四个主要步骤完成。

  1. 添加 Hystrix 启动器和仪表板依赖项。
    1. <dependency>
    2. <groupId>org.springframework.cloud</groupId>
    3. <artifactId>spring-cloud-starter-hystrix</artifactId>
    4. </dependency>
    5. <dependency>
    6. <groupId>org.springframework.cloud</groupId>
    7. <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
    8. </dependency>
  1. 添加@EnableCircuitBreaker注解

  2. 添加@EnableHystrixDashboard注解

  3. 添加注解@HystrixCommand(fallbackMethod = "myFallbackMethod")

什么是断路器模式?

如果我们在基于微服务的体系结构上设计系统,则通常会开发许多微服务,并且这些微服务会在实现某些业务目标时相互影响很大。 现在,我们所有人都可以假设,如果所有服务都已启动并且正在运行,并且每个服务的响应时间令人满意,那么这将给出预期的结果。

现在,如果当前生态系统的任何服务出现问题并停止为请求提供服务,将会发生什么。 这将导致超时/异常,并且由于此单点故障,整个生态系统将变得不稳定。

在这里,断路器模式非常方便,一旦发现任何此类情况,它将流量重定向到回退路径。 它还会密切监视有缺陷的服务,并在服务恢复正常后恢复流量。

因此,断路器是进行服务调用的方法的一种包装,它监视服务的运行状况,一旦出现问题,断路器将跳闸,所有进一步的调用都将返回到断路器,最后一旦服务回来了就自动恢复! 太酷了吧?

Hystrix 断路器模式 – SpringCloud - 图1

断路器调用顺序

Hystrix 断路器示例

为了演示断路器,我们将创建以下两个微服务,其中第一个微服务依赖于另一个。

  • 学生微服务 – 将提供Student实体的一些基本功能。 这将是一个基于 REST 的服务。 我们将从School服务中调用此服务,以了解断路器。 它将在本地主机的端口8098上运行。
  • 学校微服务 – 同样是一个简单的基于 REST 的微服务,我们将使用 Hystrix 实现断路器。 Student服务将从此处调用,一旦学生服务不可用,我们将测试后备路径。 它将在本地主机的端口 9098 上运行。

技术栈和演示运行时

  • Java 1.8
  • Eclipse 作为 IDE
  • Maven 作为构建工具
  • Spring Cloud Hystrix 作为断路器框架
  • SpringBoot
  • SpringRest

创建学生服务

请按照以下步骤创建和运行学生服务-一个简单的 REST 服务,提供学生实体的一些基本功能。

创建 spring boot 项目

Spring Boot 初始化器页面创建具有三个依赖项的 Spring Boot 项目,即WebRest RepositoriesActuator。 给出其他 Maven GAV 坐标并下载项目。

Hystrix 断路器模式 – SpringCloud - 图2

学生服务生成

将项目解压缩并将其作为现有的 maven 项目导入 Eclipse。 在此步骤中,将从 maven 存储库下载所有必需的依赖项。

服务器端口设置

打开application.properties并添加端口信息。

  1. server.port = 8098

这将使该应用程序在默认端口 8098 上运行。通过在启动服务器时提供 -Dserver.port = XXXX参数,可以轻松地覆盖此应用程序。

创建 REST API

现在添加一个称为StudentServiceController的 REST 控制器类,并公开一个其余端点,以获取特定学校的所有学生详细信息。 在这里,我们公开/getStudentDetailsForSchool/{schoolname}端点来满足业务目的。 为简单起见,我们正在对学生详细信息进行硬编码。

StudentServiceController.java

  1. package com.example.howtodoinjava.springhystrixstudentservice.controller;
  2. import java.util.ArrayList;
  3. import java.util.HashMap;
  4. import java.util.List;
  5. import java.util.Map;
  6. import org.springframework.web.bind.annotation.PathVariable;
  7. import org.springframework.web.bind.annotation.RequestMapping;
  8. import org.springframework.web.bind.annotation.RequestMethod;
  9. import org.springframework.web.bind.annotation.RestController;
  10. import com.example.howtodoinjava.springhystrixstudentservice.domain.Student;
  11. @RestController
  12. public class StudentServiceController {
  13. private static Map<String, List<Student>> schooDB = new HashMap<String, List<Student>>();
  14. static {
  15. schooDB = new HashMap<String, List<Student>>();
  16. List<Student> lst = new ArrayList<Student>();
  17. Student std = new Student("Sajal", "Class IV");
  18. lst.add(std);
  19. std = new Student("Lokesh", "Class V");
  20. lst.add(std);
  21. schooDB.put("abcschool", lst);
  22. lst = new ArrayList<Student>();
  23. std = new Student("Kajal", "Class III");
  24. lst.add(std);
  25. std = new Student("Sukesh", "Class VI");
  26. lst.add(std);
  27. schooDB.put("xyzschool", lst);
  28. }
  29. @RequestMapping(value = "/getStudentDetailsForSchool/{schoolname}", method = RequestMethod.GET)
  30. public List<Student> getStudents(@PathVariable String schoolname) {
  31. System.out.println("Getting Student details for " + schoolname);
  32. List<Student> studentList = schooDB.get(schoolname);
  33. if (studentList == null) {
  34. studentList = new ArrayList<Student>();
  35. Student std = new Student("Not Found", "N/A");
  36. studentList.add(std);
  37. }
  38. return studentList;
  39. }
  40. }

Student.java

  1. package com.example.howtodoinjava.springhystrixstudentservice.domain;
  2. public class Student {
  3. private String name;
  4. private String className;
  5. public Student(String name, String className) {
  6. super();
  7. this.name = name;
  8. this.className = className;
  9. }
  10. public String getName() {
  11. return name;
  12. }
  13. public void setName(String name) {
  14. this.name = name;
  15. }
  16. public String getClassName() {
  17. return className;
  18. }
  19. public void setClassName(String className) {
  20. this.className = className;
  21. }
  22. }

建立并测试学生服务

现在,使用mvn clean install进行最终构建,并使用命令java -jar target\spring-hystrix-student-service-0.0.1-SNAPSHOT.jar运行服务器。 这将在默认端口8098中启动学生服务。

打开浏览器,然后输入http://localhost:8098/getStudentDetailsForSchool/abcschool

它应在浏览器中显示以下输出:

Hystrix 断路器模式 – SpringCloud - 图3

学生服务响应

创建学校服务 - 启用 Hystrix

与学生服务类似,为学校创建另一个微服务。 它将在内部调用已开发的学生服务。

生成 Spring Boot 项目

Spring Boot 初始化器页面主要使用那些依赖项创建一个 Spring Boot 项目。

  • Web – REST 端点
  • 执行器 – 提供基本管理 URL
  • Hystrix – 启用断路器
  • Hystrix 仪表板 – 启用一个与断路器监控相关的仪表板屏幕

给出其他 Maven GAV 坐标并下载项目。

Hystrix 断路器模式 – SpringCloud - 图4

学校服务项目

将项目解压缩并作为现有 maven 项目导入到 Eclipse 中。 在此步骤中,将从 maven 存储库下载所有必需的依赖项。

服务器端口设置

打开application.properties并添加端口信息。

  1. server.port = 9098

这将使该应用程序在默认端口 9098 上运行。通过在启动服务器时提供 -Dserver.port = XXXX参数,可以轻松地覆盖此应用程序。

启用 Hystrix 设置

打开SpringHystrixSchoolServiceApplication,即使用@SpringBootApplication生成的类,并添加@EnableHystrixDashboard@EnableCircuitBreaker注解。

这将在应用程序中启用 Hystrix 断路器,还将添加一个在 Hystrix 提供的localhost上运行的有用仪表板。

  1. package com.example.howtodoinjava.springhystrixschoolservice;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
  5. import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
  6. @SpringBootApplication
  7. @EnableHystrixDashboard
  8. @EnableCircuitBreaker
  9. public class SpringHystrixSchoolServiceApplication {
  10. public static void main(String[] args) {
  11. SpringApplication.run(SpringHystrixSchoolServiceApplication.class, args);
  12. }
  13. }

添加 REST 控制器

在我们将公开/getSchoolDetails/{schoolname}端点的位置添加SchoolServiceController Rest 控制器,该端点将仅返回学校详细信息及其学生详细信息。 对于学生详细信息,它将调用已经开发的学生服务端点。 我们将创建一个代表层StudentServiceDelegate.java来调用学生服务。 这个简单的代码看起来像

SchoolServiceController.java

  1. package com.example.howtodoinjava.springhystrixschoolservice.controller;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.web.bind.annotation.PathVariable;
  4. import org.springframework.web.bind.annotation.RequestMapping;
  5. import org.springframework.web.bind.annotation.RequestMethod;
  6. import org.springframework.web.bind.annotation.RestController;
  7. import com.example.howtodoinjava.springhystrixschoolservice.delegate.StudentServiceDelegate;
  8. @RestController
  9. public class SchoolServiceController {
  10. @Autowired
  11. StudentServiceDelegate studentServiceDelegate;
  12. @RequestMapping(value = "/getSchoolDetails/{schoolname}", method = RequestMethod.GET)
  13. public String getStudents(@PathVariable String schoolname) {
  14. System.out.println("Going to call student service to get data!");
  15. return studentServiceDelegate.callStudentServiceAndGetData(schoolname);
  16. }
  17. }

StudentServiceDelegate

我们将在此处执行以下操作以启用 Hystrix 断路器。

  • 通过提供的 Spring 框架调用学生服务RestTemplate
  • 添加 Hystrix 命令以启用回退方法 – @HystrixCommand(fallbackMethod = "callStudentServiceAndGetData_Fallback") – 这意味着我们将不得不添加另一个具有相同签名的方法callStudentServiceAndGetData_Fallback,当实际的学生服务关闭时将调用该方法。
  • 添加后备方法 – callStudentServiceAndGetData_Fallback,它将仅返回一些默认值。
  1. package com.example.howtodoinjava.springhystrixschoolservice.delegate;
  2. import java.util.Date;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.context.annotation.Bean;
  5. import org.springframework.core.ParameterizedTypeReference;
  6. import org.springframework.http.HttpMethod;
  7. import org.springframework.stereotype.Service;
  8. import org.springframework.web.client.RestTemplate;
  9. import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
  10. @Service
  11. public class StudentServiceDelegate {
  12. @Autowired
  13. RestTemplate restTemplate;
  14. @HystrixCommand(fallbackMethod = "callStudentServiceAndGetData_Fallback")
  15. public String callStudentServiceAndGetData(String schoolname) {
  16. System.out.println("Getting School details for " + schoolname);
  17. String response = restTemplate
  18. .exchange("http://localhost:8098/getStudentDetailsForSchool/{schoolname}"
  19. , HttpMethod.GET
  20. , null
  21. , new ParameterizedTypeReference<String>() {
  22. }, schoolname).getBody();
  23. System.out.println("Response Received as " + response + " - " + new Date());
  24. return "NORMAL FLOW !!! - School Name - " + schoolname + " ::: " +
  25. " Student Details " + response + " - " + new Date();
  26. }
  27. @SuppressWarnings("unused")
  28. private String callStudentServiceAndGetData_Fallback(String schoolname) {
  29. System.out.println("Student Service is down!!! fallback route enabled...");
  30. return "CIRCUIT BREAKER ENABLED!!! No Response From Student Service at this moment. " +
  31. " Service will be back shortly - " + new Date();
  32. }
  33. @Bean
  34. public RestTemplate restTemplate() {
  35. return new RestTemplate();
  36. }
  37. }

建立和测试学校服务

现在,使用mvn clean install进行最终构建,并使用命令java -jar target\spring-hystrix-school-service-0.0.1-SNAPSHOT.jar运行服务器。 这将在默认端口 9098 中启动学校服务。

如上所述启动学生服务,然后通过打开浏览器并键入http://localhost:9098/getSchoolDetails/abcschool来测试学校服务。 它应该在浏览器中显示以下输出:

Hystrix 断路器模式 – SpringCloud - 图5

学校服务响应

测试 Hystrix 断路器 - 演示

打开浏览器,然后输入http://localhost:9098/getSchoolDetails/abcschool

它应在浏览器中显示以下输出:

Hystrix 断路器模式 – SpringCloud - 图6

学校服务响应

现在我们已经知道,学校服务在内部调用学生服务,并且正在从该服务获取学生详细信息。 因此,如果两个服务都在运行,则学校服务将显示学生服务返回的数据,正如我们在上面的学校服务浏览器输出中所看到的那样。 这是电路关闭状态

现在,让我们停止学生服务,只需在学生服务服务器控制台中按CTRL + C(停止服务器),然后从浏览器再次测试学校服务。 这次它将返回回退方法响应。 Hystrix 出现在这里,它会频繁地监视学生服务,并且在停机时,Hystrix 组件已打开电路并启用了后备路径。

这是浏览器中的回退输出。

Hystrix 断路器模式 – SpringCloud - 图7

学校服务响应回退路径

再次启动学生服务,等待片刻,然后返回学校服务,它将再次开始以正常流程进行响应。

Hystrix 仪表板

当我们添加了 hystrix 仪表板依赖时,hystrix 在以下 URL 中提供了一个不错的仪表盘和 Hystrix 流:

  • http://localhost:9098/hystrix.stream – Hystrix 产生的连续流。 这只是健康检查结果以及 Hystrix 正在监视的所有服务呼叫。 示例输出在浏览器中将如下所示:
    Hystrix 断路器模式 – SpringCloud - 图8
    Hystrix 流式输出

  • http://localhost:9098/hystrix – 这是可视仪表板的初始状态。
    Hystrix 断路器模式 – SpringCloud - 图9
    Hystrix 初始仪表盘

  • 现在,在仪表板中添加http://localhost:9098/hystrix.stream,以获得由 Hystrix 组件监视的电路的有意义的动态视觉表示。 在主页中提供流式输入后的虚拟仪表盘:
    Hystrix 断路器模式 – SpringCloud - 图10
    Hystrix 虚拟仪表盘

总结

这就是可以制造 Spring 开关 Hystrix 断路器的全部内容,我们已经测试了电路开放路径电路闭合路径。 自行进行设置,并使用不同的组合服务状态以更清楚地了解整个概念。

如果您在执行本文时遇到任何困难,请添加评论。 我们将很乐意调查这个问题。

下载源码

学习愉快!