(三)Tomcat架构及运行原理之Connector源码分析

目录

1.Connector部分源码流程

1.1 Connector

1.2 ProtocolHandler系列

1.2.1 ProtocolHandler

1.2.2 Http11NioProtocol

1.2.3 AbstractHttp11Protocol

1.2.4 AbstractProtocol

1.3 Endpoint

1.3.1 AbstractEndpoint

1.3.2 NioEndpoint

1.4 Acceptor

1.5 ServerSocketChannelImpl

1.6 SocketProcessorBase

1.7 ConnectionHandler

阅读本篇请先看(一)Tomcat架构及运行原理之基本架构文章。

1.Connector部分源码流程

1.1 Connector

从上一篇笔记我们已经知道了在service的init方法和start方法会分别调用Connector的init和start方法,因此我们看这个类时只需要关注init和start即可。其部分关键源码如下:

public class Connector extends LifecycleMBeanBase  {
    public Connector() {
        this("org.apache.coyote.http11.Http11NioProtocol");
    }
    public Connector(String protocol) {
        boolean aprConnector = AprLifecycleListener.isAprAvailable() &&
                AprLifecycleListener.getUseAprConnector();
        // 根据传进来的协议判断,但在这里是直接确定处理类的
        if ("HTTP/1.1".equals(protocol) || protocol == null) {
            ...
        } else {
            protocolHandlerClassName = protocol;
        }
        ProtocolHandler p = null;
        try {
            // 实例化协议处理类,实际上是Http11NioProtocol
            Class<?> clazz = Class.forName(protocolHandlerClassName);
            p = (ProtocolHandler) clazz.getConstructor().newInstance();
        } catch (Exception e) {
            ...
        } finally {
            this.protocolHandler = p;
        }
        ...
    }
    protected Service service = null;
    protected String scheme = "http";
    // 协议处理类,这个类及其抽象父类都很重要
    protected final ProtocolHandler protocolHandler;
    // 实际上类型是CoyoteAdapter
    protected Adapter adapter = null;
    @Override
    protected void initInternal() throws LifecycleException {
        super.initInternal();
        // 跑到这里protocolHandler一定是不为空的对象,毕竟构造函数都那样玩了
        if (protocolHandler == null) {
            throw new LifecycleException(
                    sm.getString("..."));
        }
        // 直接实例化CoyoteAdapter类型给Adapter
        adapter = new CoyoteAdapter(this);
        // adapter和protocolHandler关联
        protocolHandler.setAdapter(adapter);
        if (service != null) {
            // 前面获取的线程池在这里派上了用场
            protocolHandler.setUtilityExecutor(service.getServer()
                    .getUtilityExecutor());
        }
        // 设置默认的body解析方式(这里设置的是POST)
        if (null == parseBodyMethodsSet) {
            setParseBodyMethods(getParseBodyMethods());
        }
        if (protocolHandler.isAprRequired() && 
                !AprLifecycleListener.isInstanceCreated()) {
            throw new LifecycleException(sm.getString("...",
                    getProtocolHandlerClassName()));
        }
        if (protocolHandler.isAprRequired() && 
                !AprLifecycleListener.isAprAvailable()) {
            throw new LifecycleException(sm.getString("...",
                    getProtocolHandlerClassName()));
        }
        // 中间略过
        ...
        try {
            // 经典的initInternal再调用init方法,这个流程后面再分析
            protocolHandler.init();
        } catch (Exception e) {
            throw new LifecycleException(
                    sm.getString("..."), e);
        }
    }
    @Override
    protected void startInternal() throws LifecycleException {
        if (getPortWithOffset() < 0) {
            throw new LifecycleException(sm.getString(
                    "...", Integer.valueOf(getPortWithOffset())));
        }
        setState(LifecycleState.STARTING);
        try {
            // 经典的startInternal再调用start方法
            protocolHandler.start();
        } catch (Exception e) {
            throw new LifecycleException(
                    sm.getString("..."), e);
        }
    }
}

从这里可以明显的感觉到Connector主要通信对象就是protocolHandler,完成了架构图中的第一步:Connector和protocolHandler的关系。

1.2 ProtocolHandler系列

1.2.1 ProtocolHandler

上面说了ProtocolHandler的具体类型是Http11NioProtocol。因此我们看到这个类的关键源码:

public interface ProtocolHandler {
    public Adapter getAdapter();
    public void setAdapter(Adapter adapter);
    public Executor getExecutor();
    public void setExecutor(Executor executor);
    public ScheduledExecutorService getUtilityExecutor();
    public void setUtilityExecutor(
            ScheduledExecutorService utilityExecutor);
    public void init() throws Exception;
    public void start() throws Exception;
    public void pause() throws Exception;
    public void resume() throws Exception;
    public void stop() throws Exception;
    public void destroy() throws Exception;
    public void addUpgradeProtocol(UpgradeProtocol upgradeProtocol);
    public UpgradeProtocol[] findUpgradeProtocols();
}

