IO出入口AbstractEndPoint源码分析

AbstractEndpoint这个类的目的就是作为处理Socket套接字IO的基础,从命名上来看其要意是处理TCP连接的两端的数据,这也是两台机器之间通信的端点。

AbstractEndpoint针对不同的IO模型有不同的实现:

AbstractEndpoint源码

public abstract class AbstractEndpoint<S> {
    // -------------------------------------------------------------- Constants
    protected static final StringManager sm = StringManager.getManager("org.apache.tomcat.util.net.res");

    public static interface Handler {
        // 定义的Socket状态
        public enum SocketState {
            OPEN, CLOSED, LONG, ASYNC_END, SENDFILE, UPGRADING_TOMCAT,
            UPGRADING, UPGRADED
        }
        // 全局请求处理器GlobalRequestProcessor
        public Object getGlobal();
        // 重复利用
        public void recycle();
    }
    // 
    protected enum BindState {
        UNBOUND, BOUND_ON_INIT, BOUND_ON_START
    }
    // Socket接收器,专门用来执行serverSocket.accept()方法
    public abstract static class Acceptor implements Runnable {
        public enum AcceptorState {
            NEW, RUNNING, PAUSED, ENDED
        }
        protected volatile AcceptorState state = AcceptorState.NEW;
        private String threadName;
    }
    private static final int INITIAL_ERROR_DELAY = 50;
    private static final int MAX_ERROR_DELAY = 1600;
    // ----------------------------------------------------------------- Fields
    /**
     * Running state of the endpoint.
     */
    protected volatile boolean running = false;
    protected volatile boolean paused = false;
    // 是否使用内部线程池
    protected volatile boolean internalExecutor = true;
    // 连接计数器
    private volatile LimitLatch connectionLimitLatch = null;

    /**
     * Socket properties
     */
    protected SocketProperties socketProperties = new SocketProperties();
    // 接收器数组(tomcat推荐不要超过两个,tomcat默认1个)
    protected Acceptor[] acceptors;
    // ----------------------------------------------------------------- Properties
    // 当endpoint stop时等待内部线程池执行的最大时间,默认5秒
    private long executorTerminationTimeoutMillis = 5000;
    // Acceptor[] acceptors接收器数组大小
    protected int acceptorThreadCount = 0;
    // 最大连接数
    private int maxConnections = 10000;
    // 内部处理socket的线程池
    private Executor executor = null;
    // tomcat监听的端口,ServerSocket port
    private int port;
    // 获取ServerSocket实际绑定的端口
    public abstract int getLocalPort();
    private InetAddress address;

    /**
     * Allows the server developer to specify the acceptCount (backlog) that
     * should be used for server sockets. By default, this value
     * is 100.
     */
    private int backlog = 100;

    // 是否在init生命周期方法中绑定ServerSocket
    private boolean bindOnInit = true;
    private BindState bindState = BindState.UNBOUND;
    // 阻塞时间
    private Integer keepAliveTimeout = null;
    // 内部线程池核心线程数
    private int minSpareThreads = 10;
    // 内部线程池最大线程数
    private int maxThreads = 200;
    // 每个长连接支持处理的最大http请求数量
    private int maxKeepAliveRequests=100; // as in Apache HTTPD server
    // 支持每个请求头最大个数,0表示不限制
    private int maxHeaderCount = 100; // as in Apache HTTPD server
    /**
     * Name of the thread pool, which will be used for naming child threads.
     */
    private String name = "TP";
    // 连接池的线程是否是守护线程
    private boolean daemon = true;


    public void setMaxConnections(int maxCon) {
        this.maxConnections = maxCon;
        LimitLatch latch = this.connectionLimitLatch;
        if (latch != null) {
            // Update the latch that enforces this
            if (maxCon == -1) {
                releaseConnectionLatch();
            } else {
                // 最大线程数
                latch.setLimit(maxCon);
            }
        } else if (maxCon > 0) {
            initializeConnectionLatch();
        }
    }

    public int getKeepAliveTimeout() {
        if (keepAliveTimeout == null) {
            return getSoTimeout();
        } else {
            return keepAliveTimeout.intValue();
        }
    }

