概述
本文将介绍以下内容:
- Hystrix简介
- Dubbo接入Hystrix
Hystrix简介
Hystrix是Netflix开源的一款容错系统,主要用于解决服务提供者不可用带来的服务雪崩效应。Hystrix容错方案主要有以下几种:
- 熔断:只作用在服务调用者,即consumer端,熔断器开关由关闭到打开的状态转换是通过当前服务健康状况(请求失败数 / 请求总数)和设定阈值比较决定的。
- 降级:当某个服务熔断之后,服务器将不再被调用,此时客户端可以自己准备一个本地的fallback回调,返回一个缺省值。
- 限流(隔离):采用线程/信号的方式,通过隔离限制依赖的并发量和阻塞扩散
- 异步RPC:将同步RPC调用转为异步调用。
Dubbo接入Hystrix
Dubbo是通过Filter接入Hystrix的。
新建DubboHystrixCommand
设置Hystrix相关参数
package com.beidao.dubbo.hystrix.command;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.HystrixThreadPoolProperties;
/**
* Hystrix命令
* @author 0200759
*
*/
public class DubboHystrixCommand extends HystrixCommand<Result> {
private static Logger logger = LoggerFactory.getLogger(DubboHystrixCommand.class);
private static final int DEFAULT_THREADPOOL_CORE_SIZE = 30;
private Invoker<?> invoker;
private Invocation invocation;
public DubboHystrixCommand(Invoker<?> invoker,Invocation invocation){
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(invoker.getInterface().getName()))
.andCommandKey(HystrixCommandKey.Factory.asKey(String.format("%s_%d", invocation.getMethodName(),
invocation.getArguments() == null ? 0 : invocation.getArguments().length)))
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
.withCircuitBreakerRequestVolumeThreshold(20)//10秒钟内至少19此请求失败,熔断器才发挥起作用
.withCircuitBreakerSleepWindowInMilliseconds(30000)//熔断器中断请求30秒后会进入半打开状态,放部分流量过去重试
.withCircuitBreakerErrorThresholdPercentage(50)//错误率达到50开启熔断保护
.withExecutionTimeoutEnabled(false))//使用dubbo的超时,禁用这里的超时
.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(getThreadPoolCoreSize(invoker.getUrl()))));//线程池为30
this.invoker=invoker;
this.invocation=invocation;
}
/**
* 获取线程池大小
*
* @param url
* @return
*/
private static int getThreadPoolCoreSize(URL url) {
if (url != null) {
int size = url.getParameter("ThreadPoolCoreSize", DEFAULT_THREADPOOL_CORE_SIZE);
if (logger.isDebugEnabled()) {
logger.debug("ThreadPoolCoreSize:" + size);
}
return size;
}
return DEFAULT_THREADPOOL_CORE_SIZE;
}
@Override
protected Result run() throws Exception {
try {
return invoker.invoke(invocation);
} catch(Exception e){
e.printStackTrace();
throw new HystrixBadRequestException(e.getMessage(),e);
}
}
/*@Override
protected Result getFallback(){
return new RpcResult(new Exception("wrong invoke"));
}*/
}
注意: 这里在run方法内捕获了Exception并抛出了HystrixBadRequestException异常,故不会执行getFallback方法。
新建Filter
这里配置了一个CONSUMER端全局自动触发的Filter
package com.beidao.dubbo.hystrix.filter;
import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.Filter;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcException;
import com.beidao.dubbo.hystrix.command.DubboHystrixCommand;
/**
* Hystrix拦截器
* @author 0200759
*
*/
@Activate(group = Constants.CONSUMER)
public class HystrixFilter implements Filter {
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
DubboHystrixCommand command = new DubboHystrixCommand(invoker, invocation);
return (Result) command.execute();
}
}
目录resources\META-INF\dubbo下新建文件com.alibaba.dubbo.rpc.Filter内容如下
HystrixFilter = com.beidao.dubbo.hystrix.filter.HystrixFilter
Done!当服务调用者调用时参数不满足前面Hystrix设置的参数阈值时,调用者不再调用服务提供者,即发生熔断。