sentinel-adapter模块,见名知意,这个模块的职能是适配,目前适配主流的框架有dubbo,grpc和web.
由于最了解的是dubbo,目前就先以dubbo为例子进行讲解。
由于dubbo框架的设计思想,具体不展开了,有兴趣可以去了解下,我后续也会写dubbo源码分析。
如下面三个配置的filter,在dubbo请求时会执行到:SentinelDubboProviderFilter,SentinelDubboConsumerFilter和DubboAppContextFilter 的invoke方法
sentinel.dubbo.provider.filter=com.alibaba.csp.sentinel.adapter.dubbo.SentinelDubboProviderFilter
sentinel.dubbo.consumer.filter=com.alibaba.csp.sentinel.adapter.dubbo.SentinelDubboConsumerFilter
dubbo.application.context.name.filter=com.alibaba.csp.sentinel.adapter.dubbo.DubboAppContextFilter
干货
源码分析SentinelDubboProviderFilter dubbo调用方:
public Resultinvoke(Invoker invoker, Invocation invocation)throws RpcException {
// Get origin caller.
//获取客户端 消费方是否包含dubboApplication数据,标明调用方身份
String application = DubboUtils.getApplication(invocation, "");
Entry interfaceEntry =null;
Entry methodEntry =null;
try {
String resourceName = getResourceName(invoker, invocation);
String interfaceName = invoker.getInterface().getName();
//将数据加载到容器中保存
ContextUtil.enter(resourceName, application);
//设置资源保护,接口级别接口保护
interfaceEntry = SphU.entry(interfaceName, EntryType.IN);
//设置资源保护,方法级别接口保护
methodEntry = SphU.entry(resourceName, EntryType.IN, 1, invocation.getArguments());
//调用
Result result = invoker.invoke(invocation);
if (result.hasException()) {
//统计异常比例
Tracer.trace(result.getException());
}
return result;
}catch (BlockException e) {
//当出现拒绝后,进入fallback,可定制化fallback,默认DefaultDubboFallback,抛出SentinelRpcException异常
return DubboFallbackRegistry.getProviderFallback().handle(invoker, invocation, e);
}catch (RpcException e) {
//统计异常比例
Tracer.trace(e);
throw e;
}finally {
if (methodEntry !=null) {
//清理方法级别资源
methodEntry.exit(1, invocation.getArguments());
}
if (interfaceEntry !=null) {
//清理接口级别资源
interfaceEntry.exit();
}
//清理
ContextUtil.exit();
}
}
源码分析DubboAppContextFilter dubbo被调用方:
@Override
public Resultinvoke(Invoker invoker, Invocation invocation)throws RpcException {
String application = invoker.getUrl().getParameter(Constants.APPLICATION_KEY);
if (application !=null) {
RpcContext.getContext().setAttachment(DubboUtils.DUBBO_APPLICATION_KEY, application);
}
return invoker.invoke(invocation);
}
写入自定义的dubboApplication命名
源码分析SentinelDubboConsumerFilter dubbo被调用方:
@Override
public Resultinvoke(Invoker invoker, Invocation invocation)throws RpcException {
Entry interfaceEntry =null;
Entry methodEntry =null;
try {
//获取调用方接口名称
String resourceName = getResourceName(invoker, invocation);
ContextUtil.enter(resourceName);
//设置资源保护,接口级别接口保护
interfaceEntry = SphU.entry(invoker.getInterface().getName(), EntryType.OUT);
//设置资源保护,方法级别接口保护
methodEntry = SphU.entry(resourceName, EntryType.OUT);
Result result = invoker.invoke(invocation);
if (result.hasException()) {
//统计异常比例
Tracer.trace(result.getException());
}
return result;
}catch (BlockException e) {
//fallback
return DubboFallbackRegistry.getConsumerFallback().handle(invoker, invocation, e);
}catch (RpcException e) {
//统计异常比例
Tracer.trace(e);
throw e;
}finally {
if (methodEntry !=null) {
//资源释放
methodEntry.exit();
}
if (interfaceEntry !=null) {
//资源释放
interfaceEntry.exit();
}
//资源释放
ContextUtil.exit();
}
}