    public void setMaxThreads(int maxThreads) {
        this.maxThreads = maxThreads;
        Executor executor = this.executor;
        if (internalExecutor && executor instanceof java.util.concurrent.ThreadPoolExecutor) {
            ((java.util.concurrent.ThreadPoolExecutor) executor).setMaximumPoolSize(maxThreads);
        }
    }

    protected abstract boolean getDeferAccept();
    // 属性保存集合
    protected HashMap<String, Object> attributes = new HashMap<String, Object>();
    public int getCurrentThreadCount() {
        Executor executor = this.executor;
        if (executor != null) {
            if (executor instanceof ThreadPoolExecutor) {
                return ((ThreadPoolExecutor) executor).getPoolSize();
            } else if (executor instanceof ResizableExecutor) {
                return ((ResizableExecutor) executor).getPoolSize();
            } else {
                return -1;
            }
        } else {
            return -2;
        }
    }
    // 获取当前繁忙的线程数
    public int getCurrentThreadsBusy() {
        Executor executor = this.executor;
        if (executor != null) {
            if (executor instanceof ThreadPoolExecutor) {
                return ((ThreadPoolExecutor) executor).getActiveCount();
            } else if (executor instanceof ResizableExecutor) {
                return ((ResizableExecutor) executor).getActiveCount();
            } else {
                return -1;
            }
        } else {
            return -2;
        }
    }
    // 初始化内部线程池
    public void createExecutor() {
        internalExecutor = true;
        // 使用的任务队列
        TaskQueue taskqueue = new TaskQueue();
        // daemon-是否是守护线程
        TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", daemon, getThreadPriority());
        executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf);
        taskqueue.setParent( (ThreadPoolExecutor) executor);
    }
    // 停止内部线程池
    public void shutdownExecutor() {
        Executor executor = this.executor;
        if (executor != null && internalExecutor) {
            this.executor = null;
            if (executor instanceof ThreadPoolExecutor) {
                //this is our internal one, so we need to shut it down
                ThreadPoolExecutor tpe = (ThreadPoolExecutor) executor;
                tpe.shutdownNow();
                long timeout = getExecutorTerminationTimeoutMillis();
                if (timeout > 0) {
                    try {
                        // 等待停止
                        tpe.awaitTermination(timeout, TimeUnit.MILLISECONDS);
                    } catch (InterruptedException e) {
                        // Ignore
                    }
                }
                TaskQueue queue = (TaskQueue) tpe.getQueue();
                queue.setParent(null);
            }
        }
    }

    /**
     * Unlock the server socket accept using a bogus connection.
     */
    // 唤醒等待在accept()方法上的线程
    protected void unlockAccept() {
        // Only try to unlock the acceptor if it is necessary
        boolean unlockRequired = false;
        for (Acceptor acceptor : acceptors) {
            if (acceptor.getState() == AcceptorState.RUNNING) {
                unlockRequired = true;
                break;
            }
        }
        if (!unlockRequired) {
            return;
        }

        java.net.Socket s = null;
        InetSocketAddress saddr = null;
        try {
            // Need to create a connection to unlock the accept();
            if (address == null) {
                saddr = new InetSocketAddress("localhost", getLocalPort());
            } else if (address.isAnyLocalAddress()) {
                saddr = new InetSocketAddress(getUnlockAddress(address), getLocalPort());
            } else {
                saddr = new InetSocketAddress(address, getLocalPort());
            }
            s = new java.net.Socket();
            int stmo = 2 * 1000;
            int utmo = 2 * 1000;
            if (getSocketProperties().getSoTimeout() > stmo) {
                stmo = getSocketProperties().getSoTimeout();
            }
            if (getSocketProperties().getUnlockTimeout() > utmo) {
                utmo = getSocketProperties().getUnlockTimeout();
            }
            s.setSoTimeout(stmo);
            // TODO Consider hard-coding to s.setSoLinger(true,0)
            s.setSoLinger(getSocketProperties().getSoLingerOn(),getSocketProperties().getSoLingerTime());
            s.connect(saddr,utmo);
            if (getDeferAccept()) {
                /*
                 * In the case of a deferred accept / accept filters we need to
                 * send data to wake up the accept. Send OPTIONS * to bypass
                 * even BSD accept filters. The Acceptor will discard it.
                 */
                OutputStreamWriter sw;

                sw = new OutputStreamWriter(s.getOutputStream(), "ISO-8859-1");
                sw.write("OPTIONS * HTTP/1.0\r\n" +
                         "User-Agent: Tomcat wakeup connection\r\n\r\n");
                sw.flush();
            }
            // Wait for upto 1000ms acceptor threads to unlock
            long waitLeft = 1000;
            for (Acceptor acceptor : acceptors) {
                while (waitLeft > 0 &&
                       acceptor.getState() == AcceptorState.RUNNING) {
                    Thread.sleep(5);
                    waitLeft -= 5;
                }
            }
        } catch(Exception e) {
        } finally {
            if (s != null) {
                try {
                    s.close();
                } catch (Exception e) {
                    // Ignore
                }
            }
        }
    }

    // ---------------------------------------------- Request processing methods

    public abstract void processSocketAsync(SocketWrapper<S> socketWrapper,
                                            SocketStatus socketStatus);

    public abstract void removeWaitingRequest(SocketWrapper<S> socketWrapper);


    // ------------------------------------------------------- Lifecycle methods
    public abstract void bind() throws Exception;
    public abstract void unbind() throws Exception;
    public abstract void startInternal() throws Exception;
    public abstract void stopInternal() throws Exception;

    public final void init() throws Exception {
        testServerCipherSuitesOrderSupport();
        if (bindOnInit) {
            bind();
            bindState = BindState.BOUND_ON_INIT;
        }
    }

    private void testServerCipherSuitesOrderSupport() {
        // Only test this feature if the user explicitly requested its use.
        if(!"".equals(getUseServerCipherSuitesOrder().trim())) {
            if (!JreCompat.isJre8Available()) {
                throw new UnsupportedOperationException(
                    sm.getString("endpoint.jsse.cannotHonorServerCipherOrder"));
            }
        }
    }

    public final void start() throws Exception {
        if (bindState == BindState.UNBOUND) {
            bind();
            bindState = BindState.BOUND_ON_START;
        }
        startInternal();
    }

    // 开启处理accept()方法的线程,默认一个
    protected final void startAcceptorThreads() {
        
        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();
        }
    }
    // 实现类提供具体的接收器
    protected abstract Acceptor createAcceptor();

    public void pause() {
        if (running && !paused) {
            paused = true;
            unlockAccept();
        }
    }
    public void resume() {
        if (running) {
            paused = false;
        }
    }

    public final void stop() throws Exception {
        stopInternal();
        if (bindState == BindState.BOUND_ON_START) {
            unbind();
            bindState = BindState.UNBOUND;
        }
    }

    public final void destroy() throws Exception {
        if (bindState == BindState.BOUND_ON_INIT) {
            unbind();
            bindState = BindState.UNBOUND;
        }
    }

    protected abstract Log getLog();
    // Flags to indicate optional feature support
    // Some of these are always hard-coded, some are hard-coded to false (i.e.
    // the endpoint does not support them) and some are configurable.
    // 一些标记特性
    public abstract boolean getUseSendfile();
    public abstract boolean getUseComet();
    public abstract boolean getUseCometTimeout();
    public abstract boolean getUsePolling();

    // 连接数据控制方法---LimitLatch是通过同步器AQS实现------------------------------------------------------------------
    protected LimitLatch initializeConnectionLatch() {
        if (maxConnections==-1) {
            return null;
        }
        if (connectionLimitLatch==null) {
            // 初始化最大连接限制
            connectionLimitLatch = new LimitLatch(getMaxConnections());
        }
        return connectionLimitLatch;
    }
    // 连接数据增加
    protected void countUpOrAwaitConnection() throws InterruptedException {
        if (maxConnections==-1) {
            return;
        }
        LimitLatch latch = connectionLimitLatch;
        if (latch!=null) {
            latch.countUpOrAwait();
        }
    }
    // 连接数量减少
    protected long countDownConnection() {
        if (maxConnections==-1) {
            return -1;
        }
        LimitLatch latch = connectionLimitLatch;
        if (latch!=null) {
            long result = latch.countDown();
            return result;
        } else {
            return -1;
        }
    }
}