1.2.2 Http11NioProtocol

具体实现类关键源码:

public class Http11NioProtocol 
        extends AbstractHttp11JsseProtocol<NioChannel> {
    public Http11NioProtocol() {
        super(new NioEndpoint());
    }
    @Override
    protected String getNamePrefix() {
        if (isSSLEnabled()) {
            return "https-" + getSslImplementationShortName()+ "-nio";
        } else {
            return "http-nio";
        }
    }
}

没错,这个实现类只有这个构造函数以及getNamePrefix方法返回的内容我们真正会用到,而其它的方法都是调用父类的endpoint来进行操作,等下再详细分析。

1.2.3 AbstractHttp11Protocol

其关键源码如下:

public abstract class AbstractHttp11Protocol<S> 
        extends AbstractProtocol<S> {
    public AbstractHttp11Protocol(AbstractEndpoint<S,?> endpoint) {
        // 继续调用父类方法
        super(endpoint);
        setConnectionTimeout(Constants.DEFAULT_CONNECTION_TIMEOUT);
        // 设置handler,这个在后续处理具体的socket时会用到,需要特别留意
        ConnectionHandler<S> cHandler = new ConnectionHandler<>(this);
        setHandler(cHandler);
        getEndpoint().setHandler(cHandler);
    }
    @Override
    public void init() throws Exception {
        // 初始化时对upgradeProtocol进行配置
        for (UpgradeProtocol upgradeProtocol : upgradeProtocols) {
            configureUpgradeProtocol(upgradeProtocol);
        }
        super.init();
    }
    private void configureUpgradeProtocol(
            UpgradeProtocol upgradeProtocol) {
        // HTTP Upgrade,将http类型的添加缓存
        String httpUpgradeName = upgradeProtocol
                .getHttpUpgradeName(getEndpoint().isSSLEnabled());
        boolean httpUpgradeConfigured = false;
        if (httpUpgradeName != null && httpUpgradeName.length() > 0) {
            httpUpgradeProtocols.put(httpUpgradeName, upgradeProtocol);
            httpUpgradeConfigured = true;
            getLog().info(sm.getString("...",
                    getName(), httpUpgradeName));
        }
    }
    @Override
    protected Processor createProcessor() {
        // 将会在handler中被调用,用来返回具体的processor处理类
        Http11Processor processor = new Http11Processor(this, adapter);
        return processor;
    }
}

1.2.4 AbstractProtocol

前面实现的功能有限,都是正对某个具体类型的实现类,但是AbstractProtocol则是全部适用的,因此也注定这个类的逻辑相较于其它的会比较复杂。其关键部分源码如下:

public abstract class AbstractProtocol<S> implements ProtocolHandler,
        MBeanRegistration {
    // 终于架构图中的endPoint、handler、processor和adapter都出现了
    // acceptor接着往下分析
    private final AbstractEndpoint<S,?> endpoint;
    protected Adapter adapter;
    private Handler<S> handler;
    private final Set<Processor> waitingProcessors = 
            Collections.newSetFromMap(
                    new ConcurrentHashMap<Processor, Boolean>());
    public AbstractProtocol(AbstractEndpoint<S,?> endpoint) {
        this.endpoint = endpoint;
        setConnectionLinger(Constants.DEFAULT_CONNECTION_LINGER);
        setTcpNoDelay(Constants.DEFAULT_TCP_NO_DELAY);
    }
    @Override
    public void init() throws Exception {
        ...
        // 忽略前面无关紧要的代码,init方法就这么简洁
        // 直接调用了endpoint的init方法
        String endpointName = getName();
        endpoint.setName(endpointName.substring(1, 
                endpointName.length()-1));
        endpoint.setDomain(domain);
        endpoint.init();
    }
    @Override
    public void start() throws Exception {
        ...
        // 忽略了前面无关紧要的代码,这里还是那么简洁。。
        endpoint.start();
        monitorFuture = getUtilityExecutor().scheduleWithFixedDelay(
                new Runnable() {
                    @Override
                    public void run() {
                        if (!isPaused()) {
                            startAsyncTimeout();
                        }
                    }
                }, 0, 60, TimeUnit.SECONDS);
    }
}

1.3 Endpoint

前面出现过这么多次也终于轮到Endpoint出场了,这个类已经和ProtocolHandler的具体实现类绑定了,如Http11NioProtocol使用的类型就是写死的NioEndpoint类型。

1.3.1 AbstractEndpoint

分析具体实现类时先关注一下其父类做了什么。关键源码如下:

