官网

客户端服务引用

客户端服务引用 demo

1
2
DemoService demoService = (DemoService) context.getBean("demoService"); // get remote service proxy
demoService.sayHello("world");

dubbo 在客户端动态的生成了一个该 Interface 类型的代理类.在这个代理类中封装了远程服务调用的组件.

DemoService 创建

1
2
<dubbo:reference id="demoService" group="g1" check="true" interface="com.alibaba.dubbo.demo.DemoService"
client="netty4" timeout="10000" callbacks="1000" registry="zk01" filter="demo2">

Spring 容器启动时,AbstractBeanFactory.isFactoryBean() 会判断 demoService 配置的 RootBeanDefinition 的 beanType 为com.alibaba.dubbo.config.spring.ReferenceBean,它是个 FactoryBean,Spring 容器会创建 ReferenceBean 这个 FactoryBean 实例.

获取 DemoService

1
DemoService demoService = (DemoService) context.getBean("demoService"); // get remote service proxy

会调用 factoryBean.getObject() 方法,即调用 ReferenceBean.getObject() 创建 demoService 实例.

DUBBO-issue-2757 debug 时候遇到这个 bug 了,需要在 idea 里设置下.

在服务提供方,Invoker 用于调用服务提供类.在服务消费方,Invoker 用于执行远程调用.

客户端服务引用流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
- refer
- context.getBean("demoService")
- ReferenceBean.getObject():通过这个 FactoryBean 创建 demoService 实例
- ReferenceConfig.init(): 调用父类ReferenceConfig.init()
- ReferenceConfig.createProxy(map)创建DemoService代理对象
- 1.远程引用的逻辑
- 1.1.loadRegistries()加载注册中心URL数组
- 1.2.引用服务invoker = refprotocol.refer(interfaceClass, urls.get(0))
- Protocol$Adaptive.refer()
- ProtocolFilterWrapper.refer()
- ProtocolListenerWrapper.refer()
- RegistryProtocol.refer()
- 1.获取注册中心的url
- 2.获得注册中心registryFactory.getRegistry(url)
- 3.执行服务引用doRefer(cluster, registry, type, url)
- RegistryProtocol.doRefer()
- 1.根据DemoService的type和url创建RegistryDirectory 对象,并设置注册中心
- 2.向注册中心注册自己(服务消费者)registry.register()
- 3.向注册中心订阅 服务提供者 + 路由规则 + 配置规则
- 4.通过cluster创建Invoker对象cluster.join(directory)并返回Invoker
- 1.3.生成invoker的代理对象并返回 return (T) proxyFactory.getProxy(invoker)
- ProxyFactory$Adaptive().getProxy()
- JavassistProxyFactory.getProxy(invoker, interfaces)
- Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker))
- new InvokerInvocationHandler(invoker) // invoker为MockClusterInvoker实例

客户端服务调用

demoService.sayHello(“world”)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
- consumer-call
- demoService.sayHello("world")
- com.alibaba.dubbo.common.bytecode.proxy0.sayHello(name) // 服务代理类
- InvokerInvocationHandler.invoke(proxy, method, args)
- 1.获取参数名和方法名
- 2.RPC调用invoker.invoke(new RpcInvocation(method, args)).recreate()
- 1.将method和参数封装成RpcInvocation对象
- 2.MockClusterInvoker.invoke(invocation)
- result = this.invoker.invoke(invocation)调用FailoverClusterInvoker.invoke(),先走父类AbstractClusterInvoker.invoke()
- 1.通过 directory 获得所有服务提供者 Invoker 集合RegistryDirectory.list(Invocation invocation)
- AbstractClusterInvoker.list(invocation)
- 1.AbstractDirectory.list(invocation)
- RegistryDirectory.doList(invocation)
- 1.从localMethodInvokerMap中根据methodName获取所有匹配的invokers
- 2.根据routers,调用router.route()筛选invokers
- MockInvokersSelector.route()
- 对于普通invoker集合,调用MockInvokersSelector.getNormalInvokers(invokers)
- 不包含 MockInvoker 的情况下,直接返回 `invokers` 集合
- 3.获取loadBalance,默认是RandomLoadBalance实例
- 4.doInvoke(invocation, invokers, loadbalance)执行调用
- FailoverClusterInvoker.doInvoke()中
- 1.获取最大可调用次数: 最大可重试次数 + 1
- 2.select(loadbalance, invocation, copyinvokers, invoked)根据负载均衡机制从 copyinvokers 中选择一个Invoker
- AbstractClusterInvoker.doselect()
- 1.若只有一个invoker直接选择
- 2.如果只有两个Invoker,轮循取
- 3.其余loadbalance.select(invokers, getUrl(), invocation)使用loadbalance获取invoker对象
- // doSelect()具体的loadbalance算法实现
- 3.将选中的invoker添加到invoked(保存已经调用过的invokers)中,并设置到context里
- 4.发起RPC调用并返回result,invoker.invoke(invocation)
- invokerWrapper.invoke(invocation)
- ProtocolFilterWrapper$1.invoke()后面会调用filter链
- 5.调用成功就直接返回result了,失败则根据重试次数和策略重新选中invoker调用