Dubboソースのサービスリファレンス
7702 ワード
全体的なプロセス
ReferenceBeanはFactoryBeanとInitializingBeanインタフェースを実現しているので、Beanを初期化するときにReferenceBean#afterPropertiesSetメソッドが実行されますReferenceBean#afterPropertiesSet =>
ReferenceBean#getObject =>
ReferenceConfig#get =>
ReferenceConfig#init =>
ReferenceConfig#createProxy =>
Protocol$Adaptive#refer =>
ProtocolFilterWrapper#refer =>
ProtocolListenerWrapper#refer =>
RegistryProtocol#refer =>
RegistryProtocol#doRefer =>
ZookeeperRegistry#register( consumer ) =>
RegistryDirectory#subscribe( providers routers configurators , Invoker)
Cluster$Adaptive#join =>
MockClusterWrapper#join =>
FailoverCluster#join(return new FailoverClusterInvoker) =>
return new MockClusterInvoker =>
ProviderConsumerRegTable#registerConsumer =>
return Invoker
----------------------------- RegistryDirectory#subscribe Invoer ----------------------
RegistryDirectory#subscribe =>
FailbackRegistry#subscribe =>
AbstractRegistry#subscribe =>
ZookeeperRegistry#doSubscribe =>
AbstractZookeeperClient#addChildListener =>
ZookeeperRegistry#notify =>
AbstractRegistry#doNotify =>
RegistryDirectory#notify =>
RegistryDirectory#refreshInvoker =>
RegistryDirectory#toInvokers=>
new InvokerDelegate<>(protocol.refer(serviceType, url), url, providerUrl) =>
newUrlInvokerMap.put(key, invoker)
Consumer登録
この作業はReferenceConfig#createProxyメソッドで完了し、コアコードは次のようになります.// REF_PROTOCOL Protocol$Adaptive
invoker = REF_PROTOCOL.refer(interfaceClass, urls.get(0));
ReferenceBean#afterPropertiesSet =>
ReferenceBean#getObject =>
ReferenceConfig#get =>
ReferenceConfig#init =>
ReferenceConfig#createProxy =>
Protocol$Adaptive#refer =>
ProtocolFilterWrapper#refer =>
ProtocolListenerWrapper#refer =>
RegistryProtocol#refer =>
RegistryProtocol#doRefer =>
ZookeeperRegistry#register( consumer ) =>
RegistryDirectory#subscribe( providers routers configurators , Invoker)
Cluster$Adaptive#join =>
MockClusterWrapper#join =>
FailoverCluster#join(return new FailoverClusterInvoker) =>
return new MockClusterInvoker =>
ProviderConsumerRegTable#registerConsumer =>
return Invoker
----------------------------- RegistryDirectory#subscribe Invoer ----------------------
RegistryDirectory#subscribe =>
FailbackRegistry#subscribe =>
AbstractRegistry#subscribe =>
ZookeeperRegistry#doSubscribe =>
AbstractZookeeperClient#addChildListener =>
ZookeeperRegistry#notify =>
AbstractRegistry#doNotify =>
RegistryDirectory#notify =>
RegistryDirectory#refreshInvoker =>
RegistryDirectory#toInvokers=>
new InvokerDelegate<>(protocol.refer(serviceType, url), url, providerUrl) =>
newUrlInvokerMap.put(key, invoker)
この作業はReferenceConfig#createProxyメソッドで完了し、コアコードは次のようになります.
// REF_PROTOCOL Protocol$Adaptive
invoker = REF_PROTOCOL.refer(interfaceClass, urls.get(0));
RegistryProtocol , ProtocolFilterWrapper ProtocolListenerWrapper
RegistryProtocol#refer =>
RegistryProtocol#doRefer =>
ZookeeperRegistry#register( consumer ) =>
ノードリスニング consumer://10.10.129.164/org.apache.dubbo.demo.DemoService?application=dubbo-demo-api-consumer&category=providers,configurators,routers&check=false&dubbo=2.0.2&interface=org.apache.dubbo.demo.DemoService&lazy=false&methods=sayHello,asyncSay&pid=32780&side=consumer&sticky=false×tamp=1570954083348
ノードリスニングの概略手順は次のとおりです.
consumer://10.10.129.164/org.apache.dubbo.demo.DemoService?application=dubbo-demo-api-consumer&category=providers,configurators,routers&check=false&dubbo=2.0.2&interface=org.apache.dubbo.demo.DemoService&lazy=false&methods=sayHello,asyncSay&pid=32780&side=consumer&sticky=false×tamp=1570954083348
dubboのノードリスニングメカニズムは気持ち悪いので、このようにして、1つのノードが変化したときに、どのような操作を実行しますか?
Invokerの作成
RegistryDirectory#notifyメソッドは、主にproviderUrlに基づいてInvokerオブジェクトを生成します.
RegistryDirectory#notify
RegistryDirectory#refreshOverrideAndInvoker
RegistryDirectory#refreshInvoker
new InvokerDelegate() invoker = new InvokerDelegate<>(protocol.refer(serviceType, url), url, providerUrl);
Clusterへの参加
前のステップでInvokerオブジェクトに戻ると、Cluster$Adaptive#joinメソッドを実行し、SPIに従ってFailover Clusterを取得し、MockClusterWrapperパッケージを使用します.Cluster$Adaptive#join =>
MockClusterWrapper#join =>
FailoverCluster#join =>
new FailoverClusterInvoker =>
return MockClusterInvoker
プロキシの作成
ReferenceConfig#createProxyメソッドでは、Invokerオブジェクトを作成した後、Invokerをインパラメータとしてプロキシオブジェクトを作成します.(T) PROXY_FACTORY.getProxy(invoker)
ProxyFactory$Adaptive#getProxy => StubProxyFactoryWrapper#getProxy => AbstractProxyFactory#getProxy => JavassistProxyFactory#getProxy => return proxy
JavassistProxyFactory#getProxy public T getProxy(Invoker invoker, Class>[] interfaces) {
return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}
最新の赤で生成されたエージェントクラスは次のとおりです.public class proxy0 implements ClassGenerator.DC, EchoService, DemoService{
public static Method[] methods;
private InvocationHandler handler;
public String sayHello(String paramString){
Object[] arrayOfObject = new Object[1];
arrayOfObject[0] = paramString;
Object localObject = this.handler.invoke(this, methods[0], arrayOfObject);
return ((String)localObject);
}
public Object $echo(Object paramObject)
{
Object[] arrayOfObject = new Object[1];
arrayOfObject[0] = paramObject;
Object localObject = this.handler.invoke(this, methods[1], arrayOfObject);
return ((Object)localObject);
}
public proxy0(){
}
public proxy0(InvocationHandler paramInvocationHandler){
this.handler = paramInvocationHandler;
}
}
InvokerInvocationHandlerはJavaのInvocationHandlerインタフェースを実現しているので、JDKダイナミックエージェントのinvokerメソッドにも適用されます.@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
Class>[] parameterTypes = method.getParameterTypes();
if (method.getDeclaringClass() == Object.class) {
return method.invoke(invoker, args);
}
if ("toString".equals(methodName) && parameterTypes.length == 0) {
return invoker.toString();
}
if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
return invoker.hashCode();
}
if ("equals".equals(methodName) && parameterTypes.length == 1) {
return invoker.equals(args[0]);
}
return invoker.invoke(new RpcInvocation(method, args)).recreate();
}
すなわち、エンドユーザがプロキシオブジェクトを介してサービスを呼び出す場合、実際にInvoker#invokerメソッドを実行する
Cluster$Adaptive#join =>
MockClusterWrapper#join =>
FailoverCluster#join =>
new FailoverClusterInvoker =>
return MockClusterInvoker
ReferenceConfig#createProxyメソッドでは、Invokerオブジェクトを作成した後、Invokerをインパラメータとしてプロキシオブジェクトを作成します.
(T) PROXY_FACTORY.getProxy(invoker)
ProxyFactory$Adaptive#getProxy => StubProxyFactoryWrapper#getProxy => AbstractProxyFactory#getProxy => JavassistProxyFactory#getProxy => return proxy
JavassistProxyFactory#getProxy
public T getProxy(Invoker invoker, Class>[] interfaces) {
return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}
最新の赤で生成されたエージェントクラスは次のとおりです.
public class proxy0 implements ClassGenerator.DC, EchoService, DemoService{
public static Method[] methods;
private InvocationHandler handler;
public String sayHello(String paramString){
Object[] arrayOfObject = new Object[1];
arrayOfObject[0] = paramString;
Object localObject = this.handler.invoke(this, methods[0], arrayOfObject);
return ((String)localObject);
}
public Object $echo(Object paramObject)
{
Object[] arrayOfObject = new Object[1];
arrayOfObject[0] = paramObject;
Object localObject = this.handler.invoke(this, methods[1], arrayOfObject);
return ((Object)localObject);
}
public proxy0(){
}
public proxy0(InvocationHandler paramInvocationHandler){
this.handler = paramInvocationHandler;
}
}
InvokerInvocationHandlerはJavaのInvocationHandlerインタフェースを実現しているので、JDKダイナミックエージェントのinvokerメソッドにも適用されます.
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
Class>[] parameterTypes = method.getParameterTypes();
if (method.getDeclaringClass() == Object.class) {
return method.invoke(invoker, args);
}
if ("toString".equals(methodName) && parameterTypes.length == 0) {
return invoker.toString();
}
if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
return invoker.hashCode();
}
if ("equals".equals(methodName) && parameterTypes.length == 1) {
return invoker.equals(args[0]);
}
return invoker.invoke(new RpcInvocation(method, args)).recreate();
}
すなわち、エンドユーザがプロキシオブジェクトを介してサービスを呼び出す場合、実際にInvoker#invokerメソッドを実行する