原文地址:Spring Cloud 入门 之 Hystrix 篇(四)

博客地址:http://www.extlight.com

一、前言

在微服务应用中,服务存在一定的依赖关系,如果某个目标服务调用慢或者有大量超时造成服务不可用,间接导致其他的依赖服务不可用,最严重的可能会阻塞整条依赖链,最终导致业务系统崩溃(又称雪崩效应)。

上述的问题将是本篇需要解决的问题。

二、简单介绍

2.1 请求熔断

断路器是一种开关设置,当某个服务单元发生故障之后,通过断路器的故障监控,向调用方返回一个符合预期的服务降级处理(fallback),而不是长时间的等待或者抛出调用方无法处理的异常,这样保证了服务调用方的线程不会长时间被占用,从而避免了故障在分布式系统的蔓延乃至崩溃。

2.2 服务降级

fallback 相当于是降级操作。对于查询操作, 我们可以实现一个 fallback 方法, 当请求后端服务出现异常的时候, 可以使用 fallback 方法返回的值。 fallback 方法的返回值一般是设置的默认值或者来自缓存,告知后面的请求服务不可用了,不要再请求了。

2.3 请求熔断和服务降级区别

相同:

目标一致:为了防止系统崩溃而实施的一种防御手段

表现形式一致:当请求目标在一定时间内无响应时,返回或执行默认响应内容

不同:

触发条件不同:下游服务出现故障触发请求熔断。系统负荷超过阈值触发服务降级。

管理目标层次不同:请求熔断针对所有微服务。服务降级针对整个系统中的外围服务。

2.4 实现方案

Spring Cloud Hystrix 实现了断路器、线程隔离等一系列服务保护功能。它是基于 Netflix 的开源框架 Hystrix 实现的,该框架的目的在于通过控制访问远程系统、服务和第三方库节点,从而对延迟和故障提供更强大的容错能力。

Hystrix 具备服务熔断、服务降级、线程和信号隔离、请求缓存、请求合并以及服务监控的能力。

三、请求熔断实战

本次测试案例基于之前发表的文章中介绍的案例进行演示,不清楚的读者请先转移至 《Spring Cloud 入门 之 Feign 篇(三)》 进行浏览。

现在的项目列表如下:

服务实例 端口 描述
common-api - 公用的 api,如:实体类
eureka-server 9000 注册中心(Eureka 服务端)
goods-server 8081 商品服务(Eureka 客户端)
goods-server-02 8082 商品服务(Eureka 客户端)
goods-server-03 8083 商品服务(Eureka 客户端)
order-server 8100 订单服务(Eureka 客户端)

在 order-server 项目中:

3.1 添加依赖

<!-- hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

3.2 设置熔断策略

我们来修改获取下订单的方法,在 placeOrder 方法上加 @HystrixCommand 注解:

@Service
public class OrderServiceImpl implements OrderService{ @Autowired
private RestTemplate restTemplate; // @Autowired
// private GoodsServiceClient goodsServiceClient; @HystrixCommand(fallbackMethod = "defaultByPlaceOrder")
@Override
public void placeOrder(Order order) throws Exception{ Result result = this.restTemplate.getForObject("http://GOODS/goods/goodsInfo/" + order.getGoodsId(), Result.class); // Result result = this.goodsServiceClient.goodsInfo(order.getGoodsId()); if (result != null && result.getCode() == 200) {
System.out.println("=====下订单====");
System.out.println(result.getData());
} else {
System.out.println(result.getMsg());
}
} public void defaultByPlaceOrder(Order order) {
System.out.println("商品服务系统异常");
}
}

当调用商品服务超时或出现异常时,Hystrix 会调用 @HystrixCommand 中指定的 fallbackMethod 方法获取返回值或执行异常处理。

注意:fallbackMethod 方法要求与正常方法有相同的入参和回参。

3.3 启动熔断功能

在启动类上添加 @EnableCircuitBreaker 注解:

@EnableCircuitBreaker
@EnableEurekaClient
@SpringBootApplication
public class OrderServerApplication { public static void main(String[] args) {
SpringApplication.run(OrderServerApplication.class, args);
}
}

3.4 熔断测试

  1. 我们首先演示没有开启熔断的功能,即先把上边的 @EnableCircuitBreaker 注解进行注释。

启动好所有项目,使用 Postman 请求 order-server 进行下单操作,运行结果如下:

当我们请求发送的 goodsId 的商品不存在,服务提供方抛会异常,调用方无法处理,因此只能展示图中的异常信息。

  1. 下面,我们再将 @EnableCircuitBreaker 注解的注释放开,运行结果如下:

从图中可知,虽然请求了一个 goodsId 不存在的商品,但是调用方(order-server)开启了熔断机制,执行默认方法,从而使接口能正常通信而不是抛出调用方不可处理的异常导致整个系统不能正常运行。

看到这里,或许会有读者产生一个疑问,如果类中定义 N 个方法,是不是意味着同时也要定义 N 个异常处理的方法呢,答案是否定的。

Hystrix 还提供了 @DefaultProperties 统一处理请求熔断,在该注解上设置 defaultFallback 属性值,即熔断开启后要执行的方法。

@Service
@DefaultProperties(defaultFallback = "defaultByHystrix")
public class OrderServiceImpl implements OrderService{ // @Autowired
// private RestTemplate restTemplate; @Autowired
private GoodsServiceClient goodsServiceClient; @HystrixCommand
@Override
public void placeOrder(Order order) throws Exception{ // Result result = this.restTemplate.getForObject("http://GOODS/goods/goodsInfo/" + order.getGoodsId(), Result.class); Result result = this.goodsServiceClient.goodsInfo(order.getGoodsId()); if (result != null && result.getCode() == 200) {
System.out.println("=====下订单====");
System.out.println(result.getData());
} else {
System.out.println(result.getMsg());
}
} public void defaultByHystrix() {
System.out.println("商品服务系统异常");
}
}

注意:defaultFallback 定义的方法必须是无参的。

四、服务降级实战

在 common-api 项目中:

4.1 定义 Fallback

@Component
public class GoodsServiceClientFallbackFactory implements FallbackFactory<GoodsServiceClient> { @Override
public GoodsServiceClient create(Throwable cause) {
return new GoodsServiceClient() { @Override
public Result goodsInfo(String goodsId) {
return Result.fail(500, "商品服务系统出现异常,请联系管理员");
} };
} }

使用单独的类处理异常逻辑,当与服务端无法正常通信时调用此类中的方法返回结果。

4.2 修改 Feign 客户端

将上边定义好的 FallbackFactory 设置到 @FeignClient 注解上:

@FeignClient(value="GOODS", fallbackFactory = GoodsServiceClientFallbackFactory.class)
public interface GoodsServiceClient { @RequestMapping("/goods/goodsInfo/{goodsId}")
public Result goodsInfo(@PathVariable("goodsId") String goodsId);
}

4.3 开启服务降级功能

在 order-server 项目中:

server:
port: 8100 spring:
application:
name: ORDER eureka:
instance:
instance-id: order-api-8100
prefer-ip-address: true # 访问路径可以显示 IP
client:
service-url:
defaultZone: http://localhost:9000/eureka/ # 注册中心访问地址 feign:
hystrix:
enabled: true

4.4 去掉 @HystrixCommand 配置

@Service
//@DefaultProperties(defaultFallback = "defaultByHystrix")
public class OrderServiceImpl implements OrderService{ // @Autowired
// private RestTemplate restTemplate; @Autowired
private GoodsServiceClient goodsServiceClient; // @HystrixCommand
@Override
public void placeOrder(Order order) throws Exception{ // Result result = this.restTemplate.getForObject("http://GOODS/goods/goodsInfo/" + order.getGoodsId(), Result.class); Result result = this.goodsServiceClient.goodsInfo(order.getGoodsId()); if (result != null && result.getCode() == 200) {
System.out.println("=====下订单====");
System.out.println(result.getData());
} else {
System.out.println(result.getMsg());
}
} // public void defaultByHystrix() {
// System.out.println("商品服务系统异常");
// }
}