public abstract class AbstractEndpoint<S,U> {
    public static interface Handler<S> {
        public enum SocketState {
            OPEN, CLOSED, LONG, ASYNC_END, SENDFILE, UPGRADING, 
                    UPGRADED, SUSPENDED
        }
        public SocketState process(SocketWrapperBase<S> socket,
                SocketEvent status);
        // 其它方法忽略
    }
    protected enum BindState {
        UNBOUND, BOUND_ON_INIT, BOUND_ON_START, SOCKET_CLOSED_ON_STOP
    }
    // 盼来盼去终于盼到你了,现在Connector中的几个关键角色已经全部就位
    protected Acceptor<U> acceptor;
    protected SynchronizedStack<SocketProcessorBase<S>> processorCache;
    private Executor executor = null;
    private ScheduledExecutorService utilityExecutor = null;
    private Handler<S> handler = null;
    public final void init() throws Exception {
        if (bindOnInit) {
            bindWithCleanup();
            bindState = BindState.BOUND_ON_INIT;
        }
        // 后面的可以忽略
        ...
    }
    private void bindWithCleanup() throws Exception {
        try {
            bind();
        } catch (Throwable t) {
            unbind();
            throw t;
        }
    }
    public final void start() throws Exception {
        if (bindState == BindState.UNBOUND) {
            bindWithCleanup();
            bindState = BindState.BOUND_ON_START;
        }
        startInternal();
    }
    public abstract void bind() throws Exception;
    public abstract void unbind() throws Exception;
    public abstract void startInternal() throws Exception;
    public abstract void stopInternal() throws Exception;
    protected abstract SocketProcessorBase<S> createSocketProcessor(
            SocketWrapperBase<S> socketWrapper, SocketEvent event);
    public boolean processSocket(SocketWrapperBase<S> socketWrapper,
            SocketEvent event, boolean dispatch) {
        // 这个方法将会被子类NioEndpoint的Poller轮询器轮询到事件时调用
        try {
            if (socketWrapper == null) {
                return false;
            }
            SocketProcessorBase<S> sc = null;
            if (processorCache != null) {
                // 从缓存中去除
                sc = processorCache.pop();
            }
            if (sc == null) {
                // 如果sc为空则调用子类实现方法创建一个processor
                sc = createSocketProcessor(socketWrapper, event);
            } else {
                sc.reset(socketWrapper, event);
            }
            // 获取线程池不为空且dispatch为true,则使用线程池去调用
            Executor executor = getExecutor();
            if (dispatch && executor != null) {
                // 使用线程池启动线程,一般而言正常的请求都会使用线程池启动
                // 这个线程池类型是Tomcat自己实现的ThreadPoolExecutor
                executor.execute(sc);
            } else {
                // 否则直接启动线程
                sc.run();
            }
        } catch (RejectedExecutionException ree) {
            return false;
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            return false;
        }
        return true;
    }
    public void createExecutor() {
        // 在NioEndpoint的startInternal方法中间将会被调用
        // 用来初始化executor线程池对象,虽然都是Tomcat自己封装实现的
        // 但逻辑都和Java官方差不多
        internalExecutor = true;
        // Tomcat实现的阻塞队列
        TaskQueue taskqueue = new TaskQueue();
        // Tomcat实现的线程工厂
        TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-",
                daemon, getThreadPriority());
        // Tomcat实现的线程池类型,从传入的参数也可以看出来Tomcat的线程数量配置
        // 需要注意的是getMaxThreads()方法的返回值,默认为10,但是最大是不能
        // 超过Tomcat的最大线程数量maxThreads,当超过时将会使用maxThreads的值
        executor = new ThreadPoolExecutor(getMinSpareThreads(), 
                getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf);
        taskqueue.setParent( (ThreadPoolExecutor) executor);
    }
    protected void startAcceptorThread() {
        // 该方法将会在NioEndpoint的startInternal方法末尾调用
        acceptor = new Acceptor<>(this);
        String threadName = getName() + "-Acceptor";
        acceptor.setThreadName(threadName);
        // 将acceptor用线程封装,异步调用acceptor的run方法,这里面的run方法
        // 很关键,是用户请求到Tomcat接受的第一步,在这里面将会成为所有请求
        // 的起点站,具体的流程后面分析
        Thread t = new Thread(acceptor, threadName);
        t.setPriority(getAcceptorThreadPriority());
        t.setDaemon(getDaemon());
        t.start();
    }
}

看完这些关键方法源码后只能说简洁,抽象父类只提供各个方法的调用顺序和一些必要的操作,其它的都交给子类实现,模板模式的经典运用。

1.3.2 NioEndpoint

其父类AbstractJsseEndpoint实际上就对SSL做了一些额外的处理,在启动流程这都是无关紧要的,因此忽略。NioEndpoint的关键部分源码如下,其源码可能比较长,因为很多操作都是在这个类中完成的(大部分是在内部类中):

