最近,在我的一个项目中,我要求对失败的Web服务调用执行后备调用。 为了实现相同的功能,我一直在寻找断路器模式的实现,最后遇到了Netflix Hystrix库,我发现它是根据我们的应用程序最适合的库。
在这篇文章中,我试图展示一个简单的例子来说明我们的问题,以及Hystrix如何使用单个微服务和一个客户端以及Hystrix Dashboard来访问它来解决同样的问题。 在开始编码之前,让我们简要了解一下Hystrix是什么以及它在内部如何工作。
什么是Hystrix?
Hystrix是一个库,可通过添加等待时间容限和容错逻辑来帮助我们控制分布式服务之间的交互。 它通过隔离服务之间的访问点,停止服务之间的级联故障并提供后备选项来实现此目的,所有这些都改善了系统的整体弹性。
它实现了断路器模式,当电路达到指定的阈值且错误百分比超过阈值错误百分比时,断路器模式将在断路器从合闸转换为分闸时起作用。 当它断开时,它会使针对该断路器的所有请求短路。 在一段时间之后,下一个单个请求被允许通过(这是HALF-OPEN状态)。 如果请求失败,断路器将在睡眠窗口期间返回OPEN状态。 如果请求成功,断路器将转换为CLOSED,并且针对该断路器发出的所有请求都将传递到服务。 您可以在这里探索更多。
现在,让我们开始创建在端口8090和客户端上运行的员工服务微服务 ,以通过以下步骤与Hystrix仪表板一起访问该服务:
步骤1:根据以下图像,转到start.spring.io并添加Web启动器,以创建一个新的项目雇员服务 :
步骤2:编辑EmployeeServiceApplication.java ,添加一个返回雇员列表的方法,如下所示:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class EmployeeServiceApplication {
public static void main(String[] args) {
SpringApplication.run(EmployeeServiceApplication.class, args);
}
@RequestMapping(value = "/list")
public String list() {
return "Arpit, Sanjeev, Abhishek";
}
}
步骤3:编辑application.properties以指定服务的应用程序名称和端口号,如下所示:
server.port=8090
spring.application.name=employee-service
步骤4:移至employee-service目录并运行命令: mvn spring-boot:run 。 运行后,打开http:// localhost:8090 / list 。
接下来,我们将创建hystrix-client ,该客户端将访问我们新创建的employee-service ,如果该服务关闭,将返回fallback方法的响应。
步骤5:转到start.spring.io并基于下图创建一个新的项目hystrix-client,添加Web,Hystrix和Actuator起动器:
步骤6:编辑HystrixClientApplication.java ,添加一个方法,该方法调用employee-service以获取响应,并且由于某种原因,如果服务关闭或不可用,则从fallback方法返回响应,如下所示:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.test.service.IEmployeeService;
@EnableHystrix
@EnableCircuitBreaker
@SpringBootApplication
@RestController
@ComponentScan(basePackages = { "com.test.service" })
public class HystrixClientApplication {
@Autowired
private IEmployeeService employeeService;
public static void main(String[] args) {
SpringApplication.run(HystrixClientApplication.class, args);
}
@RequestMapping("/list")
public String list() {
return employeeService.list();
}
static class ApplicationConfig extends WebMvcConfigurerAdapter {
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
}
步骤7:在com.test.service包下创建接口IEmployeeService及其实现类EmployeeServiceImpl ,并按如下所示进行编辑:
IEmployeeService.java
package com.test.service;
public interface IEmployeeService {
String list();
}
EmployeeServiceImpl.java
package com.test.service.impl;
import java.net.URI;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.test.service.IEmployeeService;
@Service
public class EmployeeServiceImpl implements IEmployeeService {
@Value("#{'${employee.service.url}'}")
private String employeeServiceUrl;
@HystrixCommand(commandProperties = {
@HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),
@HystrixProperty(name = "execution.timeout.enabled", value = "true"),
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "500"),
@HystrixProperty(name = "execution.isolation.thread.interruptOnTimeout", value = "true"),
@HystrixProperty(name = "fallback.enabled", value = "true"),
@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "1000"),
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "10"),
@HystrixProperty(name = "circuitBreaker.forceOpen", value = "false"),
@HystrixProperty(name = "circuitBreaker.forceClosed", value = "false") }, fallbackMethod = "fallback", commandKey = "list", groupKey = "EmployeeServiceImpl", threadPoolKey = "thread-pool-employee-service", threadPoolProperties = { @HystrixProperty(name = "coreSize", value = "5") }, ignoreExceptions = { IllegalAccessException.class })
public String list() {
RestTemplate restTemplate = new RestTemplate();
URI uri = URI.create(employeeServiceUrl + "/list");
return restTemplate.getForObject(uri, String.class);
}
public String fallback() {
return "Fallback call, seems employee service is down";
}
}
上面指定的@HystrixCommand用于包装将执行具有潜在风险功能的代码,这些功能具有容错和等待时间容限,统计信息和性能指标捕获,断路器和隔板功能。
上面指定的@HystrixProperty用于控制HystrixCommand行为。 这里列出了所有可用的选项。
步骤8:编辑application.properties以指定应在其上运行hystrix-client的应用程序端口以及在其上可使用employee-service的 url,如下所示:
server.port=8080
employee.service.url=http://localhost:8090
步骤9:移至hystrix-client目录并运行命令: mvn spring-boot:run 。 运行后,打开http:// localhost:8080 / list 。
Hystrix在工作吗?
关闭员工服务应用程序。 应该看到后备消息: 后备呼叫,似乎员工服务已关闭 。
接下来,我们将创建Hystrix仪表板,它将为我们提供成功和失败请求,电路状态,主机,群集和线程池状态的图形视图。
步骤10:转到start.spring.io并添加一个Hystrix Dashboard启动器,创建一个新项目hystrix-dashboard 。 创建完成后 ,编辑HystrixDashboardApplication.java ,如下所示:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixDashboardApplication.class, args);
}
}
步骤11:编辑application.properties以指定应在其上运行hystrix-dashboard的应用程序端口,如下所示:
server.port=8383
步骤12:移至hystrix-dashboard目录并运行命令: mvn spring-boot:run 。 运行后,打开http:// localhost:8383 / hystrix并在流文本框中输入http:// localhost:8080 / hystrix.stream并单击Monitor Stream 。 加载仪表板后,我们将看到类似于以下图像:
完整的源代码托管在github上 。