1. 依赖引入
pom.xml
<properties>
<hystrix-version>
1.4
.
22
</hystrix-version>
</properties>
<dependencies>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
<version>${hystrix-version}</version>
</dependency>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-metrics-event-stream</artifactId>
<version>${hystrix-version}</version>
</dependency>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-javanica</artifactId>
<version>${hystrix-version}</version>
</dependency>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-servo-metrics-publisher</artifactId>
<version>${hystrix-version}</version>
</dependency>
</dependencies>
|
applicationContext.xml:
<aop:aspectj-autoproxy/>
<bean id=
"hystrixAspect"
class
=
"com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect"
/>
|
web.xml:
<servlet>
<display-name>HystrixMetricsStreamServlet</display-name>
<servlet-name>HystrixMetricsStreamServlet</servlet-name>
<servlet-
class
>com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet</servlet-
class
>
</servlet>
<servlet-mapping>
<servlet-name>HystrixMetricsStreamServlet</servlet-name>
<url-pattern>/hystrix.stream</url-pattern>
</servlet-mapping>
|
jmonitor:
collector=jvm,appdata,http
|
2. 使用
这里只讲注解的使用方式以及比较重要的部分,如果需要了解全部查看:https://github.com/Netflix/Hystrix/wiki/How-To-Use
2.1 Hystrix command
2.1.1 同步执行
public
class
UserService {
...
@HystrixCommand
(groupKey=
"UserGroup"
, commandKey =
"GetUserByIdCommand"
)
public
User getUserById(String id) {
return
userResource.getUserById(id);
}
}
|
2.1.2 异步执行
@HystrixCommand
public
Future<User> getUserByIdAsync(
final
String id) {
return
new
AsyncResult<User>() {
@Override
public
User invoke() {
return
userResource.getUserById(id);
}
};
}
|
2.1.3 反应执行
@HystrixCommand
public
Observable<User> getUserById(
final
String id) {
return
Observable.create(
new
Observable.OnSubscribe<User>() {
@Override
public
void
call(Subscriber<?
super
User> observer) {
try
{
if
(!observer.isUnsubscribed()) {
observer.onNext(
new
User(id, name + id));
observer.onCompleted();
}
}
catch
(Exception e) {
observer.onError(e);
}
}
});
}
|
2.1.4 三种模式使用区别
- 同步执行:当执行到注解方法时,程序会顺序执行。
- 异步执行:当执行到注解方法时,会并发异步执行,返回一个Future对象,后面使用.get()方法来阻塞拿到结果。如果有多个方法时,执行时间就是其中最长的一个服务的执行时间。
- 反应执行:当执行到注解方法时,返回一个观察者。支持EAGER和LAZY模式。和同步异步执行的区别是,当对多个方法之间的返回结果不需要做合并而是希望当多个方法返回时触发一些事件时比较适合使用该模式。
反应执行没太明白,如果需要了解可以先参考下这个https://mcxiaoke.gitbooks.io/rxdocs/content/Intro.html
2.2 Fallback
@HystrixCommand
(fallbackMethod =
"fallback1"
)
User getUserById(String id) {
throw
new
RuntimeException(
"getUserById command failed"
);
}
@HystrixCommand
(fallbackMethod =
"fallback2"
)
User fallback1(String id, Throwable e) {
assert
"getUserById command failed"
.equals(e.getMessage());
throw
new
RuntimeException(
"fallback1 failed"
);
}
@HystrixCommand
(fallbackMethod =
"fallback3"
)
User fallback2(String id) {
throw
new
RuntimeException(
"fallback2 failed"
);
}
|
注意点:
- fallback应该和注解方法在同一类下
- fallback的返回值和参数列表应该和注解方法一致,如果需要异常,则在末尾添加Throwable参数,对访问修饰符无要求
- fallback方法上可以继续添加fallback
command和fallback只支持以下几种组合:
- sync command, sync fallback
- async command, sync fallback
- async command, async fallback
2.3 Error Propagation
@HystrixCommand
(ignoreExceptions = {BadRequestException.
class
})
public
User getUserById(String id) {
return
userResource.getUserById(id);
}
|
当遇到BadRequestException时不会进入fallback,而是直接抛出异常
2.4 Configuration
@HystrixCommand
(groupKey=
"UserGroup"
, commandKey =
"GetUserByIdCommand"
,
commandProperties = {
@HystrixProperty
(name =
"execution.isolation.thread.timeoutInMilliseconds"
, value =
"500"
)
},
threadPoolProperties = {
@HystrixProperty
(name =
"coreSize"
, value =
"30"
),
@HystrixProperty
(name =
"maxQueueSize"
, value =
"101"
),
@HystrixProperty
(name =
"keepAliveTimeMinutes"
, value =
"2"
),
@HystrixProperty
(name =
"queueSizeRejectionThreshold"
, value =
"15"
),
@HystrixProperty
(name =
"metrics.rollingStats.numBuckets"
, value =
"12"
),
@HystrixProperty
(name =
"metrics.rollingStats.timeInMilliseconds"
, value =
"1440"
)
})
|
groupKey |
表示所属的group,一个group共用线程池 | 默认值:getClass().getSimpleName(); |
commandKey |
默认值:当前执行方法名 | |
execution.isolation.strategy |
隔离策略,有THREAD和SEMAPHORE | 默认使用THREAD模式,以下几种可以使用SEMAPHORE模式:
|
execution.isolation.thread.timeoutInMilliseconds
|
超时时间 | 默认值:1000 在THREAD模式下,达到超时时间,可以中断 在SEMAPHORE模式下,会等待执行完成后,再去判断是否超时 设置标准: 有retry,99meantime+avg meantime 没有retry,99.5meantime |
execution.timeout.enabled |
是否打开超时 | |
execution.isolation.thread.interruptOnTimeout |
是否打开超时线程中断 | THREAD模式有效 |
execution.isolation.semaphore.maxConcurrentRequests |
信号量最大并发度 | SEMAPHORE模式有效,默认值:10 |
fallback.isolation.semaphore.maxConcurrentRequests |
fallback最大并发度 | 默认值:10 |
circuitBreaker.requestVolumeThreshold |
熔断触发的最小个数/10s | 默认值:20 |
circuitBreaker.sleepWindowInMilliseconds |
熔断多少秒后去尝试请求 | 默认值:5000 |
circuitBreaker.errorThresholdPercentage |
失败率达到多少百分比后熔断 | 默认值:50 主要根据依赖重要性进行调整 |
circuitBreaker.forceClosed |
是否强制关闭熔断 | 如果是强依赖,应该设置为true |
coreSize |
线程池coreSize | 默认值:10 设置标准:qps*99meantime+breathing room |
maxQueueSize |
请求等待队列 | 默认值:-1 如果使用正数,队列将从SynchronizeQueue改为LinkedBlockingQueue
|