public class NioEndpoint 
        extends AbstractJsseEndpoint<NioChannel,SocketChannel> {
    private NioSelectorPool selectorPool = new NioSelectorPool();
    private volatile ServerSocketChannel serverSock = null;
    private volatile CountDownLatch stopLatch = null;
    private SynchronizedStack<PollerEvent> eventCache;
    private SynchronizedStack<NioChannel> nioChannels;
    private Poller poller = null;
    @Override
    public void bind() throws Exception {
        // 父类的init方法将会调用该方法
        // 这个方法没什么看的,只是对serverSock和socket进行初始化绑定
        initServerSocket();
        setStopLatch(new CountDownLatch(1));
        // 调用父类初始化SSL
        initialiseSsl();
        // 初始化selector
        selectorPool.open(getName());
    }
    @Override
    public void startInternal() throws Exception {
        // 父类的start方法将会调用进来
        // 判断如果当前的endpoint没有在运行,则进入
        if (!running) {
            // 设置为运行状态
            running = true;
            paused = false;
            // 下面几个if可以忽略
            if (socketProperties.getProcessorCache() != 0) {
                processorCache = new SynchronizedStack<>(
                        SynchronizedStack.DEFAULT_SIZE,
                        socketProperties.getProcessorCache());
            }
            if (socketProperties.getEventCache() != 0) {
                eventCache = new SynchronizedStack<>(
                        SynchronizedStack.DEFAULT_SIZE,
                        socketProperties.getEventCache());
            }
            if (socketProperties.getBufferPool() != 0) {
                nioChannels = new SynchronizedStack<>(
                        SynchronizedStack.DEFAULT_SIZE,
                        socketProperties.getBufferPool());
            }
            // 调用父类的方法创建executor
            if (getExecutor() == null) {
                createExecutor();
            }
            initializeConnectionLatch();
            // 从名字也可以看出来这个对象的大致作用:轮询器,即一直轮询
            // 是否有PollerEvent事件,如果有则对时间进行处理
            poller = new Poller();
            Thread pollerThread = new Thread(poller, getName() + 
                    "-ClientPoller");
            pollerThread.setPriority(threadPriority);
            pollerThread.setDaemon(true);
            pollerThread.start();
            // 调用父类的方法启动Acceptor线程,进行请求轮询
            startAcceptorThread();
        }
    }
    @Override
    protected SocketChannel serverSocketAccept() throws Exception {
        // 调用已经绑定过地址的serverSock去获取Socket
        // 如果获取到则返回,没有获取到则轮询获取
        return serverSock.accept();
    }
    @Override
    protected boolean setSocketOptions(SocketChannel socket) {
        // 这个方法将会在Acceptor轮询到有socket请求被调用
        // 具体的调用位置将在分析Acceptor时说明
        try {
            // 这中间是对SSL协议安全性进行判断,从而确定具体使用哪个channel类型
            // 无关紧要,因此略过
            ...
            // 这个对象如果debug过Tomcat请求流程就知道,Tomcat线程池执行的
            // socket对象便是这个类型,是在放进poller轮询器前封装的socket
            NioSocketWrapper socketWrapper = new NioSocketWrapper(channel, 
                    this);
            channel.setSocketWrapper(socketWrapper);
            socketWrapper.setReadTimeout(getConnectionTimeout());
            socketWrapper.setWriteTimeout(getConnectionTimeout());
            socketWrapper.setKeepAliveLeft(NioEndpoint.this
                    .getMaxKeepAliveRequests());
            socketWrapper.setSecure(isSSLEnabled());
            // 注册进轮询器,在这里面将会被转换成PollerEvent事件,并放进阻塞
            // 队列中,随后将被轮询器读取并执行
            poller.register(channel, socketWrapper);
            return true;
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            try {
                log.error(sm.getString("endpoint.socketOptionsError"), t);
            } catch (Throwable tt) {
                ExceptionUtils.handleThrowable(tt);
            }
        }
        return false;
    }
    @Override
    protected SocketProcessorBase<NioChannel> createSocketProcessor(
            SocketWrapperBase<NioChannel> socketWrapper, 
            SocketEvent event) {
        // 这个方法在AbstractEndpoint父类中被调用以获得processor实例
        return new SocketProcessor(socketWrapper, event);
    }
    public class Poller implements Runnable {
        private Selector selector;
        private final SynchronizedQueue<PollerEvent> events =
                new SynchronizedQueue<>();
        public void register(final NioChannel socket, 
                final NioSocketWrapper socketWrapper) {
            // 在setSocketOptions方法中将会调用进来
            socketWrapper.interestOps(SelectionKey.OP_READ);
            PollerEvent r = null;
            if (eventCache != null) {
                r = eventCache.pop();
            }
            // 使用PollerEvent事件封装socket
            if (r == null) {
                r = new PollerEvent(socket, OP_REGISTER);
            } else {
                r.reset(socket, OP_REGISTER);
            }
            // 添加进事件阻塞队列
            addEvent(r);
        }
        private void addEvent(PollerEvent event) {
            // 添加进阻塞队列
            events.offer(event);
            if (wakeupCounter.incrementAndGet() == 0) {
                selector.wakeup();
            }
        }
        @Override
        public void run() {
            // 在startInternal方法中将会启动poller线程
            // 在run方法中如果poller没有被关闭,那么这个循环将会一直执行下去
            while (true) {
                boolean hasEvents = false;
                try {
                    if (!close) {
                        // 如果没有关闭,则获取event事件
                        hasEvents = events();
                        if (wakeupCounter.getAndSet(-1) > 0) {
                            keyCount = selector.selectNow();
                        } else {
                            keyCount = selector.select(selectorTimeout);
                        }
                        wakeupCounter.set(0);
                    }
                    if (close) {
                        // 如果关闭了则最后获取一次事件,以防止还有事件没有读取
                        events();
                        timeout(0, false);
                        try {
                            // 关闭selector
                            selector.close();
                        } catch (IOException ioe) {
                            ...
                        }
                        break;
                    }
                } catch (Throwable x) {
                    ...
                    continue;
                }
                // 如果当前事件数量为0,则获取
                if (keyCount == 0) {
                    hasEvents = (hasEvents | events());
                }
                // 从selector中获取SelectionKey,这个selectionKey
                // 就是在events中获取到的
                Iterator<SelectionKey> iterator = keyCount > 0 ? 
                        selector.selectedKeys().iterator() : null;
                while (iterator != null && iterator.hasNext()) {
                    SelectionKey sk = iterator.next();
                    // 获取selectionKey对应的socketWrapper
                    NioSocketWrapper socketWrapper = 
                            (NioSocketWrapper) sk.attachment();
                    if (socketWrapper == null) {
                        iterator.remove();
                    } else {
                        iterator.remove();
                        // 不为空,则执行processKey方法
                        processKey(sk, socketWrapper);
                    }
                }
                timeout(keyCount,hasEvents);
            }
            // 锁数量-1
            getStopLatch().countDown();
        }
        public boolean events() {
            boolean result = false;
            PollerEvent pe = null;
            // 这里会一直轮询events阻塞队列,当在addEvents方法中添加了事件
            // 轮询方法将会获取到添加的事件,并进行处理
            for (int i = 0, size = events.size(); i < size && 
                    (pe = events.poll()) != null; i++ ) {
                result = true;
                try {
                    // 获得轮询事件后启动线程,在PollerEvent的run方法中
                    // 将会使用socket和对应的socketWrapper去注册SelectionKey
                    // 而注册成功的SelectionKey将会在Poller方法中被读取执行
                    pe.run();
                    pe.reset();
                    if (running && !paused && eventCache != null) {
                        // 将事件添加进缓存中
                        eventCache.push(pe);
                    }
                } catch ( Throwable x ) {
                    ...
                }
            }
            return result;
        }
        protected void processKey(SelectionKey sk, 
                NioSocketWrapper socketWrapper) {
            try {
                // 如果关闭,则取消对SelectionKey的处理,processSocket方法
                // 处理逻辑在AbstractEndpoint中,前面已经分析过了
                if (close) {
                    cancelledKey(sk, socketWrapper);
                } else if (sk.isValid() && socketWrapper != null) {
                    if (sk.isReadable() || sk.isWritable()) {
                        if (socketWrapper.getSendfileData() != null) {
                            // 处理文件类型
                            processSendfile(sk, socketWrapper, false);
                        } else {
                            unreg(sk, socketWrapper, sk.readyOps());
                            boolean closeSocket = false;
                            // Read goes before write
                            if (sk.isReadable()) {
                                // 处理可读类型
                                if (socketWrapper.readOperation != null) {
                                    if (!socketWrapper.readOperation
                                            .process()) {
                                        closeSocket = true;
                                    }
                                } else if (!processSocket(socketWrapper, 
                                        SocketEvent.OPEN_READ, true)) {
                                    closeSocket = true;
                                }
                            }
                            if (!closeSocket && sk.isWritable()) {
                                // 处理可写类型
                                if (socketWrapper.writeOperation != null){
                                    if (!socketWrapper.writeOperation
                                            .process()) {
                                        closeSocket = true;
                                    }
                                } else if (!processSocket(socketWrapper, 
                                        SocketEvent.OPEN_WRITE, true)) {
                                    closeSocket = true;
                                }
                            }
                            if (closeSocket) {
                                cancelledKey(sk, socketWrapper);
                            }
                        }
                    }
                } else {
                    cancelledKey(sk, socketWrapper);
                }
            } catch (CancelledKeyException ckx) {
                cancelledKey(sk, socketWrapper);
            } catch (Throwable t) {
                ExceptionUtils.handleThrowable(t);
            }
        }
    }
}

