tomcat网络模型

孤者浪人 提交于 2020-08-17 16:49:42

一、概述

tomcat的网络模型有三种,分别是 JIO(即BIO), NIO,NIO2(即AIO)。tomcat7之前包含JIO和NIO,tomcat8之后的版本包含NIO和NIO2。tomcat7默认是JIO,tomcat8之后默认的IO是NIO。这三种IO性能上从高到低  NIO2 > NIO > JIO。下面分别对这三种IO做具体源码级的分析。

JIO API: java.net.ServerSocket、java.net.Socket

NIO API: java.nio.channels.ServerSocketChannel 、 java.nio.channels.SocketChannel 、 java.nio.channels.Selector

NIO2 API: java.nio.channels.AsynchronousServerSocketChannel、 java.nio.channels.AsynchronousSocketChannel

二、JIO

流程步骤:

  1. JIoEndpoint.Acceptor    负责无线循环获取socket连接
  2. 判断是否超过最大并发
  3. 接收到socket连接请求,为socket设置自定义属性
  4. 将socket包装成  SocketWrapper
  5. 创建一个 SocketWrapper 的处理器 SocketProcessor
  6. 将SocketProcessor处理器扔进线程池执行
protected class JIoEndpoint.Acceptor extends AbstractEndpoint.Acceptor {
       @Override
       public void run() {
           while (running) {
               state = AcceptorState.RUNNING;
               try {
                   // 判断是否超过最大并发
                   countUpOrAwaitConnection();
 
                   Socket socket = null;
                   try {
                       // 接收到socket连接请求
                       socket = serverSocketFactory.acceptSocket(serverSocket);
                   } catch (IOException ioe) {
                       countDownConnection();
                   }
                  
                   // 为socket设置自定义属性
                   if (running && !paused && setSocketOptions(socket)) {
                       // Hand this socket off to an appropriate processor
                       if (!processSocket(socket)) {
                           countDownConnection();
                           // Close socket right away
                           closeSocket(socket);
                       }
                   }
               } catch (Exception x) {
               }
           }
           state = AcceptorState.ENDED;
       }
   }
 
   protected boolean processSocket(Socket socket) {
       // Process the request from this socket
       try {
           // 将socket包装成  SocketWrapper
           SocketWrapper<Socket> wrapper = new SocketWrapper<Socket>(socket);
           wrapper.setKeepAliveLeft(getMaxKeepAliveRequests());
           wrapper.setSecure(isSSLEnabled());
           // During shutdown, executor may be null - avoid NPE
           if (!running) {
               return false;
           }
           // 创建一个 SocketWrapper 的处理器 SocketProcessor
           // 将SocketProcessor处理器扔进线程池执行
           getExecutor().execute(new SocketProcessor(wrapper));
       } catch (RejectedExecutionException x) {
           log.warn("Socket processing request was rejected for:"+socket,x);
           return false;
       } catch (Throwable t) {
           ExceptionUtils.handleThrowable(t);
           // This means we got an OOM or similar creating a thread, or that
           // the pool and its queue are full
           log.error(sm.getString("endpoint.process.fail"), t);
           return false;
       }
       return true;
   }

二、NIO

流程步骤:

  1. NioEndpoint.Acceptor    负责无线循环获取socket连接
  2. 判断是否超过最大并发
  3. 接收到SocketChannel连接请求,为SocketChannel设置自定义属性
  4. 将SocketChannel封装成NioChannel
  5. 将NioChannel封装成NioSocketWrapper
  6. 根据NioChannel和NioSocketWrapper封装成PollerEvent的注册事件
  7. Poller拉倒PollerEvent的注册事件
  8. 注册读事件在selector选择器上
  9. Poller拉取到读取数据的key
  10. 将读取数据的事件封装成 SocketProcessor 扔到线程池处理
