解析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方法。