官网
客户端服务引用
客户端服务引用 demo
1 2
| DemoService demoService = (DemoService) context.getBean("demoService"); 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");
|
会调用 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调用
|