欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Nio框架需要注意的两个问题(1)

程序员文章站 2022-03-02 13:48:31
...

研究了一段时间Nio框架,有Netty和Tomcat的Nio Connector总结了一些共性的问题的解决方案。

 

  1. Selector的register和select有锁冲突,例如tomcat的Nio Connector,他采用的Acceptor和Poller的模式,Acceptor只负责接收socket,Poller是负责读写的IO线程,这种模式不用于nginx,Poller(worker)既负责接收和读写的抢占式模块。这样Acceptor和Poller存在的一个交互就是register,Acceptor需要把接收到的socket注册给Poller。Poller实现了Selector执行select和并且遍历selectionKey操作的封装。

 


Nio框架需要注意的两个问题(1)
            
    
    博客分类: nio tomcat netty  

    假设Poller正在执行Selector的select方法并且同时Acceptor又接收了新的socket并执行register操作,这时候就会发生锁等待,集体参看http://xiaoz5919.iteye.com/blog/1518473。该如何解决这个问题呢。

    Tomcat是这样解决的,把注册当成一个event,当有注册发生时添加一个注册事件到队列中,Poller在每次执行select之前先处理注册事件队列。这样保证了register和select的执行顺序是永远是一致的,先执行register再执行select,有效地避免了锁冲突。

 


Nio框架需要注意的两个问题(1)
            
    
    博客分类: nio tomcat netty  

 

  再来看看代码,

 

 

   boolean hasEvents = events();//处理register和cancel事件


                    // Time to terminate?

                    if (close) {

                        timeout(0, false);

                        break;

                    }

                    try {

                        if ( !close ) {

                            if (wakeupCounter.getAndSet(-1) > 0) {

                                //if we are here, means we have other stuff to do

                                //do a non blocking select

                                keyCount = selector.selectNow();

                            } else {

                                keyCount = selector.select(selectorTimeout);

                            }

                            wakeupCounter.set(0);

                        }

 

再看一个细节问题,selector的wakeup是一个很昂贵的工作,假如有多个socket来register也只需一次wakeup,所以tomcat设置了wakeupCounter变量来操作唤醒次数并且只有wakeup==0时才执行一次唤醒操作。

  • Nio框架需要注意的两个问题(1)
            
    
    博客分类: nio tomcat netty  
  • 大小: 19 KB
  • Nio框架需要注意的两个问题(1)
            
    
    博客分类: nio tomcat netty  
  • 大小: 9.1 KB