从其源码中不难看出,AbstractEndpoint主要定义了各种IO模型下的公共属性及行为

  1. ServerSocket的相关属性(绑定端口,ip等)
  2. 处理accept()方法的接收线程数量
  3. 内部定义了处理socket的线程池,及该线程池相关属性(线程数,是否是守护线程)等等
  4. 定义了生命周期方法init(),start()等,具体的实现initInternal()startInternal()方法交给具体子类实现
  5. 定义了Acceptor抽象接收器,交由子类实现具体的Acceptor定义如何接收新来的socket连接

JioEndPoint实现

JioEndPoint是AbstractEndpoint对于传统同步阻塞IO(BIO)的具体实现,

从JioEndPoint的类结构上看其主要实现了AbstractEndPoint的相关抽象方法,ServerSocket就是套接字服务端,同时其实现定义了具体的接收器Acceptor,以及如何处理接收的socket的SocketProcessor处理器。

来看看JioEndPoint本身几个重要的方法

public class JIoEndpoint extends AbstractEndpoint<Socket> {

    protected ServerSocket serverSocket = null;
    // ------------------------------------------------------------- Properties
    protected Handler handler = null;
    public void setHandler(Handler handler ) { this.handler = handler; }
    public Handler getHandler() { return handler; }

    protected ServerSocketFactory serverSocketFactory = null;
    protected ConcurrentLinkedQueue<SocketWrapper<Socket>> waitingRequests = new ConcurrentLinkedQueue<SocketWrapper<Socket>>();
    @Override
    public int getLocalPort() {
        ServerSocket s = serverSocket;
        if (s == null) {
            return -1;
        } else {
            return s.getLocalPort();
        }
    }