protected class NioEndpoint.Acceptor extends AbstractEndpoint.Acceptor {
    @Override
    public void run() {
        while (running) {
            state = AcceptorState.RUNNING;
            try {
                // 判断是否超过最大并发
                countUpOrAwaitConnection();
 
                SocketChannel socket = null;
                try {
                   // 接收到SocketChannel连接请求,
                    socket = serverSock.accept();
                } catch (IOException ioe) {
                    // We didn't get a socket
                    countDownConnection();
                    
                }
      
                // Configure the socket
                if (running && !paused) {
                    // 为SocketChannel设置自定义属性
                    if (!setSocketOptions(socket)) {
                        closeSocket(socket);
                    }
                } else {
                    closeSocket(socket);
                }
            } catch (Throwable t) {
                ExceptionUtils.handleThrowable(t);
                log.error(sm.getString("endpoint.accept.fail"), t);
            }
        }
        state = AcceptorState.ENDED;
    }
 
 
protected boolean setSocketOptions(SocketChannel socket) {
    // Process the connection
    try {
        //disable blocking, APR style, we are gonna be polling it
        socket.configureBlocking(false);
        Socket sock = socket.socket();
        // 为SocketChannel设置自定义属性
        socketProperties.setProperties(sock);
 
        // 从对象缓存池获取NioChannel
        NioChannel channel = nioChannels.pop();
        if (channel == null) {
            // 缓存池不存在,new一个NioChannel
            SocketBufferHandler bufhandler = new SocketBufferHandler(
                    socketProperties.getAppReadBufSize(),
                    socketProperties.getAppWriteBufSize(),
                    socketProperties.getDirectBuffer());
            if (isSSLEnabled()) {
                channel = new SecureNioChannel(socket, bufhandler, selectorPool, this);
            } else {
                channel = new NioChannel(socket, bufhandler);
            }
        } else {
            channel.setIOChannel(socket);
            channel.reset();
        }
        // 注册channel
        getPoller0().register(channel);
    } catch (Throwable t) {
        ExceptionUtils.handleThrowable(t);
        try {
            log.error("",t);
        } catch (Throwable tt) {
            ExceptionUtils.handleThrowable(tt);
        }
        // Tell to close the socket
        return false;
    }
    return true;
}
 
 
 public void register(final NioChannel socket) {
        socket.setPoller(this);
        // 将NioChannel封装成NioSocketWrapper
        NioSocketWrapper ka = new NioSocketWrapper(socket, NioEndpoint.this);
        socket.setSocketWrapper(ka);
        ka.setPoller(this);
        ka.setReadTimeout(getSocketProperties().getSoTimeout());
        ka.setWriteTimeout(getSocketProperties().getSoTimeout());
        ka.setKeepAliveLeft(NioEndpoint.this.getMaxKeepAliveRequests());
        ka.setSecure(isSSLEnabled());
        ka.setReadTimeout(getConnectionTimeout());
        ka.setWriteTimeout(getConnectionTimeout());
 
 
        // 根据NioChannel和NioSocketWrapper封装成PollerEvent的注册事件
        PollerEvent r = eventCache.pop();
        ka.interestOps(SelectionKey.OP_READ);//this is what OP_REGISTER turns into.
        if ( r==null) r = new PollerEvent(socket,ka,OP_REGISTER);
        else r.reset(socket,ka,OP_REGISTER);
 
 
        // 将event放入队列中,供poller拉取
        addEvent(r);
    }
 
    // Poller.run()
    @Override
    public void run() {
        // Loop until destroy() is called
        while (true) {
 
            boolean hasEvents = false;
 
            try {
                if (!close) {
                    // 执行事件
                    hasEvents = events();
                    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);
                }
                if (close) {
                    events();
                    timeout(0, false);
                    try {
                        selector.close();
                    } catch (IOException ioe) {
                        log.error(sm.getString("endpoint.nio.selectorCloseFail"), ioe);
                    }
                    break;
                }
            } catch (Throwable x) {
                ExceptionUtils.handleThrowable(x);
                log.error("",x);
                continue;
            }
            //either we timed out or we woke up, process events first
            if ( keyCount == 0 ) hasEvents = (hasEvents | events());
 
            Iterator<SelectionKey> iterator =
                keyCount > 0 ? selector.selectedKeys().iterator() : null;
            // Walk through the collection of ready keys and dispatch
            // any active event.
            while (iterator != null && iterator.hasNext()) {
                SelectionKey sk = iterator.next();
                NioSocketWrapper attachment = (NioSocketWrapper)sk.attachment();
                // Attachment may be null if another thread has called
                // cancelledKey()
                if (attachment == null) {
                    iterator.remove();
                } else {
                    iterator.remove();
                    processKey(sk, attachment);
                }
            }//while
 
            //process timeouts
            timeout(keyCount,hasEvents);
        }//while
 
        getStopLatch().countDown();
    }

三、NIO2

流程步骤:

  1. Nio2Endpoint.Acceptor    负责无线循环获取socket连接
  2. 判断是否超过最大并发 
  3. 接收到AsynchronousSocketChannel连接请求,为AsynchronousSocketChannel设置自定义属性(阻塞)
  4. 将AsynchronousSocketChannel封装成Nio2Channel
  5. 将Nio2Channel封装成Nio2SocketWrapper
  6. 将Nio2SocketWrapper和读取数据的事件封装成 SocketProcessor 扔到线程池处理
  7. 数据异步回调(org.apache.tomcat.util.net.Nio2Endpoint.Nio2SocketWrapper.readCompletionHandler)
protected class Nio2Endpoint.Acceptor extends AbstractEndpoint.Acceptor {
 
