解析Tomcat处理请求的类Connector<1>

http://liudeh-009.iteye.com/blog/1561638

Connector类的相关配置在Tomcat的安装目录conf下的Server.xml文件里,我这次主要解析采用NIO方式处理请求的情况.在Server.xml的配置如下:

  

Xml代码   收藏代码
  1. <Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"  
  2.            connectionTimeout="20000"  
  3.            redirectPort="8443" />  

 

在tomcat启动的时候,会调用Connector类的Start()方法,根据以上配置,Connector的start方法里会调用Http11NioProtocol类的start()方法,如下:

   

Java代码   收藏代码
  1. try {  
  2.            protocolHandler.start();  
  3.        } catch (Exception e) {  
  4.            String errPrefix = "";  
  5.            if(this.service != null) {  
  6.                errPrefix += "service.getName(): \"" + this.service.getName() + "\"; ";  
  7.            }  
  8.   
  9.            throw new LifecycleException  
  10.                (errPrefix + " " + sm.getString  
  11.                 ("coyoteConnector.protocolHandlerStartFailed", e));  
  12.        }  

   Http11NioProtocol类的start()方法又会调用NioEndpoint类的start()方法,如下:

    

Java代码   收藏代码
  1. try {  
  2.            ep.start();  
  3.        } catch (Exception ex) {  
  4.            log.error(sm.getString("http11protocol.endpoint.starterror"), ex);  
  5.            throw ex;  
  6.        }  

 

    NioEndpoint类的start()方法如下:

    

Java代码   收藏代码
  1. public void start()  
  2.         throws Exception {  
  3.         // Initialize socket if not done before  
  4.         if (!initialized) {  
  5.             init();  
  6.         }  
  7.         if (!running) {  
  8.             running = true;  
  9.             paused = false;  
  10.               
  11.             // Create worker collection  
  12.             if (getUseExecutor()) {  
  13.                 if ( executor == null ) {  
  14.                     TaskQueue taskqueue = new TaskQueue();  
  15.                     TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-");  
  16.                     executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf);  
  17.                     taskqueue.setParent( (ThreadPoolExecutor) executor, this);  
  18.                 }  
  19.             } else if ( executor == null ) {//avoid two thread pools being created  
  20.                 workers = new WorkerStack(maxThreads);  
  21.             }  
  22.   
  23.             // Start poller threads轮询线程的个数,默认等译cpu的个数  
  24.             pollers = new Poller[getPollerThreadCount()];  
  25.             for (int i=0; i<pollers.length; i++) {  
  26.                 pollers[i] = new Poller();  
  27.                 Thread pollerThread = new Thread(pollers[i], getName() + "-ClientPoller-"+i);  
  28.                 pollerThread.setPriority(threadPriority);  
  29.                 pollerThread.setDaemon(true);  
  30.                 pollerThread.start();  
  31.             }  
  32.   
  33.             // Start acceptor threads  
  34.             for (int i = 0; i < acceptorThreadCount; i++) {  
  35.                 Thread acceptorThread = new Thread(new Acceptor(), getName() + "-Acceptor-" + i);  
  36.                 acceptorThread.setPriority(threadPriority);  
  37.                 acceptorThread.setDaemon(daemon);  
  38.                 acceptorThread.start();  
  39.             }  
  40.         }  
  41.     }  

    该方式初始化了处理接受Sockt的线程Acceptor,轮询sockt的线程Poller,真正处理socket的线程池executor 或workers.Acceptor类的run方法如下:

  