至此,NioEndpoint中比较重要的部分便已经分析完了,这个类的主要作用便是注册启动请求接收器Acceptor、Poller轮询器,使其一直运行以接收用户随时请求进来的请求再处理。这里面的处理逻辑比较多也比较长,因此需要从init和start方法一步一步来看,要不然看着看着可能人就晕了。

1.4 Acceptor

其部分关键源码如下:

public class Acceptor<U> implements Runnable {
    private final AbstractEndpoint<?,U> endpoint;
    protected volatile AcceptorState state = AcceptorState.NEW;
    @Override
    public void run() {
        int errorDelay = 0;
        // 如果endpoint处于运行状态,则循环会一直进行
        // 即如果Tomcat没有关闭,则Acceptor这个线程会一直在这里轮询
        while (endpoint.isRunning()) {
            // 如果endpoint处于暂停状态,则一直循环睡眠
            while (endpoint.isPaused() && endpoint.isRunning()) {
                state = AcceptorState.PAUSED;
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    ...
                }
            }
            // 已经停止,则直接退出
            if (!endpoint.isRunning()) {
                break;
            }
            // 处于运行状态
            state = AcceptorState.RUNNING;
            try {
                // 如果已经达到最大连接,就等待直到有空闲线程出来
                endpoint.countUpOrAwaitConnection();
                if (endpoint.isPaused()) {
                    continue;
                }
                U socket = null;
                try {
                    // 从endpoint获取socket连接,这里面会一直轮询,直到有新
                    // 的socket才会退出来,因此这里可以看成是阻塞的方法
                    socket = endpoint.serverSocketAccept();
                } catch (Exception ioe) {
                    endpoint.countDownConnection();
                    if (endpoint.isRunning()) {
                        errorDelay = handleExceptionWithDelay(errorDelay);
                        throw ioe;
                    } else {
                        break;
                    }
                }
                errorDelay = 0;
                // endpoint正常运行
                if (endpoint.isRunning() && !endpoint.isPaused()) {
                    // 调用前面说过的setSocketOptions方法,将获取到的Socket
                    // 放进轮询器中执行
                    if (!endpoint.setSocketOptions(socket)) {
                        endpoint.closeSocket(socket);
                    }
                } else {
                    // endpoint未正常运行,则销毁socket连接
                    endpoint.destroySocket(socket);
                }
            } catch (Throwable t) {
                ...
            }
        }
        // 如果退出,则代表Acceptor已经结束
        state = AcceptorState.ENDED;
    }
}

