springboot晋级之断路器
你将构建一个微服务应用程序,当方法调用失败时,使用 断路器模式 平滑的完成降级功能。使用断路器模式可以允许微服务程序在相关服务发生故障时继续运行,防止故障级联并给出故障恢复服务时间。
创建目录结构
在你选择的项目目录中,创建以下子目录结构。例如, 如果你使用的是Unix/Linux系统:mkdir -p src/main/java/hello :
└── src └── main └── java └── hello
bookstore/pom.xml
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>hello</groupId> <artifactId>bookstore</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.2.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <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>
reading/pom.xml
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>hello</groupId> <artifactId>reading</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.2.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency> <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> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Camden.SR5</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>
设置服务端微服务应用程序
书店服务将有一个端点。它可以访问/recommended,并(为了简单)返回一个String推荐的阅读列表。
在BookstoreApplication.java中编辑你的主类。应该看起来像这样:
bookstore/src/main/java/hello/BookstoreApplication.java
package hello; 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 BookstoreApplication { @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(BookstoreApplication.class, args); } }
在src/main/resources/ application.properties中设置server.port,以便当我们运行时,Bookstore服务不会与客户端冲突。
bookstore/src/main/resources/application.properties
server.port=8090
设置客户端微服务应用程序
阅读应用程序将是我们的书店应用服务的前端(我们可以看到)我们将能够通过/to-read查看我们的阅读列表,并将从书店服务应用程序检索该阅读列表。
reading/src/main/java/hello/ReadingApplication.java
package hello; 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; import org.springframework.web.client.RestTemplate; import java.net.URI; @RestController @SpringBootApplication public class ReadingApplication { @RequestMapping("/to-read") public String readingList() { RestTemplate restTemplate = new RestTemplate(); URI uri = URI.create("http://localhost:8090/recommended"); return restTemplate.getForObject(uri, String.class); } public static void main(String[] args) { SpringApplication.run(ReadingApplication.class, args); } }
将 server.port 属性添加到 src/main/resources/application.properties:reading/src/main/resources/application.properties
server.port=8080
我们现在可以在浏览器中访问我们的阅读应用程序的to-read端点,并查看我们的阅读列表。然而,由于我们依靠书店服务BookService,如果发生任何事情,或者如果阅读完全无法访问书店服务BookService,我们将没有列表,我们的用户将收到一个讨厌的HTTP 500错误消息。
应用断路器模式
Netflix的Hystrix库提供了断路器模式的实现:当我们将一个断路器应用于一个方法时,Hystrix会监控该方法的失败情况,如果故障达到阈值,Hystrix将打开断路器,以便后续访问该方法自动失败。当断路器打开时,Hystrix会重新调用该方法,并将它们传递到我们指定的回退方法。
Spring Cloud Netflix Hystrix查找使用@HystrixCommand注解的任何方法,并将该方法包装在连接到断路器的代理中,以便Hystrix可以监控它。 这当前只能在标有@Component或@Service的类中工作,所以在阅读应用程序中,在src/main/java/hello下,添加一个新类:BookService。
在创建BookService时,RestTemplate将被注入到BookService的构造函数中。完整的类应该是这样的:
reading/src/main/java/hello/BookService.java
package hello; 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注解作为它的回退方法是可靠的,所以如果由于某些原因Hystrix在readingList()上打开断路器,我们将为我们的用户准备一个非常好的(如果是短的)占位符阅读列表。
在我们的主类ReadingApplication中,我们将创建一个RestTemplate bean,注入BookService并将其称为阅读列表:
reading/src/main/java/hello/ReadingApplication.java
package hello; 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 ReadingApplication { @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(ReadingApplication.class, args); } }
现在,要从书店服务检索列表,我们调用bookService.readingList()。你还会注意到,我们添加了最后一个注解,@EnableCircuitBreaker; 告诉Spring Cloud有必要在使用阅读应用程序中使用断路器并启用它的监控功能,打开和关闭(在我们的例子中由Hystrix提供的行为)。
源代码地址:https://pan.baidu.com/s/1fHcPdcTTA8DIfplOGrOSQg
原文地址:http://www.spring4all.com/article/535
浙公网安备 33010602011771号