AbstractEndpoint
这个类的目的就是作为处理Socket套接字IO的基础,从命名上来看其要意是处理TCP连接的两端的数据,这也是两台机器之间通信的端点。
AbstractEndpoint针对不同的IO模型有不同的实现:
AbstractEndpoint源码
public abstract class AbstractEndpoint<S> {
// -------------------------------------------------------------- Constants
protected static final StringManager sm = StringManager.getManager("org.apache.tomcat.util.net.res");
public static interface Handler {
// 定义的Socket状态
public enum SocketState {
OPEN, CLOSED, LONG, ASYNC_END, SENDFILE, UPGRADING_TOMCAT,
UPGRADING, UPGRADED
}
// 全局请求处理器GlobalRequestProcessor
public Object getGlobal();
// 重复利用
public void recycle();
}
//
protected enum BindState {
UNBOUND, BOUND_ON_INIT, BOUND_ON_START
}
// Socket接收器,专门用来执行serverSocket.accept()方法
public abstract static class Acceptor implements Runnable {
public enum AcceptorState {
NEW, RUNNING, PAUSED, ENDED
}
protected volatile AcceptorState state = AcceptorState.NEW;
private String threadName;
}
private static final int INITIAL_ERROR_DELAY = 50;
private static final int MAX_ERROR_DELAY = 1600;
// ----------------------------------------------------------------- Fields
/**
* Running state of the endpoint.
*/
protected volatile boolean running = false;
protected volatile boolean paused = false;
// 是否使用内部线程池
protected volatile boolean internalExecutor = true;
// 连接计数器
private volatile LimitLatch connectionLimitLatch = null;
/**
* Socket properties
*/
protected SocketProperties socketProperties = new SocketProperties();
// 接收器数组(tomcat推荐不要超过两个,tomcat默认1个)
protected Acceptor[] acceptors;
// ----------------------------------------------------------------- Properties
// 当endpoint stop时等待内部线程池执行的最大时间,默认5秒
private long executorTerminationTimeoutMillis = 5000;
// Acceptor[] acceptors接收器数组大小
protected int acceptorThreadCount = 0;
// 最大连接数
private int maxConnections = 10000;
// 内部处理socket的线程池
private Executor executor = null;
// tomcat监听的端口,ServerSocket port
private int port;
// 获取ServerSocket实际绑定的端口
public abstract int getLocalPort();
private InetAddress address;
/**
* Allows the server developer to specify the acceptCount (backlog) that
* should be used for server sockets. By default, this value
* is 100.
*/
private int backlog = 100;
// 是否在init生命周期方法中绑定ServerSocket
private boolean bindOnInit = true;
private BindState bindState = BindState.UNBOUND;
// 阻塞时间
private Integer keepAliveTimeout = null;
// 内部线程池核心线程数
private int minSpareThreads = 10;
// 内部线程池最大线程数
private int maxThreads = 200;
// 每个长连接支持处理的最大http请求数量
private int maxKeepAliveRequests=100; // as in Apache HTTPD server
// 支持每个请求头最大个数,0表示不限制
private int maxHeaderCount = 100; // as in Apache HTTPD server
/**
* Name of the thread pool, which will be used for naming child threads.
*/
private String name = "TP";
// 连接池的线程是否是守护线程
private boolean daemon = true;
public void setMaxConnections(int maxCon) {
this.maxConnections = maxCon;
LimitLatch latch = this.connectionLimitLatch;
if (latch != null) {
// Update the latch that enforces this
if (maxCon == -1) {
releaseConnectionLatch();
} else {
// 最大线程数
latch.setLimit(maxCon);
}
} else if (maxCon > 0) {
initializeConnectionLatch();
}
}
public int getKeepAliveTimeout() {
if (keepAliveTimeout == null) {
return getSoTimeout();
} else {
return keepAliveTimeout.intValue();
}
}
public void setMaxThreads(int maxThreads) {
this.maxThreads = maxThreads;
Executor executor = this.executor;
if (internalExecutor && executor instanceof java.util.concurrent.ThreadPoolExecutor) {
((java.util.concurrent.ThreadPoolExecutor) executor).setMaximumPoolSize(maxThreads);
}
}
protected abstract boolean getDeferAccept();
// 属性保存集合
protected HashMap<String, Object> attributes = new HashMap<String, Object>();
public int getCurrentThreadCount() {
Executor executor = this.executor;
if (executor != null) {
if (executor instanceof ThreadPoolExecutor) {
return ((ThreadPoolExecutor) executor).getPoolSize();
} else if (executor instanceof ResizableExecutor) {
return ((ResizableExecutor) executor).getPoolSize();
} else {
return -1;
}
} else {
return -2;
}
}
// 获取当前繁忙的线程数
public int getCurrentThreadsBusy() {
Executor executor = this.executor;
if (executor != null) {
if (executor instanceof ThreadPoolExecutor) {
return ((ThreadPoolExecutor) executor).getActiveCount();
} else if (executor instanceof ResizableExecutor) {
return ((ResizableExecutor) executor).getActiveCount();
} else {
return -1;
}
} else {
return -2;
}
}
// 初始化内部线程池
public void createExecutor() {
internalExecutor = true;
// 使用的任务队列
TaskQueue taskqueue = new TaskQueue();
// daemon-是否是守护线程
TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", daemon, getThreadPriority());
executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf);
taskqueue.setParent( (ThreadPoolExecutor) executor);
}
// 停止内部线程池
public void shutdownExecutor() {
Executor executor = this.executor;
if (executor != null && internalExecutor) {
this.executor = null;
if (executor instanceof ThreadPoolExecutor) {
//this is our internal one, so we need to shut it down
ThreadPoolExecutor tpe = (ThreadPoolExecutor) executor;
tpe.shutdownNow();
long timeout = getExecutorTerminationTimeoutMillis();
if (timeout > 0) {
try {
// 等待停止
tpe.awaitTermination(timeout, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
// Ignore
}
}
TaskQueue queue = (TaskQueue) tpe.getQueue();
queue.setParent(null);
}
}
}
/**
* Unlock the server socket accept using a bogus connection.
*/
// 唤醒等待在accept()方法上的线程
protected void unlockAccept() {
// Only try to unlock the acceptor if it is necessary
boolean unlockRequired = false;
for (Acceptor acceptor : acceptors) {
if (acceptor.getState() == AcceptorState.RUNNING) {
unlockRequired = true;
break;
}
}
if (!unlockRequired) {
return;
}
java.net.Socket s = null;
InetSocketAddress saddr = null;
try {
// Need to create a connection to unlock the accept();
if (address == null) {
saddr = new InetSocketAddress("localhost", getLocalPort());
} else if (address.isAnyLocalAddress()) {
saddr = new InetSocketAddress(getUnlockAddress(address), getLocalPort());
} else {
saddr = new InetSocketAddress(address, getLocalPort());
}
s = new java.net.Socket();
int stmo = 2 * 1000;
int utmo = 2 * 1000;
if (getSocketProperties().getSoTimeout() > stmo) {
stmo = getSocketProperties().getSoTimeout();
}
if (getSocketProperties().getUnlockTimeout() > utmo) {
utmo = getSocketProperties().getUnlockTimeout();
}
s.setSoTimeout(stmo);
// TODO Consider hard-coding to s.setSoLinger(true,0)
s.setSoLinger(getSocketProperties().getSoLingerOn(),getSocketProperties().getSoLingerTime());
s.connect(saddr,utmo);
if (getDeferAccept()) {
/*
* In the case of a deferred accept / accept filters we need to
* send data to wake up the accept. Send OPTIONS * to bypass
* even BSD accept filters. The Acceptor will discard it.
*/
OutputStreamWriter sw;
sw = new OutputStreamWriter(s.getOutputStream(), "ISO-8859-1");
sw.write("OPTIONS * HTTP/1.0\r\n" +
"User-Agent: Tomcat wakeup connection\r\n\r\n");
sw.flush();
}
// Wait for upto 1000ms acceptor threads to unlock
long waitLeft = 1000;
for (Acceptor acceptor : acceptors) {
while (waitLeft > 0 &&
acceptor.getState() == AcceptorState.RUNNING) {
Thread.sleep(5);
waitLeft -= 5;
}
}
} catch(Exception e) {
} finally {
if (s != null) {
try {
s.close();
} catch (Exception e) {
// Ignore
}
}
}
}
// ---------------------------------------------- Request processing methods
public abstract void processSocketAsync(SocketWrapper<S> socketWrapper,
SocketStatus socketStatus);
public abstract void removeWaitingRequest(SocketWrapper<S> socketWrapper);
// ------------------------------------------------------- Lifecycle methods
public abstract void bind() throws Exception;
public abstract void unbind() throws Exception;
public abstract void startInternal() throws Exception;
public abstract void stopInternal() throws Exception;
public final void init() throws Exception {
testServerCipherSuitesOrderSupport();
if (bindOnInit) {
bind();
bindState = BindState.BOUND_ON_INIT;
}
}
private void testServerCipherSuitesOrderSupport() {
// Only test this feature if the user explicitly requested its use.
if(!"".equals(getUseServerCipherSuitesOrder().trim())) {
if (!JreCompat.isJre8Available()) {
throw new UnsupportedOperationException(
sm.getString("endpoint.jsse.cannotHonorServerCipherOrder"));
}
}
}
public final void start() throws Exception {
if (bindState == BindState.UNBOUND) {
bind();
bindState = BindState.BOUND_ON_START;
}
startInternal();
}
// 开启处理accept()方法的线程,默认一个
protected final void startAcceptorThreads() {
int count = getAcceptorThreadCount();
acceptors = new Acceptor[count];
for (int i = 0; i < count; i++) {
acceptors[i] = createAcceptor();
String threadName = getName() + "-Acceptor-" + i;
acceptors[i].setThreadName(threadName);
Thread t = new Thread(acceptors[i], threadName);
t.setPriority(getAcceptorThreadPriority());
// 是否是守护线程
t.setDaemon(getDaemon());
t.start();
}
}
// 实现类提供具体的接收器
protected abstract Acceptor createAcceptor();
public void pause() {
if (running && !paused) {
paused = true;
unlockAccept();
}
}
public void resume() {
if (running) {
paused = false;
}
}
public final void stop() throws Exception {
stopInternal();
if (bindState == BindState.BOUND_ON_START) {
unbind();
bindState = BindState.UNBOUND;
}
}
public final void destroy() throws Exception {
if (bindState == BindState.BOUND_ON_INIT) {
unbind();
bindState = BindState.UNBOUND;
}
}
protected abstract Log getLog();
// Flags to indicate optional feature support
// Some of these are always hard-coded, some are hard-coded to false (i.e.
// the endpoint does not support them) and some are configurable.
// 一些标记特性
public abstract boolean getUseSendfile();
public abstract boolean getUseComet();
public abstract boolean getUseCometTimeout();
public abstract boolean getUsePolling();
// 连接数据控制方法---LimitLatch是通过同步器AQS实现------------------------------------------------------------------
protected LimitLatch initializeConnectionLatch() {
if (maxConnections==-1) {
return null;
}
if (connectionLimitLatch==null) {
// 初始化最大连接限制
connectionLimitLatch = new LimitLatch(getMaxConnections());
}
return connectionLimitLatch;
}
// 连接数据增加
protected void countUpOrAwaitConnection() throws InterruptedException {
if (maxConnections==-1) {
return;
}
LimitLatch latch = connectionLimitLatch;
if (latch!=null) {
latch.countUpOrAwait();
}
}
// 连接数量减少
protected long countDownConnection() {
if (maxConnections==-1) {
return -1;
}
LimitLatch latch = connectionLimitLatch;
if (latch!=null) {
long result = latch.countDown();
return result;
} else {
return -1;
}
}
}
从其源码中不难看出,AbstractEndpoint主要定义了各种IO模型下的公共属性及行为
- ServerSocket的相关属性(绑定端口,ip等)
- 处理accept()方法的接收线程数量
- 内部定义了处理socket的线程池,及该线程池相关属性(线程数,是否是守护线程)等等
- 定义了生命周期方法
init(),start()
等,具体的实现initInternal()
,startInternal()
方法交给具体子类实现 - 定义了Acceptor抽象接收器,交由子类实现具体的Acceptor定义如何接收新来的socket连接
JioEndPoint实现
JioEndPoint是AbstractEndpoint对于传统同步阻塞IO(BIO)的具体实现,
从JioEndPoint的类结构上看其主要实现了AbstractEndPoint的相关抽象方法,ServerSocket就是套接字服务端,同时其实现定义了具体的接收器Acceptor,以及如何处理接收的socket的SocketProcessor处理器。
来看看JioEndPoint本身几个重要的方法
public class JIoEndpoint extends AbstractEndpoint<Socket> {
protected ServerSocket serverSocket = null;
// ------------------------------------------------------------- Properties
protected Handler handler = null;
public void setHandler(Handler handler ) { this.handler = handler; }
public Handler getHandler() { return handler; }
protected ServerSocketFactory serverSocketFactory = null;
protected ConcurrentLinkedQueue<SocketWrapper<Socket>> waitingRequests = new ConcurrentLinkedQueue<SocketWrapper<Socket>>();
@Override
public int getLocalPort() {
ServerSocket s = serverSocket;
if (s == null) {
return -1;
} else {
return s.getLocalPort();
}
}
@Override
public boolean getUseSendfile() { return false; } // Not supported
@Override
public boolean getUseComet() { return false; } // Not supported
@Override
public boolean getUseCometTimeout() { return false; } // Not supported
@Override
public boolean getDeferAccept() { return false; } // Not supported
@Override
public boolean getUsePolling() { return false; } // Not supported
// ------------------------------------------------ Handler Inner Interface
public interface Handler extends AbstractEndpoint.Handler {
public SocketState process(SocketWrapper<Socket> socket,
SocketStatus status);
public SSLImplementation getSslImplementation();
public boolean isAvailable(SocketWrapper<Socket> socket);
}
// -------------------- Public methods --------------------
// 绑定端口,开始监听连接
@Override
public void bind() throws Exception {
// Initialize thread count defaults for acceptor
if (acceptorThreadCount == 0) {
acceptorThreadCount = 1;
}
if (serverSocketFactory == null) {
if (isSSLEnabled()) {
serverSocketFactory = handler.getSslImplementation().getServerSocketFactory(this);
} else {
serverSocketFactory = new DefaultServerSocketFactory(this);
}
}
if (serverSocket == null) {
try {
if (getAddress() == null) {
serverSocket = serverSocketFactory.createSocket(getPort(), getBacklog());
} else {
// 创建ServerSocket开始监听
serverSocket = serverSocketFactory.createSocket(getPort(), getBacklog(), getAddress());
}
} catch (BindException orig) {
// ....
throw be;
}
}
}
@Override
public void startInternal() throws Exception {
if (!running) {
running = true;
paused = false;
// Create worker collection
if (getExecutor() == null) {
createExecutor();
}
initializeConnectionLatch();
// 开启处理accept()接收器方法
startAcceptorThreads();
// Start async timeout thread
Thread timeoutThread = new Thread(new AsyncTimeout(), getName() + "-AsyncTimeout");
timeoutThread.setPriority(threadPriority);
timeoutThread.setDaemon(true);
timeoutThread.start();
}
}
@Override
protected AbstractEndpoint.Acceptor createAcceptor() {
return new Acceptor();
}
// 定义如何处理接收到的socket
protected boolean processSocket(Socket socket) {
// Process the request from this socket
try {
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;
}
// 包装之后交给线程池处理
getExecutor().execute(new SocketProcessor(wrapper));
} catch (RejectedExecutionException x) {
return false;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
return false;
}
return true;
}
}
BIO接收器Acceptor实现
protected class Acceptor extends AbstractEndpoint.Acceptor {
@Override
public void run() {
int errorDelay = 0;
// 循环处理
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();
Socket socket = null;
try {
// Accept the next incoming connection from the server
// 接收新的socket
socket = serverSocketFactory.acceptSocket(serverSocket);
} catch (IOException ioe) {
countDownConnection();
// Introduce delay if necessary
errorDelay = handleExceptionWithDelay(errorDelay);
// re-throw
throw ioe;
}
// Successful accept, reset the error delay
errorDelay = 0;
// Configure the socket
if (running && !paused && setSocketOptions(socket)) {
// 处理socket套接字
if (!processSocket(socket)) {
countDownConnection();
// Close socket right away
closeSocket(socket);
}
} else {
countDownConnection();
// Close socket right away
closeSocket(socket);
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("endpoint.accept.fail"), t);
}
}
state = AcceptorState.ENDED;
}
}
Acceptor主要就是根据容器的运行状态,及连接数量合适的处理ServerSocket#accept()
方法,将接收到的socket交个线程池处理。
而线程池线程如何处理Socket则是由SocketProcessor定义的
SocketProcessor如何处理socket
protected class SocketProcessor implements Runnable {
protected SocketWrapper<Socket> socket = null;
protected SocketStatus status = null;
public SocketProcessor(SocketWrapper<Socket> socket, SocketStatus status) {
this(socket);
this.status = status;
}
@Override
public void run() {
boolean launch = false;
synchronized (socket) {
try {
SocketState state = SocketState.OPEN;
// ... 省略部分ssl相关代码....
// 将socket交个具体的处理器处理
if ((state != SocketState.CLOSED)) {
if (status == null) {
state = handler.process(socket, SocketStatus.OPEN_READ);
} else {
state = handler.process(socket,status);
}
}
// 其他情况
if (state == SocketState.CLOSED) {
countDownConnection();
try {
socket.getSocket().close();
} catch (IOException e) {
// Ignore
}
} else if (state == SocketState.OPEN ||
state == SocketState.UPGRADING ||
state == SocketState.UPGRADING_TOMCAT ||
state == SocketState.UPGRADED){
// 长连接
socket.setKeptAlive(true);
socket.access();
launch = true;
} else if (state == SocketState.LONG) {
socket.access();
waitingRequests.add(socket);
}
} finally {
if (launch) {
try {
getExecutor().execute(new SocketProcessor(socket, SocketStatus.OPEN_READ));
} catch (RejectedExecutionException x) {
try {
//unable to handle connection at this time
handler.process(socket, SocketStatus.DISCONNECT);
} finally {
countDownConnection();
}
}
}
}
}
socket = null;
// Finish up this request
}
}
JioEndPoint.Handler
具体的Handler定义是JioEndPoint内部定义的接口
public interface Handler extends AbstractEndpoint.Handler {
public SocketState process(SocketWrapper<Socket> socket, SocketStatus status);
public SSLImplementation getSslImplementation();
public boolean isAvailable(SocketWrapper<Socket> socket);
}
继承至AbstractEndpoint.Handler这个标记接口,其实现根据不同的协议有不同的实现,专门处理BIO的不同协议
到此tomcat EndPoint
的脉络大致清晰了,首先是根据不同的IO模型有具体的Endpoint实现,针对某个的IO模型又有不同的协议实现如何处理接收到的套接字处理器XXX Protocol Handler
。