Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wushizhenking
advanced-java
提交
82173fe7
A
advanced-java
项目概览
wushizhenking
/
advanced-java
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
A
advanced-java
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
82173fe7
编写于
1月 04, 2019
作者:
Y
yanglbme
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: add hystrix-fallback
Hystrix 降级机制具体场景演示
上级
0584822e
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
126 addition
and
0 deletion
+126
-0
README.md
README.md
+1
-0
docs/high-availability/hystrix-fallback.md
docs/high-availability/hystrix-fallback.md
+125
-0
未找到文件。
README.md
浏览文件 @
82173fe7
...
...
@@ -87,6 +87,7 @@
-
[
Hystrix 隔离策略细粒度控制
](
/docs/high-availability/hystrix-execution-isolation.md
)
-
[
深入 Hystrix 执行时内部原理
](
/docs/high-availability/hystrix-process.md
)
-
[
基于 request cache 请求缓存技术优化批量商品数据查询接口
](
/docs/high-availability/hystrix-request-cache.md
)
-
[
基于本地缓存的 fallback 降级机制
](
/docs/high-availability/hystrix-fallback.md
)
### 高可用系统
-
如何设计一个高可用系统?
...
...
docs/high-availability/hystrix-fallback.md
0 → 100644
浏览文件 @
82173fe7
## 基于本地缓存的 fallback 降级机制
Hystrix 出现以下四种情况,都会去调用 fallback 降级机制:
-
断路器处于打开的状态。
-
资源池已满(线程池+队列 / 信号量)。
-
Hystrix 调用各种接口,或者访问外部依赖,比如 MySQL、Redis、Zookeeper、Kafka 等等,出现了任何异常的情况。
-
访问外部依赖的时候,访问时间过长,报了 TimeoutException 异常。
### 两种最经典的降级机制
-
纯内存数据
<br>
在降级逻辑中,你可以在内存中维护一个 ehcache,作为一个纯内存的基于 LRU 自动清理的缓存,让数据放在缓存内。如果说外部依赖有异常,fallback 这里直接尝试从 ehcache 中获取数据。
-
默认值
<br>
fallback 降级逻辑中,也可以直接返回一个默认值。
在
`HystrixCommand`
,降级逻辑的书写,是通过实现 getFallback() 接口;而在
`HystrixObservableCommand`
中,则是实现 resumeWithFallback() 方法。
现在,我们用一个简单的栗子,来演示 fallback 降级是怎么做的。
比如,有这么个
**场景**
。我们现在有个包含 brandId 的商品数据,假设正常的逻辑是这样:拿到一个商品数据,根据 brandId 去调用品牌服务的接口,获取品牌的最新名称 brandName。
假如说,品牌服务接口挂掉了,那么我们可以尝试从本地内存中,获取一份稍过期的数据,先凑合着用。
### 本地缓存获取数据
本地获取品牌名称的代码大致如下。
```
java
/**
* 品牌名称本地缓存
*
*/
public
class
BrandCache
{
private
static
Map
<
Long
,
String
>
brandMap
=
new
HashMap
<>();
static
{
brandMap
.
put
(
1L
,
"Nike"
);
}
/**
* brandId 获取 brandName
* @param brandId 品牌id
* @return 品牌名
*/
public
static
String
getBrandName
(
Long
brandId
)
{
return
brandMap
.
get
(
brandId
);
}
```
### 实现 GetBrandNameCommand
在 GetBrandNameCommand 中,run() 方法的正常逻辑是去调用品牌服务的接口获取到品牌名称,如果调用失败,报错了,那么就会去调用 fallback 降级机制。
这里,我们直接
**模拟接口调用报错**
,给它抛出个异常。
而在 getFallback() 方法中,就是我们的
**降级逻辑**
,我们直接从本地的缓存中,
**获取到品牌名称**
的数据。
```
java
/**
* 获取品牌名称的command
*
*/
public
class
GetBrandNameCommand
extends
HystrixCommand
<
String
>
{
private
Long
brandId
;
public
GetBrandNameCommand
(
Long
brandId
)
{
super
(
Setter
.
withGroupKey
(
HystrixCommandGroupKey
.
Factory
.
asKey
(
"BrandService"
))
.
andCommandKey
(
HystrixCommandKey
.
Factory
.
asKey
(
"GetBrandNameCommand"
))
.
andCommandPropertiesDefaults
(
HystrixCommandProperties
.
Setter
()
// 设置降级机制最大并发请求数
.
withFallbackIsolationSemaphoreMaxConcurrentRequests
(
15
)));
this
.
brandId
=
brandId
;
}
@Override
protected
String
run
()
throws
Exception
{
// 这里正常的逻辑应该是去调用一个品牌服务的接口获取名称
// 如果调用失败,报错了,那么就会去调用fallback降级机制
// 这里我们直接模拟调用报错,抛出异常
throw
new
Exception
();
}
@Override
protected
String
getFallback
()
{
return
BrandCache
.
getBrandName
(
brandId
);
}
}
```
`FallbackIsolationSemaphoreMaxConcurrentRequests`
用于设置 fallback 最大允许的并发请求量,默认值是 10,是通过 semaphore 信号量的机制去限流的。如果超出了这个最大值,那么直接 reject。
### CacheController 调用接口
在 CacheController 中,我们通过 productInfo 获取 brandId,然后创建 GetBrandNameCommand 并执行,去尝试获取 brandName。这里执行会报错,因为我们在 run() 方法中直接抛出异常,Hystrix 就会去调用 getFallback() 方法走降级逻辑。
```
java
@Controller
public
class
CacheController
{
@RequestMapping
(
"/getProductInfo"
)
@ResponseBody
public
String
getProductInfo
(
Long
productId
)
{
HystrixCommand
<
ProductInfo
>
getProductInfoCommand
=
new
GetProductInfoCommand
(
productId
);
ProductInfo
productInfo
=
getProductInfoCommand
.
execute
();
Long
brandId
=
productInfo
.
getBrandId
();
HystrixCommand
<
String
>
getBrandNameCommand
=
new
GetBrandNameCommand
(
brandId
);
// 执行会抛异常报错,然后走降级
String
brandName
=
getBrandNameCommand
.
execute
();
productInfo
.
setBrandName
(
brandName
);
System
.
out
.
println
(
productInfo
);
return
"success"
;
}
}
```
关于降级逻辑的演示,基本上就结束了。
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录