可以看到,这个类的执行流程很简单,就是单纯的在这里通过EndPoint轮询获取Socket,如果获取到了Socket也就是请求,则再传给Endpoint去处理(纯正的打工仔)。

1.5 ServerSocketChannelImpl

该类的作用便是获取已经绑定的地址的请求,如果有则返回,如果没有则一直监听地址是否有新的请求(其实也就是一直阻塞轮询)。其部分关键源码如下:

class ServerSocketChannelImpl extends ServerSocketChannel
        implements SelChImpl {
    private static NativeDispatcher nd;
    private final FileDescriptor fd;
    ServerSocket socket;
    public SocketChannel accept() throws IOException {
        synchronized (lock) {
            // 判断绑定的地址端口是否可用
            if (!isOpen())
                throw new ClosedChannelException();
            if (!isBound())
                throw new NotYetBoundException();
            SocketChannel sc = null;
    
            int n = 0;
            FileDescriptor newfd = new FileDescriptor();
            InetSocketAddress[] isaa = new InetSocketAddress[1];
            try {
                // 开始获取socket
                begin();
                if (!isOpen())
                    return null;
                thread = NativeThread.current();
                for (;;) {
                    // 一直轮询是否有新的socket请求,如果没有继续轮询
                    // 如果有则break退出
                    n = accept(this.fd, newfd, isaa);
                    if ((n == IOStatus.INTERRUPTED) && isOpen())
                        continue;
                    break;
                }
            } finally {
                thread = 0;
                end(n > 0);
                assert IOStatus.check(n);
            }
            if (n < 1)
                return null;
            // 获得newfd,并封装返回
            IOUtil.configureBlocking(newfd, true);
            InetSocketAddress isa = isaa[0];
            // 创建新的socket对象
            sc = new SocketChannelImpl(provider(), newfd, isa);
            SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
                try {
                    sm.checkAccept(isa.getAddress().getHostAddress(),
                                   isa.getPort());
                } catch (SecurityException x) {
                    sc.close();
                    throw x;
                }
            }
            return sc;
    
        }
    }
}

1.6 SocketProcessorBase

NioEndpoint的processSocket方法中,使用了SocketProcessorBase及其子类SocketProcessor来传入Executor进行运行处理,也就意味着SocketProcessorBase是实现了Runnable线程接口的,后面对于Socket的具体处理会在这里面进行,因此这一环节也不能错过。其部分关键源码如下:

