- 注:以im系统为基础开始分析,源码会截取最重要的一部分,而不是全部,以观全貌
- 代码可参考:简易版im聊天系统
1.首先回顾一下同步、异步、阻塞、非阻塞:
同步异步是相对于IO而言的,在同一时间,只能完成一个操作,则为同步(NIO);能同时完成多个操作,则为异步(AIO)。
阻塞非阻塞是相对于数据而言的,判断数据有没有准备好,如果数据没有准备好,则一直等待,则为阻塞(BIO);如果不管数据有没有准备好,都会给一个反馈,客户端可以去做一些其他事情,则为非阻塞。
简单来说,同步异步针对于底层操作系统的IO操作,阻塞非阻塞针对于接口的调用
而Netty是基于NIO的异步非阻塞,异步的原因是加了一个线程池,在同一时间,就能同时完成多个操作,拥有了异步响应;
异步响应是从Handler来体现的,这些Handler组成了Pipeline,即一条无锁化串行的链路
2.开始源码分析
2.1 Bootstrap
其使用链为
EventLoopGroup workerGroup = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
bootstrap .group(workerGroup);
.channel(NioSocketChannel.class);
.option(ChannelOption.SO_KEEPALIVE, true);
.handler(new ChannelInitializer<SocketChannel>() {
。。。
});
ChannelFuture f = b.connect(this.host, this.port).sync();
f.channel().closeFuture().sync();
客户端:Bootstrap;服务端:ServerBootstrap
2.1.1 客户端Bootstrap
2.1.1.1 channel方法:将不同类型的Channel类型放入管道中
首先分析一下Channel的初始化过程:
ChannelFactory负责初始化实现了Channel接口的类,不同协议、不同阻塞类型的连接都有不同的Channel类型与之对应,下图是一些常用的Channel类型:
因为是讲客户端,所以这里看一下NioSocketChannel,其类层次结构图如下:
注意到,NioSocketChannel是Nio客户端的起始类
这里以NioSocketChannel为例,来查看源码:
AbstractBootstrap#
public B channel(Class<? extends C> channelClass) {
return channelFactory(new ReflectiveChannelFactory<C>(channelClass));*
}
ReflectiveChannelFactory#
public ReflectiveChannelFactory(Class<? extends T> clazz) {
this.clazz = clazz;
}
public T newChannel() {
return clazz.newInstance();
}
可以看到,这里初始化了ReflectiveChannelFactory,而ReflectiveChannelFactory实现了ChannelFactory接口,将class保存下来,进行newInstance。即将new的权利交给了框架,类似IOC
那么什么时候调用newChannel呢?调用链如下: