Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
一.服务注册的整体流程图
下面我们对每一个步骤进行详细地剖析:
二.构造协议的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
我们看下时序图:
其核心处理就是在于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之后,创建的目录结构如下:
前三级节点是持久化节点。第四级节点为临时节点,连接断开,节点被删除。
服务提供者 注册完之后,会往zk节点 /dubbo/接口名/configurator节点注册监听事件,当该节点发生变化时,会调用NotifyListener监听器实例的notify方法来调用重载配置信息的逻辑。