本指南将引导您使用Netflix Hystrix容错库,将断路器应用于可能失败的方法调用。
你会建立什么
您将构建一个微服务应用程序,该应用程序将在方法调用失败时使用断路器模式来正常降低功能。使用Circuit Breaker模式可以使微服务在相关服务失败时继续运行,从而防止故障级联并为失败的服务提供恢复时间。
你需要什么
-
约15分钟
-
最喜欢的文本编辑器或IDE
-
JDK 1.8或更高版本
-
您还可以将代码直接导入到IDE中:
如何完成本指南
像大多数Spring 入门指南一样,您可以从头开始并完成每个步骤,也可以绕过您已经熟悉的基本设置步骤。无论哪种方式,您最终都可以使用工作代码。
要从头开始 ,请继续进行以Spring Initializr 开头 。
要跳过基础知识 ,请执行以下操作:
-
下载并解压缩本指南的源存储库,或使用Git对其进行克隆:
git clone https://github.com/spring-guides/gs-circuit-breaker.git
-
光盘进入
gs-circuit-breaker/initial
-
继续建立服务器微服务应用程序 。
完成后 ,您可以根据中的代码检查结果gs-circuit-breaker/complete
。
从Spring Initializr开始
对于所有Spring应用程序,您应该从Spring Initializr开始。Initializr提供了一种快速的方法来提取应用程序所需的所有依赖关系,并为您完成了许多设置。
本指南需要两个应用程序。第一个应用程序(一个简单的书店站点)仅需要Web依赖项。下图显示了为书店设置的Initializr:

上图显示了选择Maven作为构建工具的Initializr。您也可以使用Gradle。它还显示了com.example 和circuit-breaker-bookstore 分别是Group和Artifact。在本示例的其余部分中,将使用这些值。 |
以下清单显示了pom.xml
选择Maven时创建的文件(用于配置服务):
<?xml version="1.0" encoding="UTF-8"?> <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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.8.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>circuit-breaker-bookstore</artifactId> <version>0.0.1-SNAPSHOT</version> <name>circuit-breaker-bookstore</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
以下清单显示了build.gradle
选择Gradle时创建的文件(用于配置服务):
plugins { id 'org.springframework.boot' version '2.1.8.RELEASE' id 'io.spring.dependency-management' version '1.0.8.RELEASE' id 'java' } group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '1.8' repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' testImplementation 'org.springframework.boot:spring-boot-starter-test' }
第二个应用程序(阅读应用程序,将使用Hystrix断路器)需要Web和Hystrix依赖项。下图显示了为配置客户端设置的Initializr:

上图显示了选择Maven作为构建工具的Initializr。您也可以使用Gradle。它还显示了com.example 和circuit-breaker-reading 分别是Group和Artifact。在本示例的其余部分中,将使用这些值。 |
以下清单显示了pom.xml
选择Maven时创建的文件(用于配置客户端):
<?xml version="1.0" encoding="UTF-8"?> <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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.8.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>circuit-breaker-reading</artifactId> <version>0.0.1-SNAPSHOT</version> <name>circuit-breaker-reading</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR3</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-netflix-hystrix</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </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> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
以下清单显示了build.gradle
选择Gradle时创建的文件(用于配置客户端):
plugins { id 'org.springframework.boot' version '2.1.8.RELEASE' id 'io.spring.dependency-management' version '1.0.8.RELEASE' id 'java' } group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '1.8' repositories { mavenCentral() } ext { set('springCloudVersion', "Greenwich.SR3") } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.cloud:spring-cloud-starter-netflix-hystrix' testImplementation 'org.springframework.boot:spring-boot-starter-test' } dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" } }
为了方便起见,我们提供了构建文件( pom.xml 文件和一个build.gradle 文件)位于完整和初始项目的顶部(位于bookstore 和reading 目录),您可以用来同时构建书店项目和阅读项目。我们还在那里添加了Maven和Gradle包装器。 |
设置服务器微服务应用程序
Bookstore服务将具有一个终结点。可以在以下位置访问/recommended
并将(为简单起见)返回推荐的阅读清单作为String
。
您需要在BookstoreApplication.java
。它看起来应该像下面的清单(来自bookstore/src/main/java/com/example/circuitbreakerbookstore/CircuitBreakerBookstoreApplication.java
):
package com.example.circuitbreakerbookstore;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
@RestController
@SpringBootApplication
public class CircuitBreakerBookstoreApplication {
@RequestMapping(value = "/recommended")
public String readingList(){
return "Spring in Action (Manning), Cloud Native Java (O'Reilly), Learning Spring Boot (Packt)";
}
public static void main(String[] args) {
SpringApplication.run(CircuitBreakerBookstoreApplication.class, args);
}
}
的@RestController
注释表示BookstoreApplication
是REST控制器类,可确保@RequestMapping
此类中的方法的行为就像用注释@ResponseBody
。也就是说,的返回值@RequestMapping
此类中的方法会自动从其原始类型适当地转换,并直接写入响应主体。
您将在带有消耗应用程序的应用程序的本地运行此应用程序。结果, src/main/resources/application.properties
,您需要设置server.port
因此,当我们开始运行时,Bookstore服务不会与使用中的应用程序冲突。以下清单(来自bookstore/src/main/resources/application.properties
)显示了操作方法:
server.port=8090
设置客户端微服务应用程序
阅读应用程序将是您的书店应用程序的消费者(建模访问者)。您可以在此处查看您的阅读清单/to-read
,然后从书店服务应用程序中检索该阅读列表。以下示例(摘自reading/src/main/java/com/example/circuitbreakerreading/CircuitBreakerReadingApplication.java
)显示了此类:
package com.example.circuitbreakerreading;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.web.client.RestTemplate;
@EnableCircuitBreaker
@RestController
@SpringBootApplication
public class CircuitBreakerReadingApplication {
@Autowired
private BookService bookService;
@Bean
public RestTemplate rest(RestTemplateBuilder builder) {
return builder.build();
}
@RequestMapping("/to-read")
public String toRead() {
return bookService.readingList();
}
public static void main(String[] args) {
SpringApplication.run(CircuitBreakerReadingApplication.class, args);
}
}
要从您的书店获取列表,可以使用Spring的RestTemplate
模板类。 RestTemplate
向书店服务的URL发出HTTP GET请求,并将结果返回为String
。(有关使用Spring消耗RESTful服务的更多信息,请参阅《 使用RESTful Web服务指南》。)为此,您需要添加server.port
财产reading/src/main/resources/application.properties
,如以下清单所示:
server.port=8080
您现在可以在浏览器中访问/to-read
阅读应用程序的端点并查看您的阅读列表。但是,由于我们依赖书店应用程序,因此如果发生任何事情或阅读应用程序无法访问书店,您将没有列表,并且用户将收到讨厌的HTTP 500错误消息。
应用断路器模式
Netflix的Hystrix库提供了断路器模式的实现。当您将断路器应用于某个方法时,Hystrix会监视对该方法的调用失败,并且如果失败累积到阈值,则Hystrix会断开电路,以便后续调用会自动失败。当电路断开时,Hystrix将调用重定向到该方法,然后将它们传递到您指定的后备方法。
Spring Cloud Netflix Hystrix会寻找带有注解的任何方法@HystrixCommand
注释并将该方法包装在连接到断路器的代理中,以便Hystrix可以对其进行监视。目前仅在标有的课程中有效@Component
要么@Service
。因此,在阅读应用程序下src/main/java/com/example/circuitbreakerreading
,您需要添加一个新类(称为BookService
)。
的RestTemplate
被注入到BookService
创建时。以下清单(来自reading/src/main/java/com/example/circuitbreakerreading/BookService.java
显示BookService
类):
package com.example.circuitbreakerreading;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.net.URI;
@Service
public class BookService {
private final RestTemplate restTemplate;
public BookService(RestTemplate rest) {
this.restTemplate = rest;
}
@HystrixCommand(fallbackMethod = "reliable")
public String readingList() {
URI uri = URI.create("http://localhost:8090/recommended");
return this.restTemplate.getForObject(uri, String.class);
}
public String reliable() {
return "Cloud Native Java (O'Reilly)";
}
}
您已申请@HystrixCommand
到你原来的readingList()
方法。您在这里还有一个新方法: reliable()
。的@HystrixCommand
注释具有reliable
就像它一样fallbackMethod
。如果由于某种原因,Hystrix断开了电路readingList()
,您将拥有一个很好的(如果很短的)占位符阅读列表,可供用户使用。
在我们的主要班级, ReadingApplication
,您需要创建一个RestTemplate
bean ,注入BookService
,并将其称为阅读清单。以下示例(摘自reading/src/main/java/com/example/circuitbreakerreading/CircuitBreakerReadingApplication.java
)显示了操作方法:
package com.example.circuitbreakerreading;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.web.client.RestTemplate;
@EnableCircuitBreaker
@RestController
@SpringBootApplication
public class CircuitBreakerReadingApplication {
@Autowired
private BookService bookService;
@Bean
public RestTemplate rest(RestTemplateBuilder builder) {
return builder.build();
}
@RequestMapping("/to-read")
public String toRead() {
return bookService.readingList();
}
public static void main(String[] args) {
SpringApplication.run(CircuitBreakerReadingApplication.class, args);
}
}
现在,要从Bookstore服务中检索列表,您可以调用bookService.readingList()
。您还应该添加最后一个注释, @EnableCircuitBreaker
。该注释告诉Spring Cloud读取应用程序使用断路器并启用对其的监视,断开和闭合(在我们的情况下,此行为由Hystrix提供)。
试试吧
要测试您的断路器,请同时运行书店服务和阅读服务,然后在以下位置打开阅读服务的浏览器: localhost:8080/to-read
。您应该会看到完整的建议阅读清单,如以下清单所示:
Spring in Action (Manning), Cloud Native Java (O'Reilly), Learning Spring Boot (Packt)
现在停止书店应用程序。您的列表来源不见了,但是多亏了Hystrix和Spring Cloud Netflix,您才有了可靠的缩写列表。您应该看到以下内容:
Cloud Native Java (O'Reilly)
摘要
恭喜你!您刚刚开发了一个Spring应用程序,该应用程序使用断路器模式来防止级联故障并为潜在的失败呼叫提供后备行为。
也可以看看
以下指南也可能会有所帮助:
是否要编写新指南或为现有指南做出贡献?查看我们的贡献准则 。
所有指南均以代码的ASLv2许可证和写作的Attribution,NoDerivatives创作共用许可证发布 。 |