项目源码下载:(访问密码:9987)
Spring-Cloud-Circuit-Breaker.zip
学习在调用底层微服务的同时利用调用的Spring Cloud Netflix堆栈组件之一Hystrix
来实现断路器。在一些底层服务永久宕机/抛出错误的应用中,一般需要开启容错功能,我们需要自动回退到不同的程序执行路径。这与使用大量底层微服务的生态系统的分布式计算风格有关。这是断路器模式的帮助所在,也是构建此断路器的工具
Hystrix Example for real impatient
Hystrix 配置分四个主要步骤完成。
- 添加 Hystrix 启动器和仪表板依赖项。
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId> </dependency>
- 添加
@EnableCircuitBreaker
注释 - 添加
@EnableHystrixDashboard
注释 - 添加注释
@HystrixCommand(fallbackMethod = "myFallbackMethod")
什么是断路器模式?
如果我们在基于微服务的架构上设计我们的系统,我们通常会开发许多微服务,这些微服务将在实现某些业务目标时相互进行大量交互。现在,我们所有人都可以假设,如果所有服务都启动并运行并且每个服务的响应时间都令人满意,这将产生预期的结果。
现在,如果当前生态系统的任何服务出现问题并停止为请求提供服务,将会发生什么。这将导致超时/异常,并且由于这种单点故障,整个生态系统将变得不稳定。
在这里,断路器模式很方便,一旦看到任何此类情况,它就会将流量重定向到回退路径。它还密切监视有缺陷的服务,并在服务恢复正常后恢复流量。
因此,断路器是进行服务调用的方法的一种包装器,它监视服务运行状况,一旦出现问题,断路器就会跳闸,所有进一步调用都转到断路器回退并最终自动恢复一次服务回来了!!这很酷吧?
Hystrix 断路器示例
为了演示断路器,我们将创建以下两个微服务,其中第一个依赖于另一个。
- 学生微服务– 这将提供
Student
实体的一些基本功能。这将是一个基于 REST 的服务。我们将从School
Service调用此服务以了解断路器。它将8098
在本地主机的端口上运行。 - School Microservice – 又是一个简单的基于 REST 的微服务,我们将使用
Hystrix
.Student
将从这里调用服务,一旦学生服务不可用,我们将测试回退路径。它将在本地主机的 9098 端口上运行。
技术栈和演示运行时
技术栈和演示运行时
- Java 1.8
- Eclipse as IDE
- Maven as build tool
- Spring cloud Hystrix as circuit breaker framework
- Spring boot
- Spring Rest
创建学生服务
按照以下步骤创建和运行学生服务——一个简单的 REST 服务,提供学生实体的一些基本功能。
创建spring boot项目
从Spring Boot 初始值设定项门户创建一个具有三个依赖项的 Spring boot 项目,即Web
、Rest Repositories
和Actuator
。给出其他maven GAV坐标并下载项目。
解压缩该项目并将其作为现有的 maven 项目导入 Eclipse。在这一步中,所有必需的依赖项都将从 maven 存储库下载。
服务器端口设置
打开application.properties
并添加端口信息。
server.port = 8098
这将使该应用程序在默认端口 8098 上运行。我们可以通过 -Dserver.port = XXXX
在启动服务器时提供参数轻松覆盖它。
创建 REST API
现在添加一个 REST 控制器类,StudentServiceController
并公开一个 rest 端点,用于获取特定学校的所有学生详细信息。在这里,我们公开/getStudentDetailsForSchool/{schoolname}
端点以服务于业务目的。为简单起见,我们对学生的详细信息进行了硬编码。
StudentServiceController.java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.example.howtodoinjava.springhystrixstudentservice.domain.Student;
@RestController
public class StudentServiceController {
private static Map<String, List<Student>> schooDB = new HashMap<String, List<Student>>();
static {
schooDB = new HashMap<String, List<Student>>();
List<Student> lst = new ArrayList<Student>();
Student std = new Student("Sajal", "Class IV");
lst.add(std);
std = new Student("Lokesh", "Class V");
lst.add(std);
schooDB.put("abcschool", lst);
lst = new ArrayList<Student>();
std = new Student("Kajal", "Class III");
lst.add(std);
std = new Student("Sukesh", "Class VI");
lst.add(std);
schooDB.put("xyzschool", lst);
}
@RequestMapping(value = "/getStudentDetailsForSchool/{schoolname}", method = RequestMethod.GET)
public List<Student> getStudents(@PathVariable String schoolname) {
System.out.println("Getting Student details for " + schoolname);
List<Student> studentList = schooDB.get(schoolname);
if (studentList == null) {
studentList = new ArrayList<Student>();
Student std = new Student("Not Found", "N/A");
studentList.add(std);
}
return studentList;
}
}
Student.java
public class Student {
private String name;
private String className;
public Student(String name, String className) {
super();
this.name = name;
this.className = className;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
}
构建和测试学生服务
现在mvn clean install
使用 command进行最终构建并运行服务器java -jar target/spring-hystrix-student-service-0.0.1-SNAPSHOT.jar
。这将在默认端口启动学生服务8098
。
打开浏览器并输入http://localhost:8098/getStudentDetailsForSchool/abcschool
.
它应该在浏览器中显示以下输出 –
创建学校服务 – Hystrix 已启用
与学生服务类似,为学校创建另一个微服务。它将在内部调用已经开发的学生服务。
生成spring boot项目
主要使用这些依赖项从Spring Boot 初始值设定项门户创建一个 Spring boot 项目。
- Web – REST 端点
- Actuator – 提供基本的管理 URL
- Hystrix – 启用断路器
- Hystrix Dashboard – 启用一个与断路器监控相关的仪表板屏幕
给出其他maven GAV坐标并下载项目。
解压缩该项目并将其作为现有的 maven 项目导入到 Eclipse 中。在这一步中,所有必需的依赖项都将从 maven 存储库下载。
服务器端口设置
打开application.properties
并添加端口信息。
server.port = 9098
这将使该应用程序在默认端口 9098 上运行。我们可以通过 -Dserver.port = XXXX
在启动服务器时提供参数来轻松覆盖它。
启用 Hystrix 设置
打开SpringHystrixSchoolServiceApplication
即生成的类,@SpringBootApplication
并添加@EnableHystrixDashboard
和@EnableCircuitBreaker
注释。
这将在应用程序中启用 Hystrix 断路器,还将添加一个在 Hystrix 提供的本地主机上运行的有用仪表板。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
@SpringBootApplication
@EnableHystrixDashboard
@EnableCircuitBreaker
public class SpringHystrixSchoolServiceApplication {
public static void main(String[] args) {
SpringApplication.run(SpringHystrixSchoolServiceApplication.class, args);
}
}
添加 REST 控制器
添加SchoolServiceController
Rest Controller,我们将在其中公开/getSchoolDetails/{schoolname}
端点,该端点将简单地返回学校详细信息及其学生详细信息。对于学生详细信息,它将调用已经开发的学生服务端点。我们将创建一个委托层StudentServiceDelegate.java
来调用学生服务。这个简单的代码看起来像
SchoolServiceController.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.example.howtodoinjava.springhystrixschoolservice.delegate.StudentServiceDelegate;
@RestController
public class SchoolServiceController {
@Autowired
StudentServiceDelegate studentServiceDelegate;
@RequestMapping(value = "/getSchoolDetails/{schoolname}", method = RequestMethod.GET)
public String getStudents(@PathVariable String schoolname) {
System.out.println("Going to call student service to get data!");
return studentServiceDelegate.callStudentServiceAndGetData(schoolname);
}
}
学生服务代表
我们将在这里做以下事情来启用 Hystrix 断路器。
- 通过提供的 spring 框架调用学生服务
RestTemplate
- 添加 Hystrix 命令以启用回退方法 –
@HystrixCommand(fallbackMethod = "callStudentServiceAndGetData_Fallback")
– 这意味着我们将不得不添加另一个callStudentServiceAndGetData_Fallback
具有相同签名的方法,该方法将在实际学生服务关闭时调用。 - 添加回退方法——
callStudentServiceAndGetData_Fallback
它只会返回一些默认值。
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
@Service
public class StudentServiceDelegate {
@Autowired
RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "callStudentServiceAndGetData_Fallback")
public String callStudentServiceAndGetData(String schoolname) {
System.out.println("Getting School details for " + schoolname);
String response = restTemplate
.exchange("http://localhost:8098/getStudentDetailsForSchool/{schoolname}"
, HttpMethod.GET
, null
, new ParameterizedTypeReference<String>() {
}, schoolname).getBody();
System.out.println("Response Received as " + response + " - " + new Date());
return "NORMAL FLOW !!! - School Name - " + schoolname + " ::: " +
" Student Details " + response + " - " + new Date();
}
@SuppressWarnings("unused")
private String callStudentServiceAndGetData_Fallback(String schoolname) {
System.out.println("Student Service is down!!! fallback route enabled...");
return "CIRCUIT BREAKER ENABLED!!! No Response From Student Service at this moment. " +
" Service will be back shortly - " + new Date();
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
学校服务的构建和测试
现在mvn clean install
使用 command进行最终构建并运行服务器java -jar target/spring-hystrix-school-service-0.0.1-SNAPSHOT.jar
。这将在默认端口9098 中启动学校服务。
如上所述启动学生服务,然后通过打开浏览器并键入 来测试学校服务http://localhost:9098/getSchoolDetails/abcschool
。它应该在浏览器中显示以下输出:
测试 Hystrix 断路器 – 演示
打开浏览器并输入http://localhost:9098/getSchoolDetails/abcschool
.
它应该在浏览器中显示以下输出 –
现在我们已经知道 School 服务正在内部调用学生服务,并且它正在从该服务获取学生详细信息。因此,如果这两个服务都在运行,则学校服务将显示学生服务返回的数据,正如我们在上面的学校服务浏览器输出中看到的那样。这是电路关闭状态。
现在让我们停止该服务的学生只需按CTRL + C
在学生服务服务器控制台(停止服务器)和浏览器再次测试该学校的服务。这次它将返回回退方法响应。在这里,Hystrix 出现了,它频繁地监视学生服务,当它关闭时,Hystrix 组件已打开电路并启用回退路径。
这是浏览器中的回退输出。
再次启动学生服务,稍等片刻,返回学校服务,它将再次以正常流程开始响应。
Hystrix 仪表板
由于我们添加了 hystrix 仪表板依赖项,因此 hystrix 在以下 URL 中提供了一个不错的仪表板和一个 Hystrix Stream:
- http://localhost:9098/hystrix.stream – Hystrix 生成的连续流。它只是一个健康检查结果以及 Hystrix 正在监视的所有服务调用。示例输出在浏览器中看起来像 –
- http://localhost:9098/hystrix – 这是可视化仪表板初始状态。
- 现在在仪表板中添加http://localhost:9098/hystrix.stream以获得由 Hystrix 组件监控的电路的有意义的动态视觉表示。在主页中提供 Stream 输入后的 Visual Dashboard –
总结
这就是创建 spring 可以 Hystrix 断路器的全部内容,我们已经测试了电路开放路径和电路闭合路径。自己做设置,玩不同的组合服务状态,更清晰的整体概念。
项目源码下载:(访问密码:9987)
Spring-Cloud-Circuit-Breaker.zip
原创文章,作者:1402239773,如若转载,请注明出处:https://blog.ytso.com/243838.html