sentinel-adapter模塊,見名知意,這個模塊的職能是適配,目前適配主流的框架有dubbo,grpc和web.
由于最了解的是dubbo,目前就先以dubbo為例子進行講解。
由于dubbo框架的設計思想,具體不展開了,有興趣可以去了解下,我后續(xù)也會寫dubbo源碼分析。
如下面三個配置的filter,在dubbo請求時會執(zhí)行到: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數(shù)據(jù),標明調用方身份
? ? String application = DubboUtils.getApplication(invocation, "");
? ? Entry interfaceEntry =null;
? ? Entry methodEntry =null;
? ? try {
? ? ? ? String resourceName = getResourceName(invoker, invocation);
? ? ? ? String interfaceName = invoker.getInterface().getName();
? ? ? ?//將數(shù)據(jù)加載到容器中保存
? ? ? ? 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()) {
//統(tǒng)計異常比例
Tracer.trace(result.getException());
? ? ? ? }
return result;
? ? }catch (BlockException e) {
//當出現(xiàn)拒絕后,進入fallback,可定制化fallback,默認DefaultDubboFallback,拋出SentinelRpcException異常
return DubboFallbackRegistry.getProviderFallback().handle(invoker, invocation, e);
? ? }catch (RpcException e) {
//統(tǒng)計異常比例
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()) {
//統(tǒng)計異常比例
? ? ? ? ? ? Tracer.trace(result.getException());
? ? ? ? }
return result;
? ? }catch (BlockException e) {
//fallback
return DubboFallbackRegistry.getConsumerFallback().handle(invoker, invocation, e);
? ? }catch (RpcException e) {
//統(tǒng)計異常比例
Tracer.trace(e);
? ? ? ? throw e;
? ? }finally {
if (methodEntry !=null) {
//資源釋放
methodEntry.exit();
? ? ? ? }
if (interfaceEntry !=null) {
//資源釋放
interfaceEntry.exit();
? ? ? ? }
//資源釋放
ContextUtil.exit();
? ? }
}