断路器

断路器

断路器

Circuit Breaker

此教程通过使用Netflix Hystrix容错库在可能失败的方法调用中应用断路器。

This guide walks you through the process of applying circuit breakers to potentially-failing method calls using the Netflix Hystrix fault tolerance library.

将要做什么

What you’ll build

你将使用一个断路器模式构建一个微服务应用,在方法调用失败时将降级服务。当一个相关的服务失败时,使用断路器模式将允许一个微服务继续执行,防止失败传递并让失败的服务有时间恢复。

You’ll build a microservice application that uses the Circuit Breaker pattern to gracefully degrade functionality when a method call fails. Use of the Circuit Breaker pattern can allow a microservice to continue operating when a related service fails, preventing the failure from cascading and giving the failing service time to recover.

需要些什么

What you’ll need

如何完成此教程

How to complete this guide

与大多数Spring的入门教程相似,你可以从头开始并完成每一步,或者你也可以跳过你熟悉的设置步骤。无论怎样,你最终应当以有效代码结束。

Like most Spring Getting Started guides, you can start from scratch and complete each step, or you can bypass basic setup steps that are already familiar to you. Either way, you end up with working code.

如果从头开始,可参考使用Gradle构建

To start from scratch, move on to Build with Gradle.

如果要跳过基本步骤,按如下步骤:

To skip the basics, do the following:

  • 下载并解压此教程的源码仓库,或者使用Git进行clone:git clone https://github.com/spring-guides/gs-circuit-breaker.git
  • 进入gs-serving-web-content/initial目录
  • 跳至创建一个服务端微服务应用.

当你完成时,你可以与gs-serving-web-content/complete中的代码对比检查。

When you’re finished, you can check your results against the code in gs-circuit-breaker/complete.

创建一个服务端微服务应用

Set up a server microservice application

Bookstore服务将有一个单端点。可通过/recommended访问,并返回一个推荐书籍列表的String字符串。

The Bookstore service will have a single endpoint. It will be accessible at /recommended, and will (for simplicity) return a String recommended reading list.

BookstoreApplication.java修改main类,如下:

Edit our main class, in BookstoreApplication.java. It should look like this:

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);
  }
}

@RestController注解将BookstoreApplication标记为控制器类,与@Controller类似,并确保在此类中有@RequestMapping的方法可以自动注解@ResponseBody。在此类中的@RequestMapping方法的返回值将自动转换并直接写入响应体。

The @RestController annotation marks BookstoreApplication as a controller class, like @Controller does, and also ensures that @RequestMapping methods in this class will behave as though annotated with @ResponseBody. That is, the return values of @RequestMapping methods in this class will be automatically converted appropriately from their original types and will be written directly to the response body.

我们将在本地同时运行此应用与一个客户端服务应用,所以要在src/main/resources/application.properties设置server.port,以避免Bookstore服务的端口与客户端的端口冲突。

We’re going to run this application locally alongside a client service application, so in src/main/resources/application.properties, set server.port so that the Bookstore service won’t conflict with the client when we get that running.

bookstore/src/main/resources/application.properties

server.port=8090

创建一个客户端微服务应用

Set up a client microservice application

Reading应用将作为Bookstore应用的前端(假定是)。我们将通过访问/to-read查看书籍列表,书籍列表是从Bookstore服务中获取。

The Reading application will be our front-end (as it were) to the Bookstore application. We’ll be able to view our reading list there at /to-read, and that reading list will be retrieved from the Bookstore service application.

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);
  }
}

为了从Bookstore获取列表,我们将使用Spring的RestTemplate模板类。RestTemplate创建一个HTTP GET请求访问我们提供的Bookstore服务的URL,并将结果作为String字符串返回。(可以查看消费RESTful Web服务教程,来获取更多关于使用Spring来消费一个RESTful服务的信息。)

To get the list from Bookstore, we’re using Spring’s RestTemplate template class. RestTemplate makes an HTTP GET request to the Bookstore service’s URL as we provide it and then returns the result as a String. (For more information on using Spring to consume a RESTful service, see the Consuming a RESTful Web Service guide.)

并在src/main/resources/application.properties中添加server.port属性:

Add the server.port property to src/main/resources/application.properties:

reading/src/main/resources/application.properties

server.port=8080

我们可以在浏览器中通过/to-read端点来访问我们的Reading应用,然后就可以看见书籍列表。因为现在我们是依赖Bookstore应用,如果此应用出现什么问题,或者Reading不能访问Bookstore了,则将无法获取书籍列表,并且用户将看见HTTP 500错误信息。

