netty--NioEventLoop滴干活

netty是最近项目要用到的nio框架,找了各种资料,发现称赞它的有点多,所以决定用它:其实也就二选一嘛,mina或netty或自己写。对于mina,也不熟,不过看各种介绍,貌似netty干活还是很不错的,尤其是最新的4.x和5.x重构后,且使用结构清晰就先了解了解了。



首先要把应用跑起来啦(官网的例子比较多),我这是一个关于mqtt的一个例子:

 1 m_bossGroup = new NioEventLoopGroup();
 2         m_workerGroup = new NioEventLoopGroup();
 3
 4         final NettyMQTTHandler handler = new NettyMQTTHandler();
 5         handler.setMessaging(messaging);
 6
 7         ServerBootstrap b = new ServerBootstrap();
 8             b.group(m_bossGroup, m_workerGroup)
 9              .channel(NioServerSocketChannel.class)
10              .childHandler(new ChannelInitializer<SocketChannel>() {
11                  @Override
12                  public void initChannel(SocketChannel ch) throws Exception {
13                     ChannelPipeline pipeline = ch.pipeline();
14                     //pipeline.addFirst("metrics", new BytesMetricsHandler(m_metricsCollector));
15                     pipeline.addFirst("idleStateHandler", new IdleStateHandler(0, 0, Constants.DEFAULT_CONNECT_TIMEOUT));
16                     pipeline.addAfter("idleStateHandler", "idleEventHandler", new MoquetteIdleTimoutHandler());
17                     //pipeline.addLast("logger", new LoggingHandler("Netty", LogLevel.ERROR));
18                     pipeline.addLast("decoder", new MQTTDecoder());
19                     pipeline.addLast("encoder", new MQTTEncoder());
20                     pipeline.addLast("metrics", new MessageMetricsHandler(m_metricsCollector));
21                     pipeline.addLast("handler", handler);
22                  }
23              })
24              .option(ChannelOption.SO_BACKLOG, 128)
25              .option(ChannelOption.SO_REUSEADDR, true)
26              .childOption(ChannelOption.SO_KEEPALIVE, true);
27         try {
28             // Bind and start to accept incoming connections.
29             ChannelFuture f = b.bind(Constants.PORT);
30             LOG.info("Server binded");
31             f.sync();
32         } catch (InterruptedException ex) {
33             LOG.error(null, ex);
34         }

再回想下,我们自己写serversocket的时候是怎么写的呢(这是一个笨拙的实例代码):

    ServerSocket socket;
        channel = ServerSocketChannel.open(); // 打开通道
        socket = channel.socket(); //得到与通到相关的socket对象
        socket.bind(new InetSocketAddress(port)); //将scoket榜定在制定的端口上
        //配置通到使用非阻塞模式,在非阻塞模式下,可以编写多道程序同时避免使用复杂的多线程
        channel.configureBlocking(false);
        channel.register(selector, SelectionKey.OP_ACCEPT);
        try {
            while (true) {
                this.selector.select();
                Iterator<SelectionKey> iter = this.selector.selectedKeys().iterator();
                while (iter.hasNext()) {
                    SelectionKey key = iter.next();
                    iter.remove();
                    this.handleKey(key);

                }
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }

原理还是那些,channel.open(),然后register key,然后遍历,再然后才进行handleKey()的干活。

那netty的写法为什么那么潇洒呢,怀着这个莫名的疑问,我先不管它的结构什么的,直接进行search,发现了这么个东东:

1   NioEventLoop(NioEventLoopGroup parent, ThreadFactory threadFactory, SelectorProvider selectorProvider) {
2         super(parent, threadFactory, false);
3         if (selectorProvider == null) {
4             throw new NullPointerException("selectorProvider");
5         }
6         provider = selectorProvider;
7         selector = openSelector();
8     }

其中第8行从名称上来看,有点点意思了,往下看:

1  private Selector openSelector() {
2         final Selector selector;
3         try {
4             selector = provider.openSelector();

其中的provider就是我们熟悉的:java.nio.channels.spi.SelectorProvider类。

所以这个就是做了selector.open的工作。

接下来能看到NioEventLoop:

1     protected void run() {
2         for (;;) {
3             oldWakenUp = wakenUp.getAndSet(false);
4             try {
5                 if (hasTasks()) {
6                     selectNow();
7                 } else {
8                     select();

再继续看,该类中处理的selectedKey:

 1         final NioUnsafe unsafe = ch.unsafe();
 2         if (!k.isValid()) {
 3             // close the channel if the key is not valid anymore
 4             unsafe.close(unsafe.voidPromise());
 5             return;
 6         }
 7
 8         try {
 9             int readyOps = k.readyOps();
10             if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
11                 unsafe.read();
12                 if (!ch.isOpen()) {
13                     // Connection already closed - no need to handle write.
14                     return;
15                 }
16             }
17             if ((readyOps & SelectionKey.OP_WRITE) != 0) {
18                 // Call forceFlush which will also take care of clear the OP_WRITE once there is nothing left to write
19                 ch.unsafe().forceFlush();
20             }
21             if ((readyOps & SelectionKey.OP_CONNECT) != 0) {
22                 // remove OP_CONNECT as otherwise Selector.select(..) will always return without blocking
23                 // See https://github.com/netty/netty/issues/924
24                 int ops = k.interestOps();
25                 ops &= ~SelectionKey.OP_CONNECT;
26                 k.interestOps(ops);
27
28                 unsafe.finishConnect();
29             }
30         } catch (CancelledKeyException e) {
31             unsafe.close(unsafe.voidPromise());
32         }
33     

现在明白了吧,其实netty也是走这么一套逻辑。

然后再网上看,逻辑是这样:

NioEventLoopGroup extends MultithreadEventExecutorGroup,其初始化了n个单线程的线程池(children = new SingleThreadEventExecutor[nThreads];)

每个单线程的对象child[i]=NioEventLoop对象,每个NioEventLoop有一个Selector字段。

其run方法是该group都需要干活的具体业务逻辑代码。

后续再加上别的类说明。

netty--NioEventLoop滴干活

时间: 2024-10-23 16:24:32

netty--NioEventLoop滴干活的相关文章

从Netty EventLoop实现上可以学到什么

本文主要讨论Netty NioEventLoop原理及实践,关于Netty NioEventLoop,首先要知道NioEventLoop是什么,为什么它会是Netty核心Reactor处理器,实现原理是什么,进而再讨论Netty对其的实现及使用上我们可以学到哪些. EventLoop是一个Reactor模型的事件处理器,一个EventLoop对应一个线程,其内部会维护一个selector和taskQueue,负责处理客户端请求和内部任务,内部任务如ServerSocketChannel注册.Se

北京公交驾校早7点无压力100%约车攻略

大家都知道,约车是个痛苦事,麻烦事,就好比每年春节大迁徙时抢火车票类似,但是方法很重要,就好比黄牛党无处不在一样,有一话是酱紫讲滴:100%成功=100%意愿 + 100%方法 + 100%行动,SO,开始吧. 想必大家都晓得,北京公交驾校的网站是采用.NET技术做的,很有远见的说~~~而且,新版的约车站点也独立开来了,还采用了时尚前沿的MVC5,其它的具体时尚细节我就没有去过度探究了,例如:是否各种服务器控件拖拽之类滴干活,哟西. 每当早7点时临近时前10分钟至后2小时内,你要想正常的通过官网

学习go语言编程系列之helloworld

1. 下载https://golang.org/dl/ # Go语言官网地址,在国内下载太慢,甚至都无法访问.通过如下地址下载:https://golangtc.com/download. 2. 安装在windows下,直接一步步点击安装即可. 3. 配置在正式开始go语言编程之前,需要进行一些基础环境变量的配置.在这里主要需要配置2个环境变量:GOROOT和GOPATH.(1)GOROOT:GO的安装路径,需要添加到环境变量中. Linux环境: vim /etc/profile export

程序混子的这几年感悟

终于闲暇,忙了近两月,回首云笔记的这几年,内心汹涌澎湃又归于平静,暂时的也好. 我是名娇生惯养大的坏孩子,大学四年玩的都是游戏,连个像样的妹子都没泡过...大学毕业后,家里介绍的工作,我不愿意干,觉得要自己闯.于是到了电脑市场干起技术员,给人家装装机器,检修个电脑.打印机啥的,还蛮得意.记得有次做了2天的水晶头,手指头都撸肿了,也正是那次综合布线遇见的一个信息科的处长的一番话:你还是大学生啊,你干的这些活,我随便找几个民工就干了.深深打击了我,觉得这种技术含量低的活,工资也就低还得不到人尊重,我

Wireshark明断葫芦案

A:我发了. B:没收到. A:我发了! B:没收到! A:我发了!发了!发了! B:没收到!没收到!没收到! B:计时器到了,看我kill you! A:你,你,你,啊!... 几秒钟后, A:一个崭新的我又来了! B:再不按时发心跳,我还杀了你! A:我不怕,我是九头怪,我是九尾猫. B:计时器到了,看我再kill you! A:你,你,你,啊!... 又过了几秒, A:一个崭新的我又来了! B:真讨厌,还能不能一起愉快滴干活了??? ...... 列位看官,上面这段不是小品,不是相声,而是

java nio 网络框架实现(转)

maven项目https://github.com/solq360/common 链式编/解码 链路层链式处理 管道管理socket 多协议处理非常方便 仿netty NioEventLoop 单线程串行处理 ========侍加功能 : 自动化编/解码 rpc 接口增强使用 简单聊天例子 server TestNioServer //创建session管理工厂 ISessionFactory sessionFactory = new SessionFactory(); //创建编/解码管理 I

[编织消息框架][netty源码分析]4 eventLoop 实现类NioEventLoop职责与实现

NioEventLoop 是jdk nio多路处理实现同修复jdk nio的bug 1.NioEventLoop继承SingleThreadEventLoop 重用单线程处理 2.NioEventLoop是组成 pool EventLoopGroup 基本单元 总之好多边界判断跟业务经验之类的代码,非常烦碎 重要属性 public final class NioEventLoop extends SingleThreadEventLoop { //绑定 selector Selector sel

Netty线程设计5——NioEventLoop

可以看到NioEventLoop中包含selector和selectedKeys,这个selector是在NioEventLoop中初始化的. 由此可以知道Netty中NioEventLoop的个数与selector个数应该是对应的. Selector selector; NioEventLoop(NioEventLoopGroup parent, ThreadFactory threadFactory, SelectorProvider selectorProvider) { super(pa

Netty 源码(五)NioEventLoop

Netty 源码(五)NioEventLoop Netty 基于事件驱动模型,使用不同的事件来通知我们状态的改变或者操作状态的改变.它定义了在整个连接的生命周期里当有事件发生的时候处理的核心抽象. Channel 为 Netty 网络操作抽象类,EventLoop 主要是为 Channel 处理 I/O 操作,两者配合参与 I/O 操作. 下图是 Channel.EventLoop.Thread.EventLoopGroup 之间的关系. 一个 EventLoopGroup 包含一个或多个 Ev