4.5 测试服务降级

在启动类上加 FallbackFactory 类的包扫描目录:

@ComponentScan(basePackages = {"com.extlight.springcloud"}) // 为了能扫描 common-api 项目中的 GoodsServiceClientFallbackFactory
@EnableFeignClients(basePackages = {"com.extlight.springcloud"})
@EnableEurekaClient
@SpringBootApplication
public class OrderServerApplication { public static void main(String[] args) {
SpringApplication.run(OrderServerApplication.class, args);
}
}

打开 Postman 请求下单接口,结果如下图:

我们手动关闭 2 个商品服务,保留一个商品服务并多次请求商品服务接口,从而出模拟商品服务超过预定荷载情景,最终看到图中服务降级功能。当有请求再次访问商品服务时默认返回 GoodsServiceClientFallbackFactory 中定义的内容。

五、仪表盘

除了服务熔断、降级的功能外,Hystrix 还提供了准及时的调用监控。 Hystrix 会持续地记录所有通过 Hystrix 发起的请求的执行信息,并以统计报表和图形方式展示给用户。

5.1 配置被监控方

order-server 项目中:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

修改 application.yml,开放端口:

management:
endpoints:
web:
exposure:
include: "*"

5.2 配置监控方

1.新建一个名为 hystrix-dashboard 项目,添加如下依赖:

<!-- hystrix-dashboard -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

2.新建 application.yml

server:
port: 9300 spring:
application:
name: Hystrix-Dashboard

3.开启监控功能

在启动类上添加 @EnableHystrixDashboard 注解。

@EnableHystrixDashboard
@SpringBootApplication
public class HystrixdashboardApplication { public static void main(String[] args) {
SpringApplication.run(HystrixdashboardApplication.class, args);
}
}

启动,浏览器访问: http://localhost:9300/hystrix

5.3 监控设置

我们以监控 order-server 为例,在监控界面添加监控信息:

# 需要监控的服务地址
http://localhost:8100/actuator/hystrix.stream delay: 请求间隔时间 title: 监控名称 点击 monitor stream 批量访问 order-server 服务的下单接口。

最终效果如下:

通过批量访问下单接口,发现图中实心圆和曲线发生了变化。那我们如何根据这两个图形查看监控信息呢?

实心圆:通过颜色的变化代表实例的健康程度,健康度从绿色>黄色>橙色>红色递减。其大小也会根据实例的请求流量发生变化,流量越大实心圆越大。

曲线:用来记录间隔时间内流量的相对变化,通常可以观察到流量的上升和下降趋势。

六、案例源码

Hystrix demo 源码

七、参考资料

hystrix-javanica

hystrix configuration

hystrix dashboard