    @Override
    public boolean getUseSendfile() { return false; } // Not supported
    @Override
    public boolean getUseComet() { return false; } // Not supported
    @Override
    public boolean getUseCometTimeout() { return false; } // Not supported
    @Override
    public boolean getDeferAccept() { return false; } // Not supported
    @Override
    public boolean getUsePolling() { return false; } // Not supported


    // ------------------------------------------------ Handler Inner Interface
    public interface Handler extends AbstractEndpoint.Handler {
        public SocketState process(SocketWrapper<Socket> socket,
                                   SocketStatus status);
        public SSLImplementation getSslImplementation();
        public boolean isAvailable(SocketWrapper<Socket> socket);
    }
    // -------------------- Public methods --------------------
    // 绑定端口,开始监听连接
    @Override
    public void bind() throws Exception {

        // Initialize thread count defaults for acceptor
        if (acceptorThreadCount == 0) {
            acceptorThreadCount = 1;
        }
        if (serverSocketFactory == null) {
            if (isSSLEnabled()) {
                serverSocketFactory = handler.getSslImplementation().getServerSocketFactory(this);
            } else {
                serverSocketFactory = new DefaultServerSocketFactory(this);
            }
        }

        if (serverSocket == null) {
            try {
                if (getAddress() == null) {
                    serverSocket = serverSocketFactory.createSocket(getPort(), getBacklog());
                } else {
                    // 创建ServerSocket开始监听
                    serverSocket = serverSocketFactory.createSocket(getPort(), getBacklog(), getAddress());
                }
            } catch (BindException orig) {
                // ....
                throw be;
            }
        }
    }
    @Override
    public void startInternal() throws Exception {

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

            // Create worker collection
            if (getExecutor() == null) {
                createExecutor();
            }

            initializeConnectionLatch();
            // 开启处理accept()接收器方法
            startAcceptorThreads();

            // Start async timeout thread
            Thread timeoutThread = new Thread(new AsyncTimeout(), getName() + "-AsyncTimeout");
            timeoutThread.setPriority(threadPriority);
            timeoutThread.setDaemon(true);
            timeoutThread.start();
        }
    }

    @Override
    protected AbstractEndpoint.Acceptor createAcceptor() {
        return new Acceptor();
    }

    // 定义如何处理接收到的socket
    protected boolean processSocket(Socket socket) {
        // Process the request from this socket
        try {
            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;
            }
            // 包装之后交给线程池处理
            getExecutor().execute(new SocketProcessor(wrapper));
        } catch (RejectedExecutionException x) {
            return false;
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            return false;
        }
        return true;
    }
}

BIO接收器Acceptor实现

protected class Acceptor extends AbstractEndpoint.Acceptor {

