Netty核心源码解析(一)

  1. Netty是什么?
    1. Netty是Jboss提供的一个Java 开源框架,主要针对TCP协议的高并发场景
    2. Netty本质是对Java NIO做了封装的网络通信框架,主要作用是Java NIO基本接口的封装,提供了网络通信中线程同步,编解码,粘包拆包,闪断重连等问题的封装,方便我们利用API方便的开发;
    3. 提供了完整的ssl/tsl支持;
    4. 另外Netty解决了NIO中的selector空轮训的Bug;
    5. Netty 线程模型为多reactor多线程模型-1+n+m,但是Netty提供了灵活配置,也可以实现单reactor单线程,单reactor多线程模型;
  2. Netty的启动流程
    1. 先上代码
public class HelloServer {
    public static void main(String[] args) {
        NioEventLoopGroup bossGroup=new NioEventLoopGroup(1);
        NioEventLoopGroup workGroup=new NioEventLoopGroup();
        new ServerBootstrap()
                //1、绑定线程池组
                .group(bossGroup,workGroup) 
                //2、定义主reactor线程处理Handler
                .handler(new LoggingHandler(LogLevel.DEBUG))
                //3、选择服务器的ServerSocketChannel实现
                .channel(NioServerSocketChannel.class)
                //4、boss:负责处理连接;worker:处理读写,决定了worker(child)能执行哪些操作(handler)
                .childHandler(
                        //5、Channel代表和客户端进行数据读写的通道,Initializer初始化器,负责添加别的handler
                        new ChannelInitializer<NioSocketChannel>() {
                            @Override
                            protected void initChannel(NioSocketChannel ch) throws Exception {
                                //添加具体的handler
                                ch.pipeline().addLast(new StringDecoder()); //17、将ByteBuf转换为字符串,然后给下一个处理器
                                ch.pipeline().addLast(new ChannelInboundHandlerAdapter() { //自定义handler
                                    @Override //读事件
                                    //18、执行channelRead()方法,打印hello
                                    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                        System.out.println("WorkGroup thread name----"+Thread.currentThread().getName());
                                        System.out.println(msg);
                                        System.out.println(ctx.pipeline().names());
                                    }
                                });

                            }
                        })
                //6、绑定监听端口
                .bind(8888);
    }
}
  1. Netty提供了启动引导类ServerBootstrap,使用Builder模式来帮助构建启动Netty服务器程序,提供了灵活的配置需求;
  2. 基本说明--
    1. Netty启动过程就是加载配置项--主从reactor执行线程池组,socketchannel的Handler,监听端口;
    2. 然后创建serversocketchannel注册到主reactor线程上,监听新连接事件,将新的连接分发到从reactor线程的eventloop中;
    3. 这里Netty对serversocketchannel提供了默认的Handler实现对新连接创建socketchannel并分发给从reactor的逻辑;
    4. 首先通过group方法指定了主从reactor线程池组,bossGroup对应主reactor线程,负责监听端口处理连接请求,新连接请求将创建socketchannel并分发注册到workerGroup中的eventloop上,由workerGroup中的eventloop监听IO事件并调用相应的Handler来处理IO事件;
    5. 每一个eventloop对应一个单例线程池,对应一个selector对象,接受一个或多个channel注册,监听读写事件;
    6. Netty启动并初始化的核心逻辑在体现在bind()方法中,bind方法创建serversocketchannel并注册到bossGroup中的eventloop上,并为serversocketchannel提供默认用来创建新连接的Handler----ServerBootstrapAcceptor
    7. 总体来说,网络通信的基本过程为---
      1. 创建serversocketchannel监听端口,处理connect事件
      2. 创建socketchannel监听连接,处理IO事件
      3. 而Netty启动则完成了第一步;
  3. Netty中的核心类型说明
    1. NioEventLoop

Netty启动首先创建了两个nioeventloopgroup对象,这两个对象字面理解就是两个nioEventLoop数组,所以核心是NioEventLoop,看一下源码--

public final class NioEventLoop extends SingleThreadEventLoop {
    private Selector selector;
    private SelectedSelectionKeySet selectedKeys;
    private final SelectorProvider provider;
    private final SelectStrategy selectStrategy;
    //注册socketchannel到selector
    public void register(final SelectableChannel ch, final int interestOps, final NioTask<?> task);
    //重新构建selector--JDK NIO中的selector的空轮训Bug解决方案
    public void rebuildSelector();
    //eventloop运行主逻辑
    protected void run();
}

NioEventLoop可以说是Netty的reactor核心逻辑的实现,主要继承了抽象类SingleThreadEventLoop,单线程处理NIO事件循环通知;而SingleThreadEventLoop的继承和实现关系如下:

 代码实例中只写了极少一部分体现核心逻辑的方法和实例属性,主要为了概念上说明NioEventLoop的工作机制,具体详细的实现在后续专门说明;

NioEventLoop的工作原理-

  1. EventLoop核心是一个线程处理事件循环;
  2. NioEventLoop则是运行selector方法,完成对注册在selector上的channel的网络事件监听,这也就是reactor模型的基本实现----IO多路复用和事件监听;
  3. 另外NioEventLoop继承了SingleThreadEventLoop,除了监听selector之外还可以监听通过父类的execute()方法提交的任务和schedule方法提交的定时任务;
  4. rebuildSelector()方法是NioEventLoop对JDK中的selector空轮训的Bug实现的解决方案----空轮训次数超过默认512次后重新构建一个新的selector对象;
  5. register()方法用于在新连接建立后向EventLoop中的selector注册连接对应的socketchannel;
  6. run()方法则是一个死循环,对selector和注册的其他异步任务进行轮训,监听到事件发生时则执行对应的Handler来处理事件;

        2.NioEventLoopGroup

 NioEventLoopGroup 是一个线程数组,继承了MultithreadEventLoopGroup,

主要提供了对NioEventLoop 初始化的参数,用来创建NioEventLoop实例,默认创建CPU核数*2个线程(EventLoop)--

 另外MultithreadEventLoop继承了EventExecutorChooser选择器的实现,选择器用来做任务分发----NioEventLoopGroup 是一个线程池,当向NioEventLoopGroup注册一个新的channel的时候具体分发给哪一个EventLoop的selector来监听该channel上的IO事件;这里对选择器的实现机制不多做解释,大概对NioEventLoopGroup的主要功能逻辑做一个说明;

        3.ChannelHandler

channelHandler是事件处理器的实现,netty中通过责任链模式实现对事件的层层处理,责任链模式的主体对象是pipeline,相当于一个双向链表,分别对应出站(从服务端到客户端)和入站(从客户端向服务端)方向的事件处理,这里出站和入战是相对的,对本netty服务来说,接收外部的其他服务请求即为入站,反之主动向其他netty服务发出请求即为出站,简单理解为接收数据即为入站,发送数据即为出站;当事件发生的时候,EventLoop就会调用对应的channel的Handler来处理具体的逻辑--底层的ByteBuffer的读写,上层业务逻辑处理等等;

 

总结:netty通过EventLoop单线程执行selector来监听注册在其上的网络IO事件和用户在Handler中提交的异步任务,然后对不同的事件调用不同的Handler来处理;而netty的主体功能此时就体现出来了,第一,实现了reactor线程模型,第二,封装很多网络通信中底层数据的处理逻辑,用户可以通过简单的调用或者继承即可实现相应的功能,从而屏蔽了网络通信底层逻辑的复杂性;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值