zoukankan      html  css  js  c++  java
  • tomcatserver解析(六)-- Acceptor

    Acceptor负责用来管理连接到tomcatserver的数量,来看看Acceptor在tomcatserver中的应用,是怎样实现连接管理的,socket连接建立成功之后,是怎样实现内容的读写的(读写是交由Poller机制去完毕)。


    先准备一点java nio中实现socket连接所需的基础知识:SocketChannel和ServerSocketChannel

    SocketChannel和ServerSocketChannel的概念与基础的堵塞式的java 网络编程中的socket和serversocket类似。
    在后者的模型中,server端生成一个serversocket对象。bind绑定port号,然后accept堵塞等待client连接到server。每当连接建立成功,则返回一个Socket对象。用来表示连接建立成功。

    在java nio中。ServerSocketChannel和SocketChannel模型事实上是与ServerSocket和Socket模型相应的。server端open打开一个ServerSocketChannel。这个操作同一时候会成功一个ServerSocket对象,但生成的ServerSocket对象是没有进行port绑定的。所以在进行网络监听之前,还须要对ServerSocketChannel的ServerSocket对象进行bind绑定操作。

    然后ServerSocketChannel開始进行accept网络监听,请求建立成功之后返回一个SocketChannel对象。这个SocketChannel对象有一个与之相应的Socket对象。

    ServerSocketChannel是线程安全的 ---- at least the Oracle documentation says so.


    [ServerSocketChannel的初始化]
    一个port号仅仅能相应一个SocketChannel,因此也仅仅能相应一个ServerSocketChannel。因此这个ServerSocketChannel是在多个Acceptor线程之间共享的。它是NioEndpoint的一个属性,在NioEndpoint中进行初始化。
    在Endpoint模型中,有一个bind方法,用来绑定port。

    ServerSocketChannel对象在这种方法中完毕初始化。截取的部分代码例如以下所看到的,这里省略了与此主题无关的代码。

         public void bind() throws Exception {

            serverSock = ServerSocketChannel.open();
            socketProperties.setProperties(serverSock.socket());
            InetSocketAddress addr = (getAddress()!= null?

    new InetSocketAddress(getAddress(),getPort()):new InetSocketAddress(getPort()));

            serverSock.socket().bind(addr,getBacklog());
            serverSock.configureBlocking( true); //mimic APR behavior
            serverSock.socket().setSoTimeout(getSocketProperties().getSoTimeout());
         }
    [Acceptor线程组的初始化]

    Acceptor线程组中线程的个数是可配置的。这一点和Poller线程组中的线程个数一样,能够由配置文件来进行配置。仅仅是大部分情况下不须要罢了。


    Acceptor线程组的初始化在NioEndpoint的startInternal中进行,属于Endpoint初始化的一部分。


    [连接数控制]

    当一个新的连接请求到达时。怎样推断是否接收建立连接请求?

    Endpoint有个maxConnection属性,用来规定server所能接受的最大连接数。默认是10000。


    在NioEndpoint初始化的时候,会使用maxConnection来初始化一个LimitLatch,使用这个LimitLatc来进行并发请求连接的管理。

    对LimitLatch的理解能够參考java current包里面的CountDownLatch。


    Acceptor线程的执行主体部分,使用while(true)来进行循环。

    主要是进行serverSocket.accept的监听。对ServerSocketChannel使用blocking模式。所以当没有连接请求来时,线程会堵塞在accept方法上。


    当有新的请求到达时,使用countUpOrAwaitConnection来管理连接数。假设连接数还没有达到最大值。就将LimitLatch的值加1,LimitLatch的值就表示了当前与服务端建立连接的个数。

    假设已经达到了最大值,则让线程等待。


         与连接控制管理相关的代码例如以下所看到的。

                        //if we have reached max connections, wait
                        countUpOrAwaitConnection();

                        SocketChannel socket = null ;
                        try {
                            // Accept the next incoming connection from the server
                            // socket
                            socket = serverSock.accept();
                        } catch (IOException ioe) {
                            //we didn't get a socket
                            countDownConnection();
                            // Introduce delay if necessary
                            errorDelay = handleExceptionWithDelay(errorDelay);
                            // re-throw
                            throw ioe;
                        }
                        // Successful accept, reset the error delay
                        errorDelay = 0;

                        // setSocketOptions() will add channel to the poller
                        // if successful
                        if (running && !paused) {
                            if (!setSocketOptions(socket)) {
                                countDownConnection();
                                closeSocket(socket);
                            }
                        } else {
                            countDownConnection();
                            closeSocket(socket);
                        }
    当出现异常情况。就使用countDownConnection来将连接数减一。


    [连接的传递]

    管理连接的建立差点儿相同就是Acceptor的主要工作了,连接建立好之后。最后的工作就是交给Poller去实现数据的读写。在setSocketOptions中实现了SocketChannel对Poller的注冊。
  • 相关阅读:
    Educational Codeforces Round 10 C. Foe Pairs 水题
    Educational Codeforces Round 10 B. z-sort 构造
    CDOJ 1048 Bob's vector 三分
    Educational Codeforces Round 10 A. Gabriel and Caterpillar 模拟
    第14届电子科大初赛民间盗版部分题目题解
    HDU 5654 xiaoxin and his watermelon candy 离线树状数组 区间不同数的个数
    HDU 5653 Bomber Man wants to bomb an Array. dp
    HDU 5652 India and China Origins 二分+并查集
    HDU 5651 xiaoxin juju needs help 数学
    HDU 5650 so easy 数学
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5077953.html
Copyright © 2011-2022 走看看