Tomcat调用解析(EndPoint分析)

2 篇文章 0 订阅

解析EndPoint调用过程:

我们已知整个tomcat组件都是通过LifeCycle接口下的LifeCycleBase模版方法init调用initInternal完成初始化,调用start方法运行。

  • LifeCycle
  •  LifeCycleBase
    
  •  		tomcat组件
    

那么EndPoint也不例外,不过EndPoint是通过Protocolhandler进行初始化的。
Protocolhandler则是通过Connector进行初始化。
其中Connector才继承了LifeCycleBase类。

那么我们直接在Connector类下找到initInternal方法,重要操作一般都在try中。

try {
    protocolHandler.init();
} catch (Exception e) {
    throw new LifecycleException(
            sm.getString("coyoteConnector.protocolHandlerInitializationFailed"), e);
}

ProtocolHandler是一个协议处理器。
Tomcat支持NIO NIO2(异步) Apr这三种IO模型,支持HTTP1.1 AJP等应用层协议。
IO在传输层中,协议在应用层中,所以两两组合,最起码都有6种。

AbstractProtocol作为抽象类实现ProtocolHandler接口,使用组合的方式,其内部成员变量有一个AbstractEndpoint封装EndPoint。
连接器结构

ProtocolHandler中有EndPoint和Processor。

我们找到一个最常用的ProtocolHandler:Http11NioProtocol

public Http11NioProtocol() {
    super(new NioEndpoint());
}

其构造方法调用父类的构造方法注入NioEndpoint。

NioEndpoint重要的有三个东西:

1.Acceptor[] acceptors

2.Poller[] pollers

3.PollerEvent

其中1,2都相当于一个线程数组

在调用Connector的start方法时,往下会调用EndPoint的start方法,那么这时就会创建线程start。

先开启pollers数组线程

再开启acceptors数组线程

我们可以分别查看两个类的run方法:

Poller:

以下是Poller的run方法

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();
}

循环调用events方法

private final SynchronizedQueue<PollerEvent> events =
        new SynchronizedQueue<>();

events内容:
在这个同步队列里找到一个不为空的PollerEvent调用其run方法。

然后重置PollerEvent,并且添加到eventCache当中

private SynchronizedStack eventCache;

Acceptor

protected class Acceptor extends AbstractEndpoint.Acceptor {

    @Override
    public void run() {

        int errorDelay = 0;

        // Loop until we receive a shutdown command
        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();

                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();
                    if (running) {
                        // Introduce delay if necessary
                        errorDelay = handleExceptionWithDelay(errorDelay);
                        // re-throw
                        throw ioe;
                    } else {
                        break;
                    }
                }
                // Successful accept, reset the error delay
                errorDelay = 0;

                // Configure the socket
                if (running && !paused) {
                    // setSocketOptions() will hand the socket off to
                    // an appropriate processor if successful
                    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;
    }


}

Acceptor run方法循环直到shutdown

socket = serverSock.accept();等待客户端请求

其中setSocketOptions方法详细查看

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();
        socketProperties.setProperties(sock);

        NioChannel channel = nioChannels.pop();
        if (channel == null) {
            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();
        }
        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;
}

NioChannel channel = nioChannels.pop();弹出一个channel

初始化channel

getPoller0().register(channel);

public Poller getPoller0() {
    int idx = Math.abs(pollerRotater.incrementAndGet()) % pollers.length;
    return pollers[idx];
}

返回一个poller

查看register方法:

public void register(final NioChannel socket) {
    socket.setPoller(this);
    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());
    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);
    addEvent(r);
}

创建一个NioSocketWrapper类 设置属性

addEvent方法就是往events中添加PollerEvent

private final SynchronizedQueue<PollerEvent> events =
        new SynchronizedQueue<>();

总结:整个Endpoint流程可以看出先启动Poller数组线程,再启动Accept数组线程。
Accept结束socket请求,然后再Poller中获取一个poller,调用register方法往events中添加PollerEvent。

Poller则是循环检测events中是否有PollerEvent,调用其run方法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值