Spring Cloud 入门 之 Hystrix 篇(四)的更多相关文章

  1. Spring Cloud 入门 之 Zuul 篇(五)

    原文地址:Spring Cloud 入门 之 Zuul 篇(五) 博客地址:http://www.extlight.com 一.前言 随着业务的扩展,微服务会不对增加,相应的其对外开放的 API 接口 ...

  2. Spring Cloud 入门 之 Config 篇(六)

    原文地址:Spring Cloud 入门 之 Config 篇(六) 博客地址:http://www.extlight.com 一.前言 随着业务的扩展,为了方便开发和维护项目,我们通常会将大项目拆分 ...

  3. Spring Cloud 入门 之 Feign 篇(三)

    原文地址:Spring Cloud 入门 之 Feign 篇(三) 博客地址:http://www.extlight.com 一.前言 在上一篇文章<Spring Cloud 入门 之 Ribb ...

  4. Spring Cloud 入门 之 Ribbon 篇(二)

    原文地址:Spring Cloud 入门 之 Ribbon 篇(二) 博客地址:http://www.extlight.com 一.前言 上一篇<Spring Cloud 入门 之 Eureka ...

  5. Spring Cloud 入门 之 Eureka 篇(一)

    原文地址:Spring Cloud 入门 之 Eureka 篇(一) 博客地址:http://www.extlight.com 一.前言 Spring Cloud 是一系列框架的有序集合.它利用 Sp ...

  6. Spring Cloud入门教程-Hystrix断路器实现容错和降级

    简介 Spring cloud提供了Hystrix容错库用以在服务不可用时,对配置了断路器的方法实行降级策略,临时调用备用方法.这篇文章将创建一个产品微服务,注册到eureka服务注册中心,然后我们使 ...

  7. <Spring Cloud>入门五 hystrix

    1.服务熔断 1.1引入坐标 <dependency> <groupId>org.springframework.cloud</groupId> <artif ...

  8. spring cloud 入门系列四:使用Hystrix 实现断路器进行服务容错保护

    在微服务中,我们将系统拆分为很多个服务单元,各单元之间通过服务注册和订阅消费的方式进行相互依赖.但是如果有一些服务出现问题了会怎么样? 比如说有三个服务(ABC),A调用B,B调用C.由于网络延迟或C ...

  9. Spring Cloud 入门教程(八): 断路器指标数据监控Hystrix Dashboard 和 Turbine

    1. Hystrix Dashboard (断路器:hystrix 仪表盘)  Hystrix一个很重要的功能是,可以通过HystrixCommand收集相关数据指标. Hystrix Dashboa ...

随机推荐

  1. 32. Longest Valid Parentheses *HARD*

    Given a string containing just the characters '(' and ')', find the length of the longest valid (wel ...

  2. oracle11g中SQL优化(SQL TUNING)新特性之Adaptive Cursor Sharing (ACS)

    1.   ACS简介 Oracle Database 11g提供了Adaptive Cursor Sharing (ACS)功能,以克服以往不该共享的游标被共享的可能性.ACS使用两个新指标:sens ...

  3. jsp jsp传统标签开发

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...

  4. trycatch之catch对捕获异常的处理及后续代码的执行的探索

    工作时,一直对try块中throw的异常对象,在catch中如何处理此异常,以及trycatchfinally完毕,程序是否就此停止还是继续运行很迷惑,于是参考网上的资料,自己写了些demo,去慢慢探 ...

  5. Swift网络封装库Moya中文手册之Providers

    Providers 使用Moya,你可以通过一个 MoyaProvider 的实例发送所有网络请求,通过枚举来指定你要访问的具体API.在配置你的 Endpoint 之后,你差不多就做好了基础配置: ...

  6. STL标准库-仿函数与仿函数适配器

    技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性 概要: 1.仿函数 2.bind2nd() 3.not1() 4.bind() 仿函数的实现:声明一个类,重载它的operato ...

  7. 《头文字D》热门同人插画欣赏

    <头文字D>(INITIAL D)是一部以山道飙车为题材的日本青年漫画,以及以漫画改编的动画系列(包含电视版.OVA.与电影版).漫画作者为重野秀一(しげの秀一),自1995 年起开始在讲 ...

  8. 安装 Java 6

    从服务器下载 Linux 64位 jdk 到本地.下载地址:\\192.167.100.225\share\Tool\JAVA\jdk-6u34-linux-x64.bin 给安装文件添加执行权限 $ ...

  9. 使用easyui将json数据生成数据表格

    1.首先需要用script引入jquery和easyui文件.如图所示: 2.html页面设置如下: data-options里面设置的属性可根据需要自己定义,是否单选,是否设置分页等等. 3.引入e ...

  10. 获奖感言和C语言的学习心得

    获奖感言和C语言的学习心得 自我介绍: 大家好,我的名字叫袁忠,我来自湖南,今年快19岁了,现在是大学一年级,我平时喜欢跑步.打羽毛球,我也喜欢学算法与数学,以及喜欢看一些与计算机有关的书籍,每次我学 ...