首先,之所以谈这个话题呢,是发现现在很多人对微服务的设计缺乏认识,所以写一篇扫盲文。当然,考虑到目前大多微服务的文章都是口水文,烟哥争取将实现方式讲透,点清楚,让大家有所收获!
OK,我要先说明一下,我有很长一段时间将服务降级和服务熔断混在一起,认为是一回事!
为什么我会有这样的误解呢?
针对下面的情形,如图所示:
当Service A
调用Service B
,失败多次达到一定阀值,Service A
不会再去调Service B
,而会去执行本地的降级方法!
对于这么一套机制:在Spring cloud中结合Hystrix,将其称为熔断降级!
所以我当时就以为是一回事了,毕竟熔断和降级是一起发生的,而且这二者的概念太相近了!后面接触了多了,发现自己理解的还是太狭隘了,因此本文中带着点我自己的见解,大家如果有不同意见,请轻喷!毕竟还有很多人认为两者是一致的!
OK,我们从服务雪崩开始讲起!假设存在如下调用链:
而此时,Service A
的流量波动很大,流量经常会突然性增加!那么在这种情况下,就算Service A
能扛得住请求,Service B
和Service C
未必能扛得住这突发的请求。
此时,如果Service C
因为抗不住请求,变得不可用。那么Service B
的请求也会阻塞,慢慢耗尽Service B
的线程资源,Service B
就会变得不可用。紧接着,Service A
也会不可用,这一过程如下图所示
如上图所示,一个服务失败,导致整条链路的服务都失败的情形,我们称之为服务雪崩。
那么,服务熔断和服务降级就可以视为解决服务雪崩的手段之一。
服务熔断:当下游的服务因为某种原因突然变得不可用或响应过慢,上游服务为了保证自己整体服务的可用性,不再继续调用目标服务,直接返回,快速释放资源。如果目标服务情况好转则恢复调用。Hystrix默认的超时时间为1s,请求时间超过1s,熔断次数加1。
熔断器机制:
参数修改:
熔断参数的 key,value
服务降级是从整个系统的负荷情况出发和考虑的,对某些负荷会比较高的情况,为了预防某些功能(业务场景)出现负荷过载或者响应慢的情况,在其内部暂时舍弃对一些非核心的接口和数据的请求,而直接返回一个提前准备好的fallback(退路)错误处理信息。这样,虽然提供的是一个有损的服务,但却保证了整个系统的稳定性和可用性。
相同点:
不同点:
1、Maven依赖:
org.springframework.cloud
spring-cloud-starter-eureka
org.springframework.cloud
spring-cloud-starter-feign
org.springframework.cloud
spring-cloud-starter-hystrix
2、修改启动类
在启动类上增加@EnableCircuitBreaker(客户端)注解:
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableCircuitBreaker
public class DeptProvider8001_Hystrix_App{
public static void main(String[] args){
SpringApplication.run(DeptProvider8001_Hystrix_App.class, args);
}
}
这里我们在启动类中又增加了@EnableCircuitBreaker注解,用来开启断路器功能。如果你觉得启动类上的注解个数有点多的话,可以使用一个@SpringCloudApplication 注解来代替@SpringBootApplication(或者@EnableEurekaServer)、@EnableDiscoveryClient、@EnableCircuitBreaker这三个注解。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}
3、Controller:
接下来,我们为接口增加断路器功能,修改部分代码如下:
@GetMapping("/msg/get")
@HystrixCommand(fallbackMethod = "getMsgFallback")
public Object getMsg() {
String msg = messageService.getMsg();
return msg;
}
public Object getMsgFallback() {
return "祝您 2019 猪年大吉,'猪'事如意!";
}
先启动Eureka,再启动一个8771端口的message-service服务,最后启动message-center。待启动完成之后,Eureka注册中心实例注册信息如下:
此时,访问 http://localhost:8781/api/v1/center/msg/get ,返回如下结果表明服务调用成功:
然后,停掉message-service服务,再次请求 http://localhost:8781/api/v1/center/msg/get ,返回结果如下:
可以看出fallback中的信息被直接返回了,表明Hystrix断路器调用成功。
注意:fallback方法的签名需要和原方法保持一致。
上述例子耦合性太强。
以MessageService的Feign客户端为例,为其添加Hystrix断路器功能。
1、修改Feign客户端
通过配置@FeignClient注解的fallback属性来位MessageServiceClient指定一个自定义的fallback处理类(MessageServiceFallback)。
@FeignClient(name = "message-service", fallback = MessageServiceFallback.class)
public interface MessageServiceClient {
@GetMapping("/api/v1/msg/get")
public String getMsg();
}
2、创建Fallback处理类
MessageServiceFallback需要实现MessageServiceClient接口,并且在Spring容器中必须存在一个该类型的有效Bean。在这里,我们使用@Component注解将其注入到Spring容器中。
@Component // 不要忘记添加,不要忘记添加
public class MessageServiceFallback implements FallbackFactory{
@Override
public MessageServiceClient create(Throwable throwable){
return new DeptClientService() {
@Override
public String getMsg(long id){
return new String("消息接口繁忙,请稍后重试!");
}
};
}
}
3、修改配置
在新版本的Springcloud中,Feign默认关闭了对Hystrix的支持,需要在application.yml进行配置:
feign:
hystrix:
enabled: true
当message-service服务不可用时,请求 http://localhost:8781/api/v1/center/msg/get,返回结果如下:
使用Hystrix一个最大的好处就是它会为我们自动收集每一个HystrixCommand的信息,并利用Hystrix-Dashboard通过一种高效的方式对每一个断路器的健康状态进行展示。
值得注意的是,在使用HystrixCommand对RibbonClient进行包装的时候,你需要确保你配置的Hystrix超时时间要比Ribbon的超时时间长,包括由它们引起的重试时间,举个例子:如果你的Ribbon连接超时时间是1秒,并且Ribbon会连续重试请求3次,那么你的Hystrix连接超时时间需要配置成稍大于3秒。
1、引入Hystrix-Dashboard依赖
在 pom.xml 文件中引入Hystrix-Dashboard依赖:
org.springframework.cloud
spring-cloud-starter-hystrix
org.springframework.cloud
spring-cloud-starter-hystrix-dashboard
2、修改启动类
在MessageCenterApplication启动类上增加@EnableHystrixDashboard注解:
@EnableFeignClients
@SpringCloudApplication
@EnableHystrixDashboard
public class MessageCenterApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(MessageCenterApplication.class).web(WebApplicationType.SERVLET).run(args);
}
}
启动应用,访问 http://localhost:8781/hystrix ,打开Hystrix-Dashboard监控首页。
在这里配置好需要监控的Hystrix流地址 http://localhost:8781/actuator/hystrix.stream ,开始监控。
参考文章:
https://blog.csdn.net/pengjunlee/article/details/86688858
https://github.com/netflix/hystrix