该栏目讲叙微服务概念、注册中心、负载均衡、配置中心、服务熔断、服务消费等知识
背景
- :分布式系统环境下,服务间相互依赖非常常见,一个业务调用通常依赖多个基础服务。当一个服务不可用,导致一系列服务不可用,最终可能导致整个服务资源耗尽,无法继续对外提供服务。并且这种不可用可能沿请求调用链向上传递,这种现象被称为雪崩效应
简介
1、概述
- :Hystrix 是一款开源的容错框架,具有容错和自我保护的能力
2、设计目标
- 对来自依赖的延迟和故障进行防护和控制
- 阻止故障的连锁反应
- 快速失败并迅速恢复
- 回退并优雅降级
- 提供近实时的监控与告警
压力测试工具 Jmeter
# 配置语言
language=zh_CN
# 配置编码
sampleresult.default.encoding=UTF-8
运行
:bin/jmeter.jar
资源隔离
1、线程隔离
概述
:Hystrix 将不同类型的业务请求封装为对应的命令请求,并为每个命令请求配置一个线程池,当第一创建命令请求时,根据配置创建一个线程池,并放入 ConcurrentHashMap。通过将发送请求线程与执行请求的线程分离,可有效防止发生级联故障。当线程池或请求队列饱和时,Hystrix 将拒绝服务,使得请求线程可以快速失败,从而避免依赖问题扩散优点
:保护应用程序以免受来自依赖故障的影响,指定依赖线程池饱和不会影响应用程序的其余部分缺点
:增加了计算开销,Hystrx 每个命令的执行都在单独的线程完成,增加了排队、调度和上下文切换的开销操作
@HystrixCommand(
groupKey = "order-productService-listPool", // 服务名称,相同名称使用同一个线程池
commandKey = "selectProductList", // 接口名称,默认为方法名
threadPoolKey = "order-productService-listPool", // 线程池名称,相同名称使用同一个线程池
commandProperties = {
// 超时时间,默认1000ms
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",
value = "5000"),
},
threadPoolProperties = {
// 线程池大小
@HystrixProperty(name = "coreSize", value = "6"),
// 队列等待阈值(最大队列长度,默认-1)
@HystrixProperty(name = "maxQueueSize", value = "100"),
// 线程存活时间,默认1min
@HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),
// 超出队列等待阈值执行拒绝策略
@HystrixProperty(name = "queueSizeRejectionThreshold", value = "100")
}, fallbackMethod = "selectProductListFallback"
)
@Override
public List<Product> selectProductList() {
return null;
}
private List<Product> selectProductListFallback() {
System.out.println("----selectProductListFallback----");
return Arrays.asList(
new Product(1, "托底数据-华为手机", 1, 5800D),
new Product(2, "托底数据-联想笔记本", 1, 6800D),
new Product(3, "托底数据-小米平板", 5, 2020D)
);
}
2、信号量隔离
概述
:每次请求服务时,信号量进行累加,当信号量大于 maxConcurrentRequests 时,Hystrix 将拒绝服务,使得请求线程可以快速失败操作
@HystrixCommand(
commandProperties = {
// 超时时间,默认1000ms
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",
value = "5000"),
// 信号量隔离
@HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_STRATEGY,
value = "SEMAPHORE"),
// 信号量最大并发,高小一些方便模拟高并发
@HystrixProperty(
name = HystrixPropertiesManager.EXECUTION_ISOLATION_SEMAPHORE_MAX_CONCURRENT_REQUESTS,
value = "6")
}, fallbackMethod = "selectProductListFallback"
)
@Override
public List<Product> selectProductList() {
return null;
}
private List<Product> selectProductListFallback() {
System.out.println("----selectProductListFallback----");
return Arrays.asList(
new Product(1, "托底数据-华为手机", 1, 5800D),
new Product(2, "托底数据-联想笔记本", 1, 6800D),
new Product(3, "托底数据-小米平板", 5, 2020D)
);
}
服务熔断
1、概述
- :Hystrix 在运行过程中会向每个 commandKey 对应的熔断器报告成功、失败、超时和拒绝的状态,熔断器维护并统计这些数据,并根据这些统计信息来决策熔断开关是否打开。如果打开,熔断后续请求,快速返回。隔一段时间(默认是5s)之后熔断器尝试半开,放入一部分流量请求进来,相当于对依赖服务进行一次健康检查,如果请求成功,熔断器关闭
2、配置
描述 | 参数 |
---|---|
是否启用熔断器,默认是 true | enabled |
熔断器强制打开,默认是 false | forceOpen |
熔断器强制关闭,默认是 false | forceClosed |
错误率,默认值50% | errorThresholdPercentage |
一段时间内至少有20个请求才进行 errorThresholdPercentage 计算,默认20 | requestVolumeThreshold |
半开状态试探睡眠时间,默认值5000 ms | sleepWindowInMilliseconds |
2、操作
@HystrixCommand(
commandProperties = {
// 10s内请求数大于10个就启动熔断器,当请求符合熔断条件触发fallbackMethod,默认20
@HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD,
value = "10"),
// 请求错误率大于50%就启动熔断,然后for循环发起重试请求,当请求符合熔断条件fallbackMethod
@HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE,
value = "50"),
// 熔断多少秒后去重试请求,默认5s
@HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS,
value = "5000")
}, fallbackMethod = "selectProductListFallback"
)
@Override
public List<Product> selectProductList() {
return null;
}
private List<Product> selectProductListFallback() {
System.out.println("----selectProductListFallback----");
return Arrays.asList(
new Product(1, "托底数据-华为手机", 1, 5800D),
new Product(2, "托底数据-联想笔记本", 1, 6800D),
new Product(3, "托底数据-小米平板", 5, 2020D)
);
}
服务降级
1、概述
- :服务熔断以后,客户端调用自己本地方法返回缺省值
2、触发条件
- 方法抛出非HystrixBadRequestException
- 方法调用超时
- 熔断器开启拦截调用
- 线程池/队列/信号量跑满
3、操作
@HystrixCommand(fallbackMethod = "selectProductListFallback")
@Override
public List<Product> selectProductList() {
return null;
}
private List<Product> selectProductListFallback() {
System.out.println("----selectProductListFallback----");
return Arrays.asList(
new Product(1, "托底数据-华为手机", 1, 5800D),
new Product(2, "托底数据-联想笔记本", 1, 6800D),
new Product(3, "托底数据-小米平板", 5, 2020D)
);
}