public abstract class SocketProcessorBase<S> implements Runnable {
    protected SocketWrapperBase<S> socketWrapper;
    protected SocketEvent event;
    @Override
    public final void run() {
        synchronized (socketWrapper) {
            if (socketWrapper.isClosed()) {
                return;
            }
            doRun();
        }
    }
    protected abstract void doRun();
}

可以看到这个方法很简单,只是保存了两个对象以及调用了子类实现来完成doRun方法。我们接着看到NioEndpoint中实现的SocketProcessor。其部分关键源码如下:

protected class SocketProcessor extends SocketProcessorBase<NioChannel> {
    @Override
    protected void doRun() {
        // 获取Socket和Poller,如果装填判断失败则关闭销毁
        NioChannel socket = socketWrapper.getSocket();
        SelectionKey key = socket.getIOChannel()
                .keyFor(socket.getSocketWrapper().getPoller()
                .getSelector());
        Poller poller = NioEndpoint.this.poller;
        if (poller == null) {
            socketWrapper.close();
            return;
        }
        try {
            // 准备开始进行握手
            int handshake = -1;
            try {
                if (key != null) {
                    if (socket.isHandshakeComplete()) {
                    // 不需要握手,直接完成
                        handshake = 0;
                    } else if (event == SocketEvent.STOP || 
                            event == SocketEvent.DISCONNECT ||
                            event == SocketEvent.ERROR) {
                        // 因为某些原因握手失败了
                        handshake = -1;
                    } else {
                        // 进行握手,如果没抛异常,握手成功
                        handshake = socket.handshake(key.isReadable(), 
                                key.isWritable());
                        event = SocketEvent.OPEN_READ;
                    }
                }
            } catch (IOException x) {
                handshake = -1;
            } catch (CancelledKeyException ckx) {
                handshake = -1;
            }
            // 如果成功则使用handler进行相应的处理,失败则进行销毁操作
            if (handshake == 0) {
                SocketState state = SocketState.OPEN;
                // 这个的handler实际上是在AbstractHttp11Protocol类中
                // 写死的,类型为AbstractProtocol的内部类ConnectionHandler
                if (event == null) {
                    state = getHandler()
                            .process(socketWrapper, SocketEvent.OPEN_READ);
                } else {
                    state = getHandler()
                            .process(socketWrapper, event);
                }
                if (state == SocketState.CLOSED) {
                    poller.cancelledKey(key, socketWrapper);
                }
            } else if (handshake == -1 ) {
                poller.cancelledKey(key, socketWrapper);
            } else if (handshake == SelectionKey.OP_READ){
                socketWrapper.registerReadInterest();
            } else if (handshake == SelectionKey.OP_WRITE){
                socketWrapper.registerWriteInterest();
            }
        } catch (CancelledKeyException cx) {
            poller.cancelledKey(key, socketWrapper);
        } catch (VirtualMachineError vme) {
            ExceptionUtils.handleThrowable(vme);
        } catch (Throwable t) {
            poller.cancelledKey(key, socketWrapper);
        } finally {
            socketWrapper = null;
            event = null;
            if (running && !paused && processorCache != null) {
                processorCache.push(this);
            }
        }
    }
}

1.7 ConnectionHandler

由前面的SocketProcessor流程我们可以知道现在已经进入到了handler来处理Socket了,因此我们看到这部分的源码。ConnectionHandler是AbstractProtocol的内部类,其关键源码如下:

protected static class ConnectionHandler<S> 
        implements AbstractEndpoint.Handler<S> {
    private final AbstractProtocol<S> proto;
    private final AtomicLong registerCount = new AtomicLong(0);
    private final Map<S,Processor> connections = new ConcurrentHashMap<>();
    @Override
    public SocketState process(SocketWrapperBase<S> wrapper, 
            SocketEvent status) {
        if (wrapper == null) {
            // 为空则直接跳出
            return SocketState.CLOSED;
        }
        S socket = wrapper.getSocket();
        // 第一次进来connections里面肯定为空,因此获取不到
        Processor processor = connections.get(socket);
        // 如果是异步已经有专门的线程去处理了,因此直接返回即可
        if (SocketEvent.TIMEOUT == status && (processor == null ||
                !processor.isAsync() || 
                !processor.checkAsyncTimeoutGeneration())) {
            return SocketState.OPEN;
        }
        if (processor != null) {
            // 确保不会触发异步超时
            getProtocol().removeWaitingProcessor(processor);
        } else if (status == SocketEvent.DISCONNECT || 
                status == SocketEvent.ERROR) {
            // 如果状态异常则直接返回
            return SocketState.CLOSED;
        }
        ContainerThreadMarker.set();
        try {
            // 一种类型的socket第一次一定是null,需要进行实例化
            // 下面无关紧要的略过
            ...
            if (processor == null) {
                // 使用AbstractProtocol中的createProcessor获得具体的处理类
                // 这个类型在Http11NioProtocol类中的方法中已经写死了
                // 可以具体确定为Http11Processor类型
                processor = getProtocol().createProcessor();
                register(processor);
            }
            processor.setSslSupport(
                    wrapper.getSslSupport(getProtocol()
                    .getClientCertProvider()));
            // 将创建好的processor和socket关联起来
            connections.put(socket, processor);
            SocketState state = SocketState.CLOSED;
            do {
                // 调用processor来处理wrapper和status
                // 根据返回状态来进行具体的后置处理
                // 如果是普通的HTTP请求直接在里面就处理完了,返回的状态
                // 后续用不到,会直接返回,结束这个方法流程
                state = processor.process(wrapper, status);
                // UPGRADING状态Websocket会用到,但是普通的http请求用不到
                if (state == SocketState.UPGRADING) {
                    // 这里略过
                    ...
                    if (upgradeToken == null) {
                        ...
                    } else {
                        HttpUpgradeHandler httpUpgradeHandler = 
                                upgradeToken.getHttpUpgradeHandler();
                        release(processor);
                        // 根据upgradeToken来获取具体的Websocket处理类
                        processor = getProtocol()
                                .createUpgradeProcessor(wrapper, 
                                        upgradeToken);
                        wrapper.unRead(leftOverInput);
                        wrapper.setUpgraded(true);
                        connections.put(socket, processor);
                        // 在这里面调用进去处理WebSocket
                        if (upgradeToken.getInstanceManager() == null) {
                            httpUpgradeHandler
                                    .init((WebConnection) processor);
                        } else {
                            ClassLoader oldCL = upgradeToken
                                    .getContextBind().bind(false, null);
                            try {
                                httpUpgradeHandler
                                        .init((WebConnection) processor);
                            } finally {
                                upgradeToken.getContextBind()
                                        .unbind(false, oldCL);
                            }
                        }
                        if (httpUpgradeHandler instanceof 
                                InternalHttpUpgradeHandler) {
                            if (((InternalHttpUpgradeHandler) 
                                    httpUpgradeHandler).hasAsyncIO()) {
                                state = SocketState.LONG;
                            }
                        }
                    }
                }
            } while ( state == SocketState.UPGRADING);
            ...
            // 如果成功则会直接返回状态
            return state;
        }
        // 后面都是失败后的处理逻辑了,无需关心
        ...
        // 处理完再将对应关系删除
        connections.remove(socket);
        // 释放资源
        release(processor);
        return SocketState.CLOSED;
    }
}

至此这一篇便告一段落了,这一篇讲解了Connector从初始化到运行时获取Socket请求并交给对应的processor进行处理。逻辑稍微复杂,需要一步一步跟着源码走,并且由于这里面大部分类都是由多线程运行的,更加让人迷惑,但只要理解了这里面的运行方式和逻辑就很清晰明了了。

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
作为一个AI机器人,我并没有能力进行源码分析。但是我可以提供一些关于Tomcat8.5的相关信息。 Tomcat8.5是Apache Tomcat的一个版本,是一个开源的Web容器,使用Java编写,可用于部署Java Web应用程序。Tomcat8.5增加了对Java Servlet 3.1、JavaServer Pages 2.3、Java Unified Expression Language 3.0以及WebSocket 1.1的支持。Tomcat8.5还增强了对SSL/TLS的支持,包括支持ALPN协议和OCSP Stapling。Tomcat8.5还提供了一些新的特性,如异步I/O和NIO2。 在Tomcat8.5源码中,主要涉及到的模块有:Catalina、Coyote、Jasper、WebSocket和Tomcat Native。Catalina模块是Tomcat的核心模块,负责处理HTTP请求和响应。Coyote模块负责处理HTTP请求的接收和响应。Jasper模块负责处理JSP页面的编译和执行。WebSocket模块提供了基于WebSocket协议的通信。Tomcat Native模块提供了对APR(Apache Portable Runtime)库的支持,可以提高Tomcat的性能和可靠性。 在Tomcat8.5源码中,还有一些其他的模块,如:Cluster、Manager、Realm、Valve等。Cluster模块提供了集群支持,可以让多个Tomcat实例共享会话信息。Manager模块提供了Web应用程序管理的功能。Realm模块提供了认证和授权的支持。Valve模块提供了一些过滤器和拦截器,可以对HTTP请求和响应进行处理。 总体来说,Tomcat8.5源码是一个庞大而复杂的项目,需要对JavaWeb开发有一定的了解才能进行源码分析。如果有兴趣了解Tomcat8.5的源码,可以先从官方文档和源码注释入手,逐步深入了解各个模块的实现原理

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值