    @Override
    public void run() {

        int errorDelay = 0;

        // 循环处理
        while (running) {

            // Loop if endpoint is paused
            while (paused && running) {
                state = AcceptorState.PAUSED;
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    // Ignore
                }
            }

            if (!running) {
                break;// 非运行态,退出
            }
            
            state = AcceptorState.RUNNING;

            try {
                //if we have reached max connections, wait 检查是否达到最大连接
                countUpOrAwaitConnection();

                Socket socket = null;
                try {
                    // Accept the next incoming connection from the server
                    // 接收新的socket
                    socket = serverSocketFactory.acceptSocket(serverSocket);
                } catch (IOException ioe) {
                    countDownConnection();
                    // Introduce delay if necessary
                    errorDelay = handleExceptionWithDelay(errorDelay);
                    // re-throw
                    throw ioe;
                }
                // Successful accept, reset the error delay
                errorDelay = 0;

                // Configure the socket
                if (running && !paused && setSocketOptions(socket)) {
                    // 处理socket套接字
                    if (!processSocket(socket)) {
                        countDownConnection();
                        // Close socket right away
                        closeSocket(socket);
                    }
                } else {
                    countDownConnection();
                    // Close socket right away
                    closeSocket(socket);
                }
            } catch (Throwable t) {
                ExceptionUtils.handleThrowable(t);
                log.error(sm.getString("endpoint.accept.fail"), t);
            }
        }
        state = AcceptorState.ENDED;
    }
}

Acceptor主要就是根据容器的运行状态,及连接数量合适的处理ServerSocket#accept()方法,将接收到的socket交个线程池处理。

而线程池线程如何处理Socket则是由SocketProcessor定义的

SocketProcessor如何处理socket

protected class SocketProcessor implements Runnable {

    protected SocketWrapper<Socket> socket = null;
    protected SocketStatus status = null;
    public SocketProcessor(SocketWrapper<Socket> socket, SocketStatus status) {
        this(socket);
        this.status = status;
    }
    @Override
    public void run() {
        boolean launch = false;
        synchronized (socket) {
            try {
                SocketState state = SocketState.OPEN;
				// ... 省略部分ssl相关代码....
                // 将socket交个具体的处理器处理
                if ((state != SocketState.CLOSED)) {
                    if (status == null) {
                        state = handler.process(socket, SocketStatus.OPEN_READ);
                    } else {
                        state = handler.process(socket,status);
                    }
                }
                
                // 其他情况
                if (state == SocketState.CLOSED) {
                    countDownConnection();
                    try {
                        socket.getSocket().close();
                    } catch (IOException e) {
                        // Ignore
                    }
                } else if (state == SocketState.OPEN ||
                           state == SocketState.UPGRADING ||
                           state == SocketState.UPGRADING_TOMCAT  ||
                           state == SocketState.UPGRADED){
                    // 长连接
                    socket.setKeptAlive(true);
                    socket.access();
                    launch = true;
                } else if (state == SocketState.LONG) {
                    socket.access();
                    waitingRequests.add(socket);
                }
            } finally {
                if (launch) {
                    try {
                        getExecutor().execute(new SocketProcessor(socket, SocketStatus.OPEN_READ));
                    } catch (RejectedExecutionException x) {
                        try {
                            //unable to handle connection at this time
                            handler.process(socket, SocketStatus.DISCONNECT);
                        } finally {
                            countDownConnection();
                        }
                    }
                }
            }
        }
        socket = null;
        // Finish up this request
    }
}

JioEndPoint.Handler

具体的Handler定义是JioEndPoint内部定义的接口

public interface Handler extends AbstractEndpoint.Handler {
    public SocketState process(SocketWrapper<Socket> socket,  SocketStatus status);
    public SSLImplementation getSslImplementation();
    public boolean isAvailable(SocketWrapper<Socket> socket);
}

继承至AbstractEndpoint.Handler这个标记接口,其实现根据不同的协议有不同的实现,专门处理BIO的不同协议

到此tomcat EndPoint的脉络大致清晰了,首先是根据不同的IO模型有具体的Endpoint实现,针对某个的IO模型又有不同的协议实现如何处理接收到的套接字处理器XXX Protocol Handler

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值