dubbo与zk注册中心如何对接,如何作到服务自动发现

先看下consumer端发起调用时的链路流程:html

+---------------------------+            +---------------------------+            +---------------------------+              
 |      helloService         |            |      proxy                |            |  InvokerInvocationHandler |              
 |      sayHello             +----------> |      sayHello             +----------> |  invoke                   |              
 |                           |            |                           |            |  proxy method args        |              
 +---------------------------+            +---------------------------+            +-------------+-------------+              
                                                                                                 |                            
                                                                                                 |                            
                                                                                  +---------------------------------+         
                                                                                  |              |                  |         
                                                                                  | +------------v--------------+   |         
                                                                                  | |  MockClusterInvoker       |   |         
                                                                                  | |  invoke                   |   |         
                                                                                  | |                           |   |         
                                                                                  | +------------+--------------+   |         
                                                                                  |              |                  |         
                                                                                  |              |                  |         
                                                                                  |              |                  |         
 +---------------------------+            +---------------------------+           | +------------v--------------+   |         
 | Router                    |            | RegistryDirectory         |           | |  FailoverClusterInvoker   |   |         
 | route                     | <----------+ list                      | <-----------+  invoke                   |   |         
 | MockInVokersSelector      |            | INVOCATION-->List INVOKER |           | |                           |   |         
 +------------+--------------+            +---------------------------+           | +---------------------------+   |         
              |                                                                   |                                 |         
              |                                                                   +---------------------------------+         
              |                                                                 cluster invoke,分布式调用容错机制也是在这作                      
              |                                                                                                               
              |                                                                                                               
              |                                                                                                               
              |                                                                                                               
              |                                                                                                               
+-------------v-------------+             +---------------------------+             +---------------------------+             
|  RandomLoadBalance        |             |InvokerDelegate            |             | ListenerInvokerWrap       |             
|  select                   +-----------> |invoke                     +-----------> | invoke                    |             
|  List INVOKER-->INVOKER   |             |                           |             |                           |             
+---------------------------+             +---------------------------+             +---------------------------+

1. 引入zookeeper做为注册中心后,服务查找过程

从创建spring到netty client创建链接的调用栈:
NettyClient.doOpen() line: 66
NettyClient(AbstractClient). (URL, ChannelHandler) line: 94
NettyClient. (URL, ChannelHandler) line: 61
NettyTransporter.connect(URL, ChannelHandler) line: 37
Transporter$Adpative.connect(URL, ChannelHandler) line: not available
Transporters.connect(URL, ChannelHandler...) line: 67
HeaderExchanger.connect(URL, ExchangeHandler) line: 37
Exchangers.connect(URL, ExchangeHandler) line: 102
DubboProtocol.initClient(URL) line: 378
DubboProtocol.getSharedClient(URL) line: 344
DubboProtocol.getClients(URL) line: 321
DubboProtocol.refer(Class , URL) line: 303
ProtocolListenerWrapper.refer(Class , URL) line: 65
ProtocolFilterWrapper.refer(Class , URL) line: 62
Protocol$Adpative.refer(Class, URL) line: not available
RegistryDirectory .toInvokers(List ) line: 405
RegistryDirectory .refreshInvoker(List ) line: 228
RegistryDirectory .notify(List ) line: 196
ZookeeperRegistry(AbstractRegistry).notify(URL, NotifyListener, List ) line: 449
ZookeeperRegistry(FailbackRegistry).doNotify(URL, NotifyListener, List ) line: 273
ZookeeperRegistry(FailbackRegistry).notify(URL, NotifyListener, List ) line: 259
ZookeeperRegistry.doSubscribe(URL, NotifyListener) line: 170
ZookeeperRegistry(FailbackRegistry).subscribe(URL, NotifyListener) line: 189
RegistryDirectory .subscribe(URL) line: 134
RegistryProtocol.doRefer(Cluster, Registry, Class , URL) line: 271
RegistryProtocol.refer(Class , URL) line: 254
ProtocolListenerWrapper.refer(Class , URL) line: 63
ProtocolFilterWrapper.refer(Class , URL) line: 60
Protocol$Adpative.refer(Class, URL) line: not available
ReferenceBean (ReferenceConfig ).createProxy() line: 394
ReferenceBean (ReferenceConfig ).init() line: 303
ReferenceBean (ReferenceConfig ).get() line: 138
ReferenceBean .getObject() line: 65
DefaultListableBeanFactory(FactoryBeanRegistrySupport).doGetObjectFromFactoryBean(FactoryBean, String, boolean) line: 142
java

总体来讲: 先由注册中心的协议处理器处理注册中心的地址,找到全部provider的地址,建立全部invoker,而后再由invoker在真正调用时发起调用。
注册中心的这个也抽象一种协议,由注册中心结合提供者的协议推导出提供者的协议地址,也就是目标端的地址与端口得知了。
每个接口在zookeeper上都有节点,节点下面是provider,再下面是全部provider的具体地址。spring

2. netty client的基本步骤

建立channelPipelineFactory,并在这个factory中返回加工好的ChannelPipeline,加工过程包括加入编解码器,链接事件处理组成的netty handler实现
(包括链接创建,断开,请求写出去,)app

writeRequested(netty的)-->调用编码器(编码的这个对象中包括了 须要调用的目标接口名 方法名等信息)
(继承SimpleChannelHandler重写逻辑,能够定制channel的读取与写出逻辑)dom

3. 在使用zookeeper做为注册中心时,若是有provider服务停掉, consumer端如何感知?再次启动刚停掉的provider呢?

provider停掉会触发zk客户端的监听,监听对客户端的invoker列表进行刷新。
再次启动会触发 zk的监听,代码在ZkclientZookeeperClient分布式

public IZkChildListener createTargetChildListener(String path, final ChildListener listener) {
        return new IZkChildListener() {
            public void handleChildChange(String parentPath, List<String> currentChilds)
                    throws Exception {
                listener.childChanged(parentPath, currentChilds);
            }
        };
    }

而后再触发 com.alibaba.dubbo.registry.support.FailbackRegistry.doNotify(URL, NotifyListener, List )。
com.alibaba.dubbo.registry.integration.RegistryDirectory.refreshInvoker(List ), 这是在zk的event线程完成的。
若是有provider停掉了 走同样的监听逻辑
ide

同时,dubbo支持 定时检查provider的状态并进行重连,具体参见
com.alibaba.dubbo.remoting.transport.AbstractClient.initConnectStatusCheckCommand()
reconnectExecutorService.scheduleWithFixedDelay(connectStatusCheckCommand, reconnect, reconnect, TimeUnit.MILLISECONDS);this

4. 若是正在发服务的时候,provider停掉了,dubbo是如何处理的?

若是在发服务时,provider停掉了,那么此时会抛出异常,并在FailoverClusterInvoker doInvoke中捕获,
FailoverClusterInvoker支持调用失败时重试(可配置),此时达到再次重试的目的。编码

5. client在屡次调用时,与provider端的链接是创建几回,在prodvider端服务状态有变化时呢?

NettyClient 的doOpen doConnect均在初始化的时候调用,有几个provider就调用几回,真正rpc调用服务的时候是不会再调用open与connect的。
上面这个说法不严格,由于看他发送消息的代码就知道了,每次发消息时还会检查下:url

public void send(Object message, boolean sent) throws RemotingException {
    if (send_reconnect && !isConnected()){
        connect();
    }
    Channel channel = getChannel();
    //TODO getChannel返回的状态是否包含null须要改进
    if (channel == null || ! channel.isConnected()) {
      throw new RemotingException(this, "message can not send, because channel is closed . url:" + getUrl());
    }
    channel.send(message, sent);
}

6. 对于多个provider,dubbo默认在哪里选择了一个invoker进行调用的

com.alibaba.dubbo.rpc.cluster.support.AbstractClusterInvoker.select(LoadBalance, Invocation, List<Invoker >, List<Invoker >)。

com.alibaba.dubbo.rpc.filter.EchoFilter@1fd14d74 com.alibaba.dubbo.rpc.filter.ClassLoaderFilter@563e4951 com.alibaba.dubbo.rpc.filter.GenericFilter@4066c471 com.alibaba.dubbo.rpc.filter.ContextFilter@2b175c00 com.alibaba.dubbo.rpc.protocol.dubbo.filter.TraceFilter@3eb81efb com.alibaba.dubbo.rpc.filter.TimeoutFilter@1ae8bcbc com.alibaba.dubbo.monitor.support.MonitorFilter@6cdba6dc com.alibaba.dubbo.rpc.filter.ExceptionFilter@2609b277

相关文章
相关标签/搜索