1.概述
在本文中我们将介绍Spring Cloud Netflix Hystrix - 断路器。我们将使用该库来实现断路器的企业模式,该模式描述了应用程序中不同级别的故障级联策略。
断路器的工作原理类似于电子产品:Hystrix 用来观察正在调用某些相关服务的方法。如果出现了故障,它将打开断路器并将呼叫转发到回退方法。
该库将设置失败次数的阈值,正常情况下它将使电路保持开放状态。当超过容忍失败次数的阈值后,它会将所有后续调用转发给回退方法,以防止将来出现故障。这为相关服务创建了一个时间缓冲区,以便从其失败状态中恢复。
2. 服务提供者
要创建演示断路器模式的场景,我们首先需要一个服务。我们将其命名为“ REST Producer”,因为它为启用Hystrix的“ REST消费者 ” 提供数据。
让我们使用spring-boot-starter-web依赖创建一个新的Maven项目:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
项目本身有意保持简单。它包括了一个控制器接口,里面的GET方法使用@RequestMapping注解绑定了访问地址,此方法简单地返回一个字符串;一个@RestController实现此接口和一个@SpringBootApplication。
首先是服务接口
public interface GreetingController {
@RequestMapping("/greeting/{username}")
String greeting(@PathVariable("username") String username);
}
然后是实现类
@RestController
public class GreetingControllerImpl implements GreetingController {
@Override
public String greeting(@PathVariable("username") String username) {
return String.format("Hello %s!\n", username);
}
}
接下来是主要的应用程序类
@SpringBootApplication
public class RestProducerApplication {
public static void main(String[] args) {
SpringApplication.run(RestProducerApplication.class, args);
}
}
此外,我们定义一个应用程序名称,以便能够从我们稍后将介绍的客户端应用程序中查找我们的“ REST Producer ”。让我们创建一个包含以下内容的application.properties:
spring.application.name=rest-producer
server.port=9090
现在我们可以使用curl 测试我们的' REST Producer '了:
$> curl http://localhost:9090/greeting/Peter
Hello Peter!
3.使用Hystrix的服务消费者
对于我们的演示场景,我们将实现一个Web应用程序,它使用RestTemplate和Hystrix调用上一步中的REST服务。为简单起见,我们将其称为“ REST消费者 ”。
因此,我们创建了一个新的Maven项目,其中包含spring-cloud -starter- hystrix ,spring-boot-starter-web和spring-boot-starter-thymeleaf作为依赖项:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
要使断路器工作,Hystix将扫描@Component或@Service注解类以获取@HystixCommand注解方法,为其实现代理并监视其调用。
我们将首先创建一个@Service类,它将被注入@Controller。由于我们正在使用Thymeleaf构建Web应用程序,因此我们还需要一个HTML模板作为视图。
同时在注入@Service的类中实现@HystrixCommand以及相关的回退方法。
@Service
public class GreetingService {
@HystrixCommand(fallbackMethod = "defaultGreeting")
public String getGreeting(String username) {
return new RestTemplate().getForObject("http://localhost:9090/greeting/{username}", String.class, username);
}
@SuppressWarnings("unused")
private String defaultGreeting(String username) {
return "Hello User!";
}
}
RestConsumerApplication将是我们的主要应用程序类。该@EnableCircuitBreaker注解将扫描任何兼容的类路径断路器实现。
@SpringBootApplication
@EnableCircuitBreaker
public class RestConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(RestConsumerApplication.class, args);
}
}
我们将使用GreetingService设置控制器:
@Controller
public class GreetingController {
@Autowired
private GreetingService greetingService;
@RequestMapping("/get-greeting/{username}")
public String getGreeting(Model model, @PathVariable("username") String username) {
model.addAttribute("greeting", greetingService.getGreeting(username));
return "greeting-view";
}
}
这是HTML模板:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Greetings from Hystrix</title>
</head>
<body>
<h2 th:text="${greeting}"/>
</body>
</html>
为确保应用程序正在侦听已定义的端口,我们将以下内容放在application.properties文件中:
server.port=8080
为了查看正在运行的Hystix断路器,我们将启动“ REST Consumer ”并用浏览器访问http://localhost:8080/get-greeting/Peter。在正常情况下,将显示以下内容:
Hello Peter!
为了模拟我们的' REST Producer ' 的失败,我们停止它然后刷新浏览器,我们应该会看到一个通用消息,从@Service中的fallback方法返回:
Hello User!
4.使用Hystrix和Feign的REST消费者
现在,我们将使用Spring Netflix Feign作为声明性REST客户端,而不是Spring RestTemplate。
这种方法的优点是我们以后能够轻松地重构我们的Feign Client界面,以使用Spring Netflix Eureka进行服务发现。
为了启动新项目,我们将制作“ REST Consumer ” 的副本,并添加spring-cloud-starter-feign作为依赖项:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
现在,我们可以使用GreetingController来扩展Feign客户端。@FeignClient的name属性是必需的。如果给出此属性,则可以使用Eureka客户端或URL通过服务发现来查找应用程序。
@FeignClient(name = "rest-producer", url = "http://localhost:9090", fallback = GreetingClientFallback.class)
public interface GreetingClient {
@RequestMapping("/greeting/{username}")
String greeting(@PathVariable("username") String username);
}
我们将Hystrix回退实现为使用@Component注解的类。
@Component
public class GreetingClientFallback implements GreetingClient {
@Override
public String greeting(@PathVariable("username") String username) {
return "Hello User!";
}
}
在RestConsumerFeignApplication中,我们将添加一个额外的注解,以实现Feign集成,添加@EnableFeignClients到主应用程序类:
@SpringBootApplication
@EnableFeignClients
@EnableCircuitBreaker
public class RestConsumerFeignApplication {
public static void main(String[] args) {
SpringApplication.run(RestConsumerFeignApplication.class, args);
}
}
我们将修改控制器以使用自动连接的Feign Client而不是之前注入的@Service来访问greeting服务:
@Controller
public class GreetingController {
@Autowired
private GreetingClient greetingClient;
@RequestMapping("/get-greeting/{username}")
public String getGreeting(Model model, @PathVariable("username") String username) {
model.addAttribute("greeting", greetingClient.greeting(username));
return "greeting-view";
}
}
最后,我们将测试这个Feign-enabled的 ' REST Consumer ',就像上一节中的那样。预期结果应该是相同的。
5. Hystrix仪表板
Hystrix的一个不错的可选功能是能够在仪表板上监控其状态。
为了实现它,我们将spring-cloud-starter-hystrix-dashboard和spring-boot-starter-actuator放在我们的' REST Consumer ' 的pom.xml中:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
前者需要通过使用@EnableHystrixDashboard注解来启用,后者会自动在我们的Web应用程序中启用所需的指标。
在我们重新启动应用程序之后,我们在浏览器中访问http://localhost:8080/hystrix,输入'http://localhost:8080/hystrix.stream ' 的指标URL 并开始监控。
最后,我们应该看到这样的事情:
监视' hystrix.stream '是好的,但是如果你必须观看多个启用Hystrix的应用程序,它将变得不方便。为此,Spring Cloud提供了一个名为Turbine的工具,它可以聚合流以在一个Hystrix仪表板中显示。
6.结论
正如我们目前所见,我们现在能够使用Spring Cloud Netflix Hystrix以及Spring RestTemplate或Spring Cloud Netflix Feign实现断路器模式。
这意味着我们能够使用“静态”或“默认”数据来使用包含回退的服务,并且我们能够监控此数据的使用情况。示例工程下载地址
网友评论