AbstractCommand关键源码
protected final HystrixRequestCache requestCache;
//默认返回null
protected String getCacheKey(){
return null;
}
protected boolean isRequestCachingEnabled(){
//必须重写getCacheKey方法,让它返回一个非null的值,否则不会开启
//请求命令缓存开启属性也需要设置为true才能开启(默认为true)
return properties.requestCacheEnalbed().get && getCacheKey()!=null;
}
public Observable<R> toObservable() {
final AbstractCommand<R> _cmd = this;
......
final boolean requestCacheEnabled = isRequestCachingEnabled();
final String cacheKey = getCacheKey();
/*首先尝试从缓存中获取结果 */
/*
Hystrix命令再执行前根据isRequestCachingEnabled方法判断当前是否启用了请求缓存。如果启用了
并且重写了getCacheKey方法,并返回了一个非null的缓存Key值,那么就使用getCacheKey返回的key
去调用requestCache中的get方法来获取缓存的HystrixCacheObservable对象
*/
if (requestCacheEnabled) {
HystrixCommandResponseFromCache<R> fromCache = (HystrixCommandResponseFromCache<R>) requestCache.get(cacheKey);
if (fromCache != null) {
isResponseFromCache = true;
return handleRequestCacheHitAndEmitValues(fromCache, _cmd);
}
}
Observable<R> hystrixObservable =
Observable.defer(applyHystrixSemantics) //未使用缓存,则继续调用applyHystrixSemantics
.map(wrapWithAllOnNextHooks);
Observable<R> afterCache;
// 加入缓存
if (requestCacheEnabled && cacheKey != null) {
// wrap it for caching
/*
请求缓存对象HystrixRequestCache维护了一个线程安全的Map来保存请求缓存的响应,调用putIfAbsent,将包装
的请求缓存放入缓存对象后,对其返回结果进行判断,如果不为null,说明当前缓存Key的请求命令缓存命中
直接对toCache执行取消订阅操作(不再发起真实请求),同时调用 handleRequestCacheHitAndEmitValues
来执行缓存命令的结果获取。如果fromCache为空,说明缓存没命中,则将当前结果toCache缓存起来,并将其转换
成Observable返回给调用者使用。
*/
HystrixCachedObservable<R> toCache = HystrixCachedObservable.from(hystrixObservable, _cmd);
HystrixCommandResponseFromCache<R> fromCache = (HystrixCommandResponseFromCache<R>) requestCache.putIfAbsent(cacheKey, toCache);
if (fromCache != null) {
// another thread beat us so we'll use the cached value instead
toCache.unsubscribe();
isResponseFromCache = true;
return handleRequestCacheHitAndEmitValues(fromCache, _cmd);
} else {
// we just created an ObservableCommand so we cast and return it
afterCache = toCache.toObservable();
}
} else {
afterCache = hystrixObservable;
}
return afterCache
.doOnTerminate(terminateCommandCleanup) // perform cleanup once (either on normal terminal state (this line), or unsubscribe (next line))
.doOnUnsubscribe(unsubscribeCommandCleanup) // perform cleanup once
.doOnCompleted(fireOnCompletedHook);
}
});
}