Spring Cloud熔断器

以Netflix Hystrix断路器为例说明。

配置服务端应用

使用Spring Boot构建一个RESTful风格应用。

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

确保@RequestMapping行为具有@ResponseBody功能。

/src/main/resources/application.properties

server.port=8090

配置客户端应用

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

Spring RestTemplate从Bookstore获取数据。

src/main/resources/application.properties

server.port=8080

浏览器中访问客户端应用/to-read接口,客户端应用依赖Bookstore服务,如果Bookstore发生任何变化,导致客户端应用无法访问Bookstore服务,浏览器将收到HTTP 500消息。

断路器模式

Netflix Hystrix库提供断路器实现:

断路器应用于到一个方法上,Hystrix会监视方法上发生的失败调用,失败次数累积到指定阈值,Hystrix会开启熔断,后续调用自动失败。

当断路器打开时,Hystrix将调用重定向到指定的回退方法上。

Spring Cloud Netflix Hystrix会扫描所有使用@HystrixCommand注解的方法,将方法包装在一个连接到断路器的代理中,实现监视目的。

目前,仅适用于@Component、@Service注解的类。

/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()方法上。

新建一个trusted()方法作为失败回退方法。

Hystrix熔断readingList时,会将trusted方法的结果返回。

因此,@HystrixCommand注解的回退方法(fallbackMethod)应是可靠的。

ReadingApplication中创建一个RestTemplate bean,注入BookService以便调用readingList方法。

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

添加一个注释:

@EnableCircuitBreaker

告诉Spring Cloud此应用使用了断路器,需要启用监控,并在条件满足时打开和关闭熔断。

测试

浏览器访问localhost:8080/to-read:

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

关闭Bookstore服务,依然能看到应用的数据返回:

Cloud Native Java (O'Reilly)