Netty学习(四)----Netty概述以及线程模型

原生NIO存在的问题

  • NIO的类库和API繁杂,使用恶心;
  • 需要周边能力:要熟悉JAVA多线程编程,因为NIO编辑涉及到Reactor模式;
  • 工作复杂:包含客户端面临的断连、网络闪断、半包、黏包、自定义协议等;
  • JDK NIO 的BUG:Epoll 空轮等。

Netty的优点:

  1. 使用 JDK 自带的NIO需要了解太多的概念,编程复杂,一不小心 bug 横飞
  2. Netty 底层 IO 模型随意切换,而这一切只需要做微小的改动,改改参数,Netty可以直接从 NIO 模型变身为 IO 模型
  3. Netty 自带的拆包解包,异常检测等机制让你从NIO的繁重细节中脱离出来,让你只需要关心业务逻辑
  4. Netty 解决了 JDK 的很多包括空轮询在内的 Bug
  5. Netty 底层对线程,selector 做了很多细小的优化,精心设计的 reactor 线程模型做到非常高效的并发处理
  6. 自带各种协议栈让你处理任何一种通用协议都几乎不用亲自动手
  7. Netty 社区活跃,遇到问题随时邮件列表或者 issue
  8. Netty 已经历各大 RPC 框架,消息中间件,分布式通信中间件线上的广泛验证,健壮性无比强大

一) Netty的线程模型


1)单Reactor多线程

在这里插入图片描述

执行过程:

  1. Reactor 对象通过Select监控客户端请求时间,通过dispatch进行分发;
  2. 如果建立连接请求,则左Acceptor通过accept处理连接请求,然后创建一个Handler对象处理完成连接后的各种事情。
  3. 如果不是连接请求,则由reactor分发调用连接对应的handler。
  4. hander只负责响应事件,不去做具体的业务处理,通过read读取数据后,会委派worker线程池进行某个业务处理。
  5. worker线程池会分配独立线程完成真正的任务,并将返回结果告知handler。
  6. handler收到线程池worker后,通过send告知返回结果给client。

优点:利用多核cpu能力
缺点:多线程共享和访问比较复杂,reactor承担所有的事件的监听和响应,在单线程运行,容易形成瓶颈。

2)主(MainReactor)从(SubReactor)Reactor多线程

在这里插入图片描述

执行过程:

  1. Reactor 主线程MainReactor对象通过select监听连接事件,收到事件后,通过Acceptor处理连接事件;
  2. 当Acceptor处理连接事件后,MainReactor将连接分配SubReactor;
  3. SubReactor将连接加入到连接队列进行监听,并创建hander进行各种事件处理(非OP);
  4. 当有新的事件发生时,SubReactor就会调用对应的handler进行处理;
  5. handler通过read读取数据,分发个后面的worker线程处理;
  6. worker线程池会分配独立的worker线程进行业务处理,并返回结果;
  7. handler收到响应的结果后,在通过send将结果返回给Client;

优点:父线程与子线程的数据交互简单职责明确,父线程只需接收新连接,子线程完成后续的操作;
优点:Reactor主线程只需要把新连接传给子线程,子线程无需再返回给主线程。
缺点:编程复杂度高

应用实例:Nginx主从Reactor多线程模型、Memcached主从多线程模型,同时Netty也对模型支持。

3)Netty线程模型

-1:概览

在这里插入图片描述

  1. Boss线程维护Selector,并只关注Accept事件;
  2. 当接收到Acceptor事件后,获取到对应的socketChannel,并进一步封装成NIOSocketChannel注册到Worker线程(事件循环),并进行维护;
  3. 当Worker线程监听到Selector中的通道发生关注的时间后,将任务派发至对应的handler
-2:综述

在这里插入图片描述
Netty主要基于主从Reactor多线程模型做一定更改,其中主从Reactor多线程模型有多个Reactor;

在这里插入图片描述

  1. Netty是抽象出两组线程池的,一组为BossGroup用于接收客户端的连接,WorkerGroup专门负责网络的读写。
  2. BossGroup和WorkerGroup类型都是NioEventLoopGroup。
  3. NioEventLoopGroup相当于事件循环组,这个组中含有很多事件循环,每一个事件循环是NioEventLoop
  4. NioEventLoop表示一个不断循环的执行处理任务的线程,每个NioEventLoop都有一个Selector,用于监听绑定在其上的socket的网络通讯。
  5. NioEventLoopGroup可以有多个线程,既可以含有多个NioEventLoop
  6. 每个Boss NioEventLoop 执行的步骤有3步骤:

1:轮询Acceot事件
2:处理Accept事件,与client建立连接,生成NioSocketChannel,并将其注册到某个worker
NIOEventLoop上的Selector
3:处理任务队列的任务,既runAllTasks

  1. 每个Worker NIOEventLoop循环执行的步骤:

1:轮询read、write事件
2:处理i/o事件,既read、write事件,在NioSocketChannel进行处理
3:处理任务队列的任务,既runAllTasks


TaskQueue

  1. 用户定义的普通任务
  2. 用户定义的定时任务
  3. 非当前Reactor线程调用Channel的各种方法
    例如:在推送系统的业务线程里面,根据用户的标识,找到对应的Channel引用,然后调用Write类方法向该用户推送消息,就会进入到这种场景。最终的Write会提交到任务队列中后被异步消费。
	//如果异步发送,则channelRead不会等待该消息,因为任务加在了scheduleTask中。并且会触发channelReadComplete ,eventLoop().schedule()同样
        ctx.channel().eventLoop().execute(() -> {
            try {
                Thread.sleep(1000 * 10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            ctx.writeAndFlush(Unpooled.copiedBuffer("hello , 客户端\r\n", CharsetUtil.UTF_8));
            System.out.println("go on");
        });

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值