3张图搞懂dubbo的服务注册机制

356 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一.服务注册的整体流程图

3张图搞懂dubbo的服务注册机制

下面我们对每一个步骤进行详细地剖析:

二.构造协议的url

dubbo默认使用dubbo协议,我们写一个自己的服务:

@Service
public class AServiceImpl implements AService {

    @Override
    public void test(){

    }
}

构造出来dubbo协议的url如下:

dubbo://192.168.29.192:28080/com.netty.use.nettyuse.dubbo.AService?anyhost=true&application=dubbodemo-provider&bean.name=ServiceBean:com.netty.use.nettyuse.dubbo.AService&bind.ip=192.168.29.192&bind.port=28080&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=com.netty.use.nettyuse.dubbo.AService&methods=test&pid=34676&qos.enable=false®ister=true&release=2.7.3&side=provider×tamp=1647744853325

这个url在后面的本地服务导出,创建远程连接的Server,服务注册到zk时都会用到。

三.本地服务导出

本地服务导出,是为了服务的消费者和提供者在一个jvm中,避免远程调用的耗时,直接在本地执行。

最终会构造出一个ListenerExporterWrapper对象,并存放在集合中。

四.创建远程连接的Server

我们看下时序图:

3张图搞懂dubbo的服务注册机制

其核心处理就是在于NettyServer的doOpen()方法:

protected void doOpen() throws Throwable {
    bootstrap = new ServerBootstrap();
    //负责接收连接
    bossGroup = new NioEventLoopGroup(1, new DefaultThreadFactory("NettyServerBoss", true));
    //负责处理读写请求
    workerGroup = new NioEventLoopGroup(getUrl().getPositiveParameter(IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS),
            new DefaultThreadFactory("NettyServerWorker", true));

    final NettyServerHandler nettyServerHandler = new NettyServerHandler(getUrl(), this);
    channels = nettyServerHandler.getChannels();

    bootstrap.group(bossGroup, workerGroup)
            .channel(NioServerSocketChannel.class)
            .childOption(ChannelOption.TCP_NODELAY, Boolean.TRUE)
            .childOption(ChannelOption.SO_REUSEADDR, Boolean.TRUE)
            .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
            .childHandler(new ChannelInitializer<NioSocketChannel>() {
                @Override
                protected void initChannel(NioSocketChannel ch) throws Exception {
                    int idleTimeout = UrlUtils.getIdleTimeout(getUrl());
                    NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyServer.this);
                    ch.pipeline()//.addLast("logging",new LoggingHandler(LogLevel.INFO))//for debug
                            .addLast("decoder", adapter.getDecoder())
                            .addLast("encoder", adapter.getEncoder())
                            .addLast("server-idle-handler", new IdleStateHandler(0, 0, idleTimeout, MILLISECONDS))
                            //核心处理类
                           .addLast("handler", nettyServerHandler);
                }
            });
    // bind
    ChannelFuture channelFuture = bootstrap.bind(getBindAddress());
    channelFuture.syncUninterruptibly();
    channel = channelFuture.channel();

}

五.服务注册到zk

服务注册到zk之后,创建的目录结构如下:

3张图搞懂dubbo的服务注册机制

前三级节点是持久化节点。第四级节点为临时节点,连接断开,节点被删除。

服务提供者 注册完之后,会往zk节点 /dubbo/接口名/configurator节点注册监听事件,当该节点发生变化时,会调用NotifyListener监听器实例的notify方法来调用重载配置信息的逻辑。