Tomcat组件
这篇文章介绍的是客户端请求的接收过程,而不是tomcat的启动过程。关注点在:服务端在serverSocket启动、监听和客户端socket发送请求的执行过程。鉴于服务端通常是NIO模型,后面基于Http11NioProtocol协议介绍的。
服务端serverSocket启动和客户端socket请求监听的过程
- 在Connector组件init初始化的时,通过NioEndpoint的bind方法来绑定服务端端口。在Connector组件start启动的时,通过NioEndpoint的startInternal方法初始化线程池Executor、启动Poller线程和启动Acceptor线程。
- Acceptor线程一直循环监听serverSocketChannel是否有连接,如果有连接,则accept接收客户端的链接socket,并向poller中的events队列增加OP_REGISTER事件。
//Acdeptor线程的主体逻辑
while (!stopCalled) {
//accept客户端的请求socket
socket = endpoint.serverSocketAccept();
//向poller中的envets队列中添加OP_REGISTER事件
endpoint.setSocketOptions(socket)
}
//accept客户端的链接socket
protected SocketChannel serverSocketAccept(){
SocketChannel result = serverSock.accept();
return result;
}
//向poller中的envets队列添加OP_REGISTER事件
protected boolean setSocketOptions(SocketChannel socket) {
NioSocketWrapper socketWrapper = null;
try {
// Allocate channel and wrapper
NioChannel channel = null;
if (nioChannels != null) {
channel = nioChannels.pop();
}
if (channel == null) {
SocketBufferHandler bufhandler = new SocketBufferHandler(
socketProperties.getAppReadBufSize(),
socketProperties.getAppWriteBufSize(),
socketProperties.getDirectBuffer());
if (isSSLEnabled()) {
channel = new SecureNioChannel(bufhandler, this);
} else {
channel = new NioChannel(bufhandler);
}
}
NioSocketWrapper newWrapper = new NioSocketWrapper(channel, this);
channel.reset(socket, newWrapper);
connections.put(socket, newWrapper);
socketWrapper = newWrapper;
// Set socket properties
// Disable blocking, polling will be used
socket.configureBlocking(false);
socketProperties.setProperties(socket.socket());
socketWrapper.setReadTimeout(getConnectionTimeout());
socketWrapper.setWriteTimeout(getConnectionTimeout());
socketWrapper.setKeepAliveLeft(NioEndpoint.this.getMaxKeepAliveRequests());
//向poller中的envets队列中添加OP_REGISTER事件
poller.register(socketWrapper);
return true;
} catch (Throwable t) {
//...
}
return false;
}
- Poller线程处理events中的OP_REGISTER注册事件,在对应Selector中注册客户端socket的OP_READ兴趣事件,并且在循环中监听Selector中客户端socket中的事件,如果有请求事件发生,则调用方法processKey处理客户端socket的请求。
//Poller线程中的主要逻辑:
//1、处理Acceptor线程向events队列中添加的注册事件-events()方法处理;
//2、处理selector中客户端socket请求的事件-processKey(sk,socketWrapper)
public void run() {
// Loop until destroy() is called
while (true) {
boolean hasEvents = false;
try {
if (!close) {
//处理Acceptor线程向events队列中添加的注册事件
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);
}
//没有请求读写事件发生,优先处理events队列中的注册事件
if (keyCount == 0) {
hasEvents = (hasEvents | events());
}
} catch (Throwable x) {
ExceptionUtils.handleThrowable(x)<