tomcat 8.x NioEndpoint核心组件浅析1

1. Nio初始化阶段

  • 1.1 NioEndpoint 实现了建立连接、处理连接、和关闭连接等操作,在看NioEndpoint之前先看一下下面的uml图

    image.png

    以上图把整个NioEndpoint的核心关系展示出来了,我们在看下图tomcat中 nio的网络模型借用了网上的图片
    image.png

  • 1.2 acceptor 顾名思义用来处理链接 我们来看一下他在NioEndpoint中的实现

 /**
     * Start the NIO endpoint, creating acceptor, poller threads.
     */
    @Override
    public void startInternal() throws Exception {

        if (!running) {
            running = true;
            paused = false;

            processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
                    socketProperties.getProcessorCache());
            eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
                            socketProperties.getEventCache());
            //申请nioChannel 默认128个 为什么有这个东西 
            //其实这个东西就是申请了系统内存io读写直接使用系统内存的效率比堆内存好快很多
            //当然申请系统内存会有很大的开销,所以直接初始一些出来,这样要用的时候直接可以使用、当socket关闭的时候、nioChannel并不会被销毁、而是重新放入这个队列中、重复被使用
            //总之可以理解内核复用技术、类似netty的内核复用技术
            nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
                    socketProperties.getBufferPool());

            if ( getExecutor() == null ) {
              //构建线程池对应上图的executor 它是用来处理SocketProcessor
              //换句话主要是用来对socket进行读写封装成request对象然后做业务处理
              //我们常常用的controller也是使用这个线程来执行的 
                createExecutor();
            }

            initializeConnectionLatch();

            // Start poller threads
            // 初始化poller默认是两个poller
            // poller主要循环扫描PollerEvent队列是否存在待处理请求
            // 如果存在PollerEvent待处理,进行请求解析封装
            // 启动Executor线程进行请求读处理
            pollers = new Poller[getPollerThreadCount()];
            for (int i=0; i<pollers.length; i++) {
                pollers[i] = new Poller();
                Thread pollerThread = new Thread(pollers[i], getName() + "-ClientPoller-"+i);
                pollerThread.setPriority(threadPriority);
                pollerThread.setDaemon(true);
                pollerThread.start();
            }
            //启动Acceptor 默认使用一单线程处理连接
            startAcceptorThreads();
        }
    }

来看一下startAcceptorThreads的源码

protected final void startAcceptorThreads() {
       //acceptor连接池个数 默认为一个
       int count = getAcceptorThreadCount();
       acceptors = new Acceptor[count];

       for (int i = 0; i < count; i++) {
           acceptors[i] = createAcceptor();
           String threadName = getName() + "-Acceptor-" + i;
           acceptors[i].setThreadName(threadName);
           Thread t = new Thread(acceptors[i], threadName);
           t.setPriority(getAcceptorThreadPriority());
           t.setDaemon(getDaemon());
           t.start();
       }
   }

以上就是Accetor、poller、Executor等核心组件初始化的过程

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,841评论 18 139
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,341评论 11 349
  • 概述 Tomcat是一个JSP/Servlet容器。其作为Servlet容器,有三种工作模式:独立的Servlet...
    jiangmo阅读 2,247评论 0 13
  • 如果我还会远行 我会带上我的母亲 避风来、避雨淋、避开时光的约定 看清晨太阳 喝午后清茶 守望夜晚的月亮,星星 我...
    燕返楼兰阅读 221评论 0 2