        @Override
        public void run() {
 
            int errorDelay = 0;
 
            // Loop until we receive a shutdown command
            while (running) {
                state = AcceptorState.RUNNING;
 
                try {
                    // 判断是否超过最大并发
                    countUpOrAwaitConnection();
 
                    AsynchronousSocketChannel socket = null;
                    try {
                        //接收到AsynchronousSocketChannel连接请求
                        socket = serverSock.accept().get();
                    } catch (Exception e) {
                        // We didn't get a socket
                        countDownConnection();
                        if (running) {
                            // Introduce delay if necessary
                            errorDelay = handleExceptionWithDelay(errorDelay);
                            // re-throw
                            throw e;
                        } else {
                            break;
                        }
                    }
                    // Successful accept, reset the error delay
                    errorDelay = 0;
 
                    // Configure the socket
                    if (running && !paused) {
                        // 为AsynchronousSocketChannel设置自定义属性,并且执行后续流程
                        if (!setSocketOptions(socket)) {
                            closeSocket(socket);
                        }
                    } else {
                        closeSocket(socket);
                    }
                } catch (Throwable t) {
                    ExceptionUtils.handleThrowable(t);
                    log.error(sm.getString("endpoint.accept.fail"), t);
                }
            }
            state = AcceptorState.ENDED;
        }
 
 
        protected boolean setSocketOptions(AsynchronousSocketChannel socket) {
        try {
            //
            socketProperties.setProperties(socket);
 
 
            // 将AsynchronousSocketChannel封装成Nio2Channel
            Nio2Channel channel = nioChannels.pop();
            if (channel == null) {
                SocketBufferHandler bufhandler = new SocketBufferHandler(socketProperties.getAppReadBufSize(),
                        socketProperties.getAppWriteBufSize(), socketProperties.getDirectBuffer());
                if (isSSLEnabled()) {
                    channel = new SecureNio2Channel(bufhandler, this);
                } else {
                    channel = new Nio2Channel(bufhandler);
                }
            }
            // 将Nio2Channel封装成Nio2SocketWrapper
            Nio2SocketWrapper socketWrapper = new Nio2SocketWrapper(channel, this);
            channel.reset(socket, socketWrapper);
            socketWrapper.setReadTimeout(getSocketProperties().getSoTimeout());
            socketWrapper.setWriteTimeout(getSocketProperties().getSoTimeout());
            socketWrapper.setKeepAliveLeft(Nio2Endpoint.this.getMaxKeepAliveRequests());
            socketWrapper.setSecure(isSSLEnabled());
            socketWrapper.setReadTimeout(getConnectionTimeout());
            socketWrapper.setWriteTimeout(getConnectionTimeout());
            // 将Nio2SocketWrapper和读取数据的事件封装成 SocketProcessor 扔到线程池处理
            return processSocket(socketWrapper, SocketEvent.OPEN_READ, true);
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            log.error("", t);
        }
        // Tell to close the socket
        return false;
    }
 
 
    public boolean processSocket(SocketWrapperBase<S> socketWrapper,
            SocketEvent event, boolean dispatch) {
        try {
            if (socketWrapper == null) {
                return false;
            }
            SocketProcessorBase<S> sc = processorCache.pop();
            if (sc == null) {
                sc = createSocketProcessor(socketWrapper, event);
            } else {
                sc.reset(socketWrapper, event);
            }
            Executor executor = getExecutor();
            if (dispatch && executor != null) {
                executor.execute(sc);
            } else {
                sc.run();
            }
        } catch (RejectedExecutionException ree) {
            getLog().warn(sm.getString("endpoint.executor.fail", socketWrapper) , ree);
            return false;
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            // This means we got an OOM or similar creating a thread, or that
            // the pool and its queue are full
            getLog().error(sm.getString("endpoint.process.fail"), t);
            return false;
        }
        return true;
    }
 
 
    public Nio2SocketWrapper(Nio2Channel channel, final Nio2Endpoint endpoint) {
            super(channel, endpoint);
            socketBufferHandler = channel.getBufHandler();
 
            this.readCompletionHandler = new CompletionHandler<Integer, ByteBuffer>() {
                @Override
                public void completed(Integer nBytes, ByteBuffer attachment) {
                    if (log.isDebugEnabled()) {
                        log.debug("Socket: [" + Nio2SocketWrapper.this + "], Interest: [" + readInterest + "]");
                    }
                    // 将读通知置为false
                    readNotify = false;
                    synchronized (readCompletionHandler) {
                        // 判断是否有数据可读
                        if (nBytes.intValue() < 0) {
                            failed(new EOFException(), attachment);
                        } else {
                            if (readInterest && !Nio2Endpoint.isInline()) {// 如果注册了读信号,而且没有线程等待读,则直接启动读
                                readNotify = true;
                            } else {// 有线程等待读,则唤醒线程继续读
                                // Release here since there will be no
                                // notify/dispatch to do the release.
                                readPending.release();
                            }
                            readInterest = false;// 读信号置为false,从新等待注册读信号
                        }
                    }
                    if (readNotify) {// 直接启动读
                        getEndpoint().processSocket(Nio2SocketWrapper.this, SocketEvent.OPEN_READ, false);
                    }
                }
        }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!