一、概述
tomcat的网络模型有三种,分别是 JIO(即BIO), NIO,NIO2(即AIO)。tomcat7之前包含JIO和NIO,tomcat8之后的版本包含NIO和NIO2。tomcat7默认是JIO,tomcat8之后默认的IO是NIO。这三种IO性能上从高到低 NIO2 > NIO > JIO。下面分别对这三种IO做具体源码级的分析。
JIO API: java.net.ServerSocket、java.net.Socket
NIO API: java.nio.channels.ServerSocketChannel 、 java.nio.channels.SocketChannel 、 java.nio.channels.Selector
NIO2 API: java.nio.channels.AsynchronousServerSocketChannel、 java.nio.channels.AsynchronousSocketChannel
二、JIO
流程步骤:
- JIoEndpoint.Acceptor 负责无线循环获取socket连接
- 判断是否超过最大并发
- 接收到socket连接请求,为socket设置自定义属性
- 将socket包装成 SocketWrapper
- 创建一个 SocketWrapper 的处理器 SocketProcessor
- 将SocketProcessor处理器扔进线程池执行
protected class JIoEndpoint.Acceptor extends AbstractEndpoint.Acceptor {
@Override
public void run() {
while (running) {
state = AcceptorState.RUNNING;
try {
// 判断是否超过最大并发
countUpOrAwaitConnection();
Socket socket = null;
try {
// 接收到socket连接请求
socket = serverSocketFactory.acceptSocket(serverSocket);
} catch (IOException ioe) {
countDownConnection();
}
// 为socket设置自定义属性
if (running && !paused && setSocketOptions(socket)) {
// Hand this socket off to an appropriate processor
if (!processSocket(socket)) {
countDownConnection();
// Close socket right away
closeSocket(socket);
}
}
} catch (Exception x) {
}
}
state = AcceptorState.ENDED;
}
}
protected boolean processSocket(Socket socket) {
// Process the request from this socket
try {
// 将socket包装成 SocketWrapper
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;
}
// 创建一个 SocketWrapper 的处理器 SocketProcessor
// 将SocketProcessor处理器扔进线程池执行
getExecutor().execute(new SocketProcessor(wrapper));
} catch (RejectedExecutionException x) {
log.warn("Socket processing request was rejected for:"+socket,x);
return false;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
// This means we got an OOM or similar creating a thread, or that
// the pool and its queue are full
log.error(sm.getString("endpoint.process.fail"), t);
return false;
}
return true;
}
二、NIO
流程步骤:
- NioEndpoint.Acceptor 负责无线循环获取socket连接
- 判断是否超过最大并发
- 接收到SocketChannel连接请求,为SocketChannel设置自定义属性
- 将SocketChannel封装成NioChannel
- 将NioChannel封装成NioSocketWrapper
- 根据NioChannel和NioSocketWrapper封装成PollerEvent的注册事件
- Poller拉倒PollerEvent的注册事件
- 注册读事件在selector选择器上
- Poller拉取到读取数据的key
- 将读取数据的事件封装成 SocketProcessor 扔到线程池处理
protected class NioEndpoint.Acceptor extends AbstractEndpoint.Acceptor {
@Override
public void run() {
while (running) {
state = AcceptorState.RUNNING;
try {
// 判断是否超过最大并发
countUpOrAwaitConnection();
SocketChannel socket = null;
try {
// 接收到SocketChannel连接请求,
socket = serverSock.accept();
} catch (IOException ioe) {
// We didn't get a socket
countDownConnection();
}
// Configure the socket
if (running && !paused) {
// 为SocketChannel设置自定义属性
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;
}
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();
// 为SocketChannel设置自定义属性
socketProperties.setProperties(sock);
// 从对象缓存池获取NioChannel
NioChannel channel = nioChannels.pop();
if (channel == null) {
// 缓存池不存在,new一个NioChannel
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();
}
// 注册channel
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;
}
public void register(final NioChannel socket) {
socket.setPoller(this);
// 将NioChannel封装成NioSocketWrapper
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());
// 根据NioChannel和NioSocketWrapper封装成PollerEvent的注册事件
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);
// 将event放入队列中,供poller拉取
addEvent(r);
}
// Poller.run()
@Override
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();
}
三、NIO2
流程步骤:
- Nio2Endpoint.Acceptor 负责无线循环获取socket连接
- 判断是否超过最大并发
- 接收到AsynchronousSocketChannel连接请求,为AsynchronousSocketChannel设置自定义属性(阻塞)
- 将AsynchronousSocketChannel封装成Nio2Channel
- 将Nio2Channel封装成Nio2SocketWrapper
- 将Nio2SocketWrapper和读取数据的事件封装成 SocketProcessor 扔到线程池处理
- 数据异步回调(org.apache.tomcat.util.net.Nio2Endpoint.Nio2SocketWrapper.readCompletionHandler)
protected class Nio2Endpoint.Acceptor extends AbstractEndpoint.Acceptor {
@Override
public void run() {
int errorDelay = 0;
// Loop until we receive a shutdown command
while (running) {
state = AcceptorState.RUNNING;
try {
// 判断是否超过最大并发
countUpOrAwaitConnection();
AsynchronousSocketChannel socket = null;
try {
//接收到AsynchronousSocketChannel连接请求
socket = serverSock.accept().get();
} catch (Exception e) {
// We didn't get a socket
countDownConnection();
if (running) {
// Introduce delay if necessary
errorDelay = handleExceptionWithDelay(errorDelay);
// re-throw
throw e;
} else {
break;
}
}
// Successful accept, reset the error delay
errorDelay = 0;
// Configure the socket
if (running && !paused) {
// 为AsynchronousSocketChannel设置自定义属性,并且执行后续流程
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;
}
protected boolean setSocketOptions(AsynchronousSocketChannel socket) {
try {
//
socketProperties.setProperties(socket);
// 将AsynchronousSocketChannel封装成Nio2Channel
Nio2Channel channel = nioChannels.pop();
if (channel == null) {
SocketBufferHandler bufhandler = new SocketBufferHandler(socketProperties.getAppReadBufSize(),
socketProperties.getAppWriteBufSize(), socketProperties.getDirectBuffer());
if (isSSLEnabled()) {
channel = new SecureNio2Channel(bufhandler, this);
} else {
channel = new Nio2Channel(bufhandler);
}
}
// 将Nio2Channel封装成Nio2SocketWrapper
Nio2SocketWrapper socketWrapper = new Nio2SocketWrapper(channel, this);
channel.reset(socket, socketWrapper);
socketWrapper.setReadTimeout(getSocketProperties().getSoTimeout());
socketWrapper.setWriteTimeout(getSocketProperties().getSoTimeout());
socketWrapper.setKeepAliveLeft(Nio2Endpoint.this.getMaxKeepAliveRequests());
socketWrapper.setSecure(isSSLEnabled());
socketWrapper.setReadTimeout(getConnectionTimeout());
socketWrapper.setWriteTimeout(getConnectionTimeout());
// 将Nio2SocketWrapper和读取数据的事件封装成 SocketProcessor 扔到线程池处理
return processSocket(socketWrapper, SocketEvent.OPEN_READ, true);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error("", t);
}
// Tell to close the socket
return false;
}
public boolean processSocket(SocketWrapperBase<S> socketWrapper,
SocketEvent event, boolean dispatch) {
try {
if (socketWrapper == null) {
return false;
}
SocketProcessorBase<S> sc = processorCache.pop();
if (sc == null) {
sc = createSocketProcessor(socketWrapper, event);
} else {
sc.reset(socketWrapper, event);
}
Executor executor = getExecutor();
if (dispatch && executor != null) {
executor.execute(sc);
} else {
sc.run();
}
} catch (RejectedExecutionException ree) {
getLog().warn(sm.getString("endpoint.executor.fail", socketWrapper) , ree);
return false;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
// This means we got an OOM or similar creating a thread, or that
// the pool and its queue are full
getLog().error(sm.getString("endpoint.process.fail"), t);
return false;
}
return true;
}
public Nio2SocketWrapper(Nio2Channel channel, final Nio2Endpoint endpoint) {
super(channel, endpoint);
socketBufferHandler = channel.getBufHandler();
this.readCompletionHandler = new CompletionHandler<Integer, ByteBuffer>() {
@Override
public void completed(Integer nBytes, ByteBuffer attachment) {
if (log.isDebugEnabled()) {
log.debug("Socket: [" + Nio2SocketWrapper.this + "], Interest: [" + readInterest + "]");
}
// 将读通知置为false
readNotify = false;
synchronized (readCompletionHandler) {
// 判断是否有数据可读
if (nBytes.intValue() < 0) {
failed(new EOFException(), attachment);
} else {
if (readInterest && !Nio2Endpoint.isInline()) {// 如果注册了读信号,而且没有线程等待读,则直接启动读
readNotify = true;
} else {// 有线程等待读,则唤醒线程继续读
// Release here since there will be no
// notify/dispatch to do the release.
readPending.release();
}
readInterest = false;// 读信号置为false,从新等待注册读信号
}
}
if (readNotify) {// 直接启动读
getEndpoint().processSocket(Nio2SocketWrapper.this, SocketEvent.OPEN_READ, false);
}
}
}
}
来源:oschina
链接:https://my.oschina.net/u/2937247/blog/4305576