We now can access, in a browser, the /to-read endpoint on our Reading application, and see our reading list. Yet since we rely on the Bookstore application, if anything happens to it, or if Reading is simply unable to access Bookstore, we’ll have no list and our users will get a nasty HTTP 500 error message.

应用断路器模式

Apply the Circuit Breaker pattern

Netflix的Hystrix库提供了断路器模式的一种实现:当在一个方法上应用一个断路器时,Hystrix将监视此方法的失败调用,如果失败达到一个阈值,Hystrix将断路,所以后续的调用将自动失败。当断路时,Hystrix将直接调用此方法,并传递到我们指定的回调方法。

Netflix’s Hystrix library provides an implementation of the Circuit Breaker pattern: when we apply a circuit breaker to a method, Hystrix watches for failing calls to that method, and if failures build up to a threshold, Hystrix opens the circuit so that subsequent calls automatically fail. While the circuit is open, Hystrix redirects calls to the method, and they’re passed on to our specified fallback method.

Spring Cloud Netflix Hystrix将搜索所有使用@HystrixCommand注解的方法,并封装此方法使其连接到一个断路器代理,使得Hystrix可以监控它。当前只在标记了@Component或者@Service的类中起效,所以需要在Reading应用的src/main/java/hello目录下,添加一个新类:BookService

Spring Cloud Netflix Hystrix looks for any method annotated with the @HystrixCommand annotation, and wraps that method in a proxy connected to a circuit breaker so that Hystrix can monitor it. This currently only works in a class marked with @Component or @Service, so in the Reading application, under src/main/java/hello, add a new class: BookService.

BookService的构造中将注入RestTemplate。完整的类如下:

The RestTemplate will be injected into the constructor of the BookService when it is created. The complete class should look like this:

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)";
  }

}

我们在开始的readingList()方法上应用@HystrixCommand。还创建了一个新方法:reliable()@HystrixCommand注解将reliable作为了其fallbackMethod回调方法,在某种情况下,Hystrix将在readingList()方法上断路,用户将得到一个替补书籍列表。

We’ve applied @HystrixCommand to our original readingList() method. We also have a new method here: reliable(). The @HystrixCommand annotation has reliable as its fallbackMethod, so if, for some reason, Hystrix opens the circuit on readingList(), we’ll have an excellent (if short) placeholder reading list ready for our users.

在主类ReadingApplication中,我们将创建一个RestTemplate bean,注入到BookService,并调用它来获取书籍列表:

In our main class, ReadingApplication, we will create a RestTemplate bean, inject the BookService and call it for our reading list:

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(),从Bookstore服务获取列表。你可能注意到我们在最后加了一个注解@EnableCircuitBreaker;这是用来告诉Spring Cloud我们的Reading应用使用了断路器,并且开启了监控、断路、闭路等功能(在此例中是Hystrix支持了这些行为)。

Now, to retrieve the list from the Bookstore service, we call bookService.readingList(). You’ll also notice that we’ve added one last annotation, @EnableCircuitBreaker; that’s necessary to tell Spring Cloud that the Reading application uses circuit breakers and to enable their monitoring, opening, and closing (behavior supplied, in our case, by Hystrix).

试一试

Try it out

同时运行Bookstore服务和Reading服务,打开浏览器通过localhost:8080/to-read访问Reading服务。你可以看见完成的推荐书籍列表:

Run both the Bookstore service and the Reading service, and then open a browser to the Reading service, at localhost:8080/to-read. You should see the complete recommended reading list:

Spring in Action (Manning), Cloud Native Java (O'Reilly), Learning Spring Boot (Packt)

现在关掉Bookstore应用。此时就没有书籍列表来源了,但由于Hystrix和Spring Cloud Netflix,我们可以获取到一个简短的列表:

Now shut down the Bookstore application. Our list source is gone, but thanks to Hystrix and Spring Cloud Netflix, we have a reliable abbreviated list to stand in the gap; you should see:

Cloud Native Java (O'Reilly)

总结

Summary

恭喜!你完成了使用断路器模式来开发一个Spring应用,可以防止失败传递,并为潜在的失败调用提供了回调行为。

Congratulations! You’ve just developed a Spring application that uses the Circuit Breaker pattern to protect against cascading failures and to provide fallback behavior for potentially failing calls.

翻译部分版权归YahaCode团队所有。仅供学习研究之用,任何组织或个人不得私自以此用于任何形式的商业目的

发表评论