文章转载于:乐字节
文章内容:微服务系列之Hystrix服务容错(一)
1.什么是 Hystrix
Hystrix 源自 Netflix 团队于 2011 年开始研发。2012年 Hystrix 不断发展和成熟,Netflix 内部的许多团队都采用了它。如今,每天在 Netflix 上通过 Hystrix 执行数百亿个线程隔离和数千亿个信号量隔离的调用。极大地提高了系统的稳定性。
在分布式环境中,不可避免地会有许多服务依赖项中的某些服务失败而导致「雪崩效应」。Hystrix 是一个库,可通过添加等待时间容限和容错逻辑来帮助您控制这些分布式服务之间的交互。Hystrix 通过隔离服务之间的访问点,停止服务之间的级联故障并提供后备选项来实现此目的,所有这些都可以提高系统的整体稳定性。
2.雪崩效应
在微服务架构中,一个请求需要调用多个服务是非常常见的。如客户端访问 A 服务,而 A 服务需要调用 B 服务,B 服务需要调用 C 服务,由于网络原因或者自身的原因,如果 B 服务或者 C 服务不能及时响应,A 服务将处于阻塞状态,直到 B 服务 C 服务响应。此时若有大量的请求涌入,容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性,故障会传播,造成连锁反应,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的“雪崩”效应。以下图示完美解释了什么是雪崩效应。
当一切服务正常时,请求看起来是这样的:
当其中一个服务有延迟时,它可能阻塞整个用户请求:
在高并发的情况下,一个服务的延迟可能导致所有服务器上的所有资源在数秒内饱和。比起服务故障,更糟糕的是这些应用程序还可能导致服务之间的延迟增加,从而备份队列,线程和其他系统资源,从而导致整个系统出现更多级联故障。
总结
造成雪崩的原因可以归结为以下三点:
服务提供者不可用(硬件故障,程序 BUG,缓存击穿,用户大量请求等)
重试加大流量(用户重试,代码逻辑重试)
服务消费者不可用(同步等待造成的资源耗尽)
最终的结果就是:一个服务不可用,导致一系列服务的不可用。
需要微服务系列资料可:关注【乐字节】公众号,输入233,领取
解决方案
雪崩是系统中的蝴蝶效应导致,其发生的原因多种多样,从源头我们无法完全杜绝雪崩的发生,但是雪崩的根本原因来源于服务之间的强依赖,所以我们可以提前评估做好服务容错。解决方案大概可以分为以下几种:
请求缓存:支持将一个请求与返回结果做缓存处理;
请求合并:将相同的请求进行合并然后调用批处理接口;
服务隔离:限制调用分布式服务的资源,某一个调用的服务出现问题不会影响其他服务调用;
服务熔断:牺牲局部服务,保全整体系统稳定性的措施;
服务降级:服务熔断以后,客户端调用自己本地方法返回缺省值。
环境准备
eureka-server:注册中心
eureka-server02:注册中心
product-service:商品服务,提供了 /product/{id} 接口,/product/list 接口,/product/listByIds 接口
order-service-rest:订单服务,基于 Ribbon 通过 RestTemplate 调用商品服务
order-server-feign:订单服务,基于 Feign 通过声明式服务调用商品服务
模拟高并发场景
服务提供者接口添加Thread.sleep(2000),模拟服务处理时长。
package com.example.controller;
import com.example.pojo.Product;
import com.example.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/product")
public class ProductController {
@Autowired
private ProductService productService;
/**
* 查询商品列表
*
* @return
*/
@GetMapping("/list")
public List selectProductList() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return productService.selectProductList();
}
/**
* 根据多个主键查询商品
*
* @param ids
* @return
*/
@GetMapping("/listByIds")
public List selectProductListByIds(@RequestParam("id") List ids) {
return productService.selectProductListByIds(ids);
}
/**
* 根据主键查询商品
*
* @param id
* @return
*/
@GetMapping("/{id}")
public Product selectProductById(@PathVariable("id") Integer id) {
return productService.selectProductById(id);
}
}
服务消费者降低 Tomcat 最大线程数方便模拟高并发。
server:
port: 8080
tomcat:
max-threads: 10 # 降低最大线程数方便模拟高并发
JMeter
Apache JMeter 应用程序是开源软件,100% 纯 Java 应用而设计的负载测试功能行为和测量性能。它最初是为测试 Web 应用程序而设计的,但此后已扩展到其他测试功能。
Apache JMeter 可用于测试静态和动态资源,Web 动态应用程序的性能。它可用于模拟服务器,服务器组,网络或对象上的繁重负载,以测试其强度或分析不同负载类型下的整体性能。
安装
解压apache-jmeter-5.2.1.zip,进入bin目录运行jmeter.bat即可。不过运行之前我们先来修改一下配置文件,方便大家更友好的使用。
修改配置
进入 bin 目录编辑 jmeter.properties 文件,修改 37 行和 1085 行两处代码(不同的电脑可能行数不一致,不过上下差距不大)。
language=zh_CN 界面显示中文
sampleresult.default.encoding=UTF-8 编码字符集使用 UTF-8
#language=en
language=zh_CN
#sampleresult.default.encoding=ISO-8859-1
sampleresult.default.encoding=UTF-8
运行
运行bin/jmeter.bat文件,界面显示如下。
大家可以通过选项→外观选择自己喜欢的界面风格。
下一篇我们讲解 Hystrix 服务隔离的线程池隔离与信号量隔离,记得关注噢~