Java代码   收藏代码
  1. public void run() {  
  2.             // Loop until we receive a shutdown command  
  3.             while (running) {  
  4.                 // Loop if endpoint is paused  
  5.                 while (paused) {  
  6.                     try {  
  7.                         Thread.sleep(1000);  
  8.                     } catch (InterruptedException e) {  
  9.                         // Ignore  
  10.                     }  
  11.                 }  
  12.                 try {  
  13.                     // Accept the next incoming connection from the server socket  
  14.                     SocketChannel socket = serverSock.accept();  
  15.                     // Hand this socket off to an appropriate processor  
  16.                     //TODO FIXME - this is currently a blocking call, meaning we will be blocking  
  17.                     //further accepts until there is a thread available.  
  18.                     if ( running && (!paused) && socket != null ) {  
  19.                         //processSocket(socket);  
  20.                        <span style="color: #ff0000;"if (!setSocketOptions(socket))</span> {//把sockt交给poller数组  
  21.                             try {  
  22.                                 socket.socket().close();  
  23.                                 socket.close();  
  24.                             } catch (IOException ix) {  
  25.                                 if (log.isDebugEnabled())  
  26.                                     log.debug("", ix);  
  27.                             }  
  28.                         }   
  29.                     }  
  30.                 }catch (SocketTimeoutException sx) {  
  31.                     //normal condition  
  32.                 }catch ( IOException x ) {  
  33.                     if ( running ) log.error(sm.getString("endpoint.accept.fail"), x);  
  34.                 } catch (OutOfMemoryError oom) {  
  35.                     try {  
  36.                         oomParachuteData = null;  
  37.                         releaseCaches();  
  38.                         log.error("", oom);  
  39.                     }catch ( Throwable oomt ) {  
  40.                         try {  
  41.                             try {  
  42.                                 System.err.println(oomParachuteMsg);  
  43.                                 oomt.printStackTrace();  
  44.                             }catch (Throwable letsHopeWeDontGetHere){}  
  45.                         }catch (Throwable letsHopeWeDontGetHere){}  
  46.                     }  
  47.                 } catch (Throwable t) {  
  48.                     log.error(sm.getString("endpoint.accept.fail"), t);  
  49.                 }  
  50.             }//while  
  51.         }//run  

 

      setSocketOptions(Socket socket)如下:

       

            

Java代码   收藏代码
  1. /** 
  2.     * Process the specified connection. 
  3.     */  
  4.    protected boolean setSocketOptions(SocketChannel socket) {  
  5.        // Process the connection  
  6.        try {  
  7.            //disable blocking, APR style, we are gonna be polling it  
  8.            socket.configureBlocking(false);  
  9.            Socket sock = socket.socket();  
  10.            socketProperties.setProperties(sock);  
  11.   
  12.            NioChannel channel = nioChannels.poll();  
  13.            if ( channel == null ) {  
  14.                // SSL setup  
  15.                if (sslContext != null) {  
  16.                    SSLEngine engine = createSSLEngine();  
  17.                    int appbufsize = engine.getSession().getApplicationBufferSize();  
  18.                    NioBufferHandler bufhandler = new NioBufferHandler(Math.max(appbufsize,socketProperties.getAppReadBufSize()),  
  19.                                                                       Math.max(appbufsize,socketProperties.getAppWriteBufSize()),  
  20.                                                                       socketProperties.getDirectBuffer());  
  21.                    channel = new SecureNioChannel(socket, engine, bufhandler, selectorPool);  
  22.                } else {  
  23.                    // normal tcp setup  
  24.                    NioBufferHandler bufhandler = new NioBufferHandler(socketProperties.getAppReadBufSize(),  
  25.                                                                       socketProperties.getAppWriteBufSize(),  
  26.                                                                       socketProperties.getDirectBuffer());  
  27.   
  28.                    channel = new NioChannel(socket, bufhandler);  
  29.                }  
  30.            } else {                  
  31.                channel.setIOChannel(socket);  
  32.                if ( channel instanceof SecureNioChannel ) {  
  33.                    SSLEngine engine = createSSLEngine();  
  34.                    ((SecureNioChannel)channel).reset(engine);  
  35.                } else {  
  36.                    channel.reset();  
  37.                }  
  38.            }  
  39.            //将socket注册到Poller的Selector上  
  40.            <span style="color: #ff0000;">getPoller0().register(channel);</span>  
  41.        } catch (Throwable t) {  
  42.            try {  
  43.                log.error("",t);  
  44.            }catch ( Throwable tt){}  
  45.            // Tell to close the socket  
  46.            return false;  
  47.        }  
  48.        return true;  
  49.    }  

 getPoller0()方法如下:

   

Java代码   收藏代码
  1. public Poller getPoller0() {  
  2.     int idx = Math.abs(pollerRotater.incrementAndGet()) % pollers.length;  
  3.     return pollers[idx];  
  4. }  

 Poller的register()方法如下:

     

Java代码   收藏代码
  1. public void register(final NioChannel socket)  
  2.  {  
  3.      socket.setPoller(this);  
  4.      KeyAttachment key = keyCache.poll();  
  5.      final KeyAttachment ka = key!=null?key:new KeyAttachment();  
  6.      ka.reset(this,socket,getSocketProperties().getSoTimeout());  
  7.      PollerEvent r = eventCache.poll();  
  8. tyle="color: #000000;">            ka.interestOps(SelectionKey.OP_READ);//this is what OP_REGISTER turns into.</span>  
  9.      if ( r==null) r = new PollerEvent(socket,ka,OP_REGISTER);  
  10.      else r.reset(socket,ka,OP_REGISTER);  
  11.      <span style="color: #ff0000;">addEvent(r);//将sockt注册到Poller的队列中</span>  
  12.  }  

  addEvent()方法如下:

      

