序言
在微服务架构中,根据业务来拆分成一个个的服务,服务与服务之间可以通过 RPC
相互调用,在 Spring Cloud 中可以用 RestTemplate + Ribbon
和 Feign
来调用。为了保证其高可用,单个服务通常会集群部署。由于网络原因或者自身的原因,服务并不能保证 100% 可用,如果单个服务出现问题,调用这个服务就会出现线程阻塞,此时若有大量的请求涌入,Servlet
容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的 “雪崩” 效应。 为了解决这个问题,业界提出了熔断器模型。
Netflix 开源了 Hystrix 组件,实现了熔断器模式。
此文章仅限入门 SpringCloud版本为 Greenwich
当然 Hystrix 已经进入维护阶段了,也就是说不再会有新功能产出,但是已经足够成熟。Spring Cloud 正在孵化自己的熔断器 Resilience4j ,最近阿里的 Sentinel 也发布了可用于生产的版本。
使用
首先呢加入如下依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
</dependencies>
在yml里配置一下注册中心
server:
port: 7001
spring:
application:
name: spring-cloud-action-server-order
eureka:
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.ip-address}:${spring.application.instance_id:${server.port}}
hostname: localhost
client:
service-url:
defaultZone: http://${eureka.instance.hostname}:8761/eureka/
然后呢是启动类
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableHystrix
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(ATestApplication.class, args);
}
}
其实还有一个注解可以 同时包含@EnableDiscoveryClient 、@EnableDiscoveryClient、@EnableHystrix
换成@SpringCloudApplication
就行了
@SpringCloudApplication
@EnableFeignClients
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
在Ribbon中使用
在 Ribbon 调用方法上增加 @HystrixCommand
注解并指定 fallbackMethod
熔断方法
@RestController
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "getProductsError")
@GetMapping
public String getOrder() {
return restTemplate.getForObject("http://SPRING-CLOUD-ACTION-SERVER-B/getProducts, String.class);
}
public String getProductsError(String message) {
return "Hi,your request error.";
}
}
怎么测试呢? 当我关闭 spring-cloud-action-server-product
服务时,访问@HystrixCommand
注解标注的接口时候,我们发现直接返回了getProductsError
里的内容,就表示服务已经熔断。
这里说一点高级用法,如果想使用Hystrix 的详细配置,可以 使用@HystrixCommand
将commandProperties
属性与@HystrixProperty
注释列表一起使用 。
比如设置一个超时
@HystrixCommand(commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "15000")
}
)
或者这样使用
@HystrixCommand(commandProperties = {@HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_THREAD_TIMEOUT_IN_MILLISECONDS, value = "15000")})
Hystrix 还而已通过信号量来实现限流,等功能,具体可以在 其 github仓库的wiki 里详细的看到。
Feign 中使用熔断器
Feign 是自带熔断器的,但默认是关闭的。需要在配置文件中配置打开它,在配置文件增加以下代码
feign:
hystrix:
enabled: true
然后在Feign的接口中增加forback指定类
@FeignClient(value = "spring-cloud-action-server-product",fallback =ProductService.FallbackProductService.class )
public interface ProductService {
@GetMapping("/getProducts")
String getProducts();
@Component
class FallbackProductService implements ProductService {
@Override
public String query() {
return "访问出现问题";
}
}
}
然后在调用Feign的时候也就会带有熔断的效果啦。
仪表盘
除了隔离依赖服务的调用以外,Hystrix还提供了近实时的监控,Hystrix会实时、累加地记录所有关于HystrixCommand的执行信息,包括每秒执行多少请求多少成功,多少失败等。Netflix通过hystrix-metrics-event-stream
项目实现了对以上指标的监控。
添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
然后在启动类中加入
@SpringCloudApplication
@EnableFeignClients
@EnableHystrixDashboard
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
然后加入 HystrixMetricsStreamServlet
的配置
@Configuration
public class HystrixDashboardConfig {
@Bean
public ServletRegistrationBean getServlet() {
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
}
打开项目 访问 http://localhost:7001/hystrix
就可以啦
输入相应的玩意设置一下标题就可以进入控制台了,只要触发了Hystrix
熔断 就会显示在控制台中。
给一个详细的说明图解
什么情况下会触发 fallback
方法
名字 | 描述 | 触发fallback |
---|---|---|
EMIT | 值传递 | NO |
SUCCESS | 执行完成,没有错误 | NO |
FAILURE | 执行抛出异常 | YES |
TIMEOUT | 执行开始,但没有在允许的时间内完成 | YES |
BAD_REQUEST | 执行抛出HystrixBadRequestException | NO |
SHORT_CIRCUITED | 断路器打开,不尝试执行 | YES |
THREAD_POOL_REJECTED | 线程池拒绝,不尝试执行 | YES |
SEMAPHORE_REJECTED | 信号量拒绝,不尝试执行 | YES |
fallback
方法在什么情况下会抛出异常
名字 | 描述 | 抛异常 |
---|---|---|
FALLBACK_EMIT | Fallback值传递 | NO |
FALLBACK_SUCCESS | Fallback执行完成,没有错误 | NO |
FALLBACK_FAILURE | Fallback执行抛出出错 | YES |
FALLBACK_REJECTED | Fallback信号量拒绝,不尝试执行 | YES |
FALLBACK_MISSING | 没有Fallback实例 | YES |
注意
Hystrix在执行他的逻辑的时候,其实做了来回的线程切换,所以说很容易导致一些问题,比如ThreadLocal 或者 Spring 声明式事物的失效。所以是用需要仔细考虑。
此文章仅限入门,切记啊不会用找不到多去官网看文档!