Spring Cloud熔断器入门指南

本指南将介绍如何使用Netflix Hystrix容错库(fault tolerance library)作为应用的断路器,以便在服务失败时执行其他调用。

将构建一个使用断路器模式的微服务应用程序,以便在方法调用失败时优雅地对应用进行降级。使用断路器模式能够让微服务,在相关服务出现故障时仍能继续运行,从而防止级联故障,并为服务恢复留出时间。

Spring Cloud熔断器应用构建环境

JDK 1.8 或更新

Gradle 4+ 或 Maven 3.2+

配置微服务应用

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

@RestController注解将BookstoreApplication标记为Controller,以此,确保该类中的@RequestMapping行为具有@ResponseBody的功能,将自动对原始类型进行适当地转换,并直接写入响应体。

因为本地还有其他服务运行,所以,设置应用端口很有必要。

/src/main/resources/application.properties

server.port=8090

配置微服务客户端应用

使用Spring Boot构建一个RESTful风格的微服务客户端应用程序。

/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获取数据,使用RestTemplate发出HTTP GET请求,并返回字符串结果。

配置客户端应用端口

src/main/resources/application.properties

server.port=8080

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

使用断路器模式

Netflix的Hystrix库提供了断路器模式的实现:当将断路器应用于到一个方法上时,Hystrix会监视该方法上发现的失败调用,如果失败次数累积到一定阈值,Hystrix会开启熔断,以便后续调用自动失败。当断路器打开时,Hystrix将调用重定向到指定的回退方法上。

Spring Cloud Netflix Hystrix会查找所有使用@HystrixCommand注解的方法,并将该方法包装在一个连接到断路器的代理中,以便Hystrix可以监视它。目前,它仅适用于标记为@Component或@Service的类,因此,需要在客户端应用中创建一个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此应用程序使用了断路器,需要开启监视,并在条件满足时打开和关闭熔断,在这个例子中由Hystrix提供此行为。

测试Spring Cloud熔断器

使用浏览器访问localhost:8080/to-read,查看服务的行为。

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

现在关闭Bookstore服务,由于使用了Hystrix和Spring Cloud Netflix,依然可以看到客户端应用返回了数据:

Cloud Native Java (O'Reilly)