Java代码   收藏代码
  1. public void addEvent(Runnable event) {  
  2.          events.offer(event);  
  3.          if ( wakeupCounter.incrementAndGet() == 0 ) selector.wakeup();  
  4.      }  

 

  Poller的run()方法如下:

         

Java代码   收藏代码
  1. public void run() {  
  2.            // Loop until we receive a shutdown command  
  3.            while (running) {  
  4.                try {  
  5.                    // Loop if endpoint is paused  
  6.                    while (paused && (!close) ) {  
  7.                        try {  
  8.                            Thread.sleep(100);  
  9.                        } catch (InterruptedException e) {  
  10.                            // Ignore  
  11.                        }  
  12.                    }  
  13.                    boolean hasEvents = false;  
  14.   
  15.                    <span style="color: #ff0000;">hasEvents = (hasEvents | events());//往Selector注册Socket事件</span>  
  16.                    // Time to terminate?  
  17.                    if (close) {  
  18.                        timeout(0false);  
  19.                        break;  
  20.                    }  
  21.                    int keyCount = 0;  
  22.                    try {  
  23.                        if ( !close ) {  
  24.                            if (wakeupCounter.getAndSet(-1) > 0) {  
  25.                                //if we are here, means we have other stuff to do  
  26.                                //do a non blocking select  
  27.                                keyCount = selector.selectNow();  
  28.                            } else {  
  29.                                keyCount = selector.select(selectorTimeout);  
  30.                            }  
  31.                            wakeupCounter.set(0);  
  32.                        }  
  33.                        if (close) {  
  34.                            timeout(0false);  
  35.                            selector.close();   
  36.                            break;   
  37.                        }  
  38.                    } catch ( NullPointerException x ) {  
  39.                        //sun bug 5076772 on windows JDK 1.5  
  40.                        if ( log.isDebugEnabled() ) log.debug("Possibly encountered sun bug 5076772 on windows JDK 1.5",x);  
  41.                        if ( wakeupCounter == null || selector == null ) throw x;  
  42.                        continue;  
  43.                    } catch ( CancelledKeyException x ) {  
  44.                        //sun bug 5076772 on windows JDK 1.5  
  45.                        if ( log.isDebugEnabled() ) log.debug("Possibly encountered sun bug 5076772 on windows JDK 1.5",x);  
  46.                        if ( wakeupCounter == null || selector == null ) throw x;  
  47.                        continue;  
  48.                    } catch (Throwable x) {  
  49.                        log.error("",x);  
  50.                        continue;  
  51.                    }  
  52.                    //either we timed out or we woke up, process events first  
  53.                    if ( keyCount == 0 ) hasEvents = (hasEvents | events());  
  54.   
  55.                    Iterator iterator = keyCount > 0 ? selector.selectedKeys().iterator() : null;  
  56.                    // Walk through the collection of ready keys and dispatch  
  57.                    // any active event.  
  58.                    while (iterator != null && iterator.hasNext()) {  
  59.                        SelectionKey sk = (SelectionKey) iterator.next();  
  60.                        KeyAttachment attachment = (KeyAttachment)sk.attachment();  
  61.                        // Attachment may be null if another thread has called  
  62.                        // cancelledKey()  
  63.                        if (attachment == null) {  
  64.                            iterator.remove();  
  65.                        } else {  
  66.                            attachment.access();  
  67.                            iterator.remove();  
  68.                    <span style="color: #000000;">        <span>processKey(sk, attachment);//将Socket交由线程池executor 或workers处理</span></span>  
  69.                        }  
  70.                    }//while  
  71.   
  72.                    //process timeouts  
  73.                    timeout(keyCount,hasEvents);  
  74.                    if ( oomParachute > 0 && oomParachuteData == null ) checkParachute();  
  75.                } catch (OutOfMemoryError oom) {  
  76.                    try {  
  77.                        oomParachuteData = null;  
  78.                        releaseCaches();  
  79.                        log.error("", oom);  
  80.                    }catch ( Throwable oomt ) {  
  81.                        try {  
  82.                            System.err.println(oomParachuteMsg);  
  83.                            oomt.printStackTrace();  
  84.                        }catch (Throwable letsHopeWeDontGetHere){}  
  85.                    }  
  86.                }  
  87.            }//while  
  88.            synchronized (this) {  
  89.                this.notifyAll();  
  90.            }  
  91.            stopLatch.countDown();  
  92.   
  93.        }  

 

       后续就是处理sockt请求,返回处理结果到浏览器端

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值