JBossWeb 是JBoss 中的 Web 容器,他是对 Tomcat 的封装,本文以 Http 连接器为例,简单说明 JBossWeb/Tomcat 初始化连接器和处理 Http 请求过程 。本文内容提要:
如下图所示:
Connector 可以是 HTTP Connector,也可以是 AJP Connector,Connector 中有 ProtocolHandler 和 Adapter 属性,Connector 初始化主要包括:初始化 Adapter,且将初始化的 Adapter 的 设定给 ProtocolHandler,然后调运 ProtocolHandler 的初始化方法,如下面代码段所示:
// Initializa adapter
adapter = new CoyoteAdapter(this);
protocolHandler.setAdapter(adapter);
IntrospectionUtils.setProperty(protocolHandler, "jkHome", System.getProperty("catalina.base"));
try {
protocolHandler.init();
} catch (Exception e) {
throw new LifecycleException(MESSAGES.protocolHandlerInitFailed(e));
}
Http11Protocol 它有一个 Http11ConnectionHandler Handler,该 Handler 实现 `org.apache.tomcat.util.net.JIoEndpoint.Handler` 接口,Http11Protocol 同样有一个 JIoEndpoint 属性,该属性用来处理 incoming TCP connections,如下代码段所示:
protected Http11ConnectionHandler cHandler = new Http11ConnectionHandler(this);
protected JIoEndpoint endpoint = new JIoEndpoint();
JIoEndpoint,关于此类的作用之前我们有说,对该类最直接的总结如下:
/**
* Handle incoming TCP connections.
*
* This class implement a simple server model: one listener thread accepts on a socket and
* creates a new worker thread for each incoming connection.
*
* More advanced Endpoints will reuse the threads, use queues, etc.
*
* @author James Duncan Davidson
* @author Jason Hunter
* @author James Todd
* @author Costin Manolache
* @author Gal Shachor
* @author Yoav Shapira
* @author Remy Maucherat
*/
public class JIoEndpoint {
Connector 开始方法验证更新当前的状态,并调运 Http11Protocol 的开始方法
Http11Protocol 的开始方法中直接调运 JIoEndpoint 的开始方法。
JIoEndpoint 的开始方法主要包括:
如果外部基于 Executor 的线程池为空,则初始化内部的 workers 栈,该栈保存Worker,初始化的栈大小定义如下:
protected int maxThreads = (org.apache.tomcat.util.Constants.LOW_MEMORY) ? 64 : ((Constants.MAX_THREADS == -1) ? 512 * Runtime.getRuntime().availableProcessors() : Constants.MAX_THREADS);
启动 Acceptor 线程,默认线程的名字为 http-/127.0.0.1:8080-Acceptor-0
如下代码段显示如上逻辑
public void start()
throws Exception {
// Initialize socket if not done before
if (!initialized) {
init();
}
if (!running) {
running = true;
paused = false;
// Create worker collection
if (executor == null) {
workers = new WorkerStack(maxThreads);
}
// Start event poller thread
eventPoller = new Poller();
eventPoller.init();
Thread pollerThread = new Thread(eventPoller, getName() + "-Poller");
pollerThread.setPriority(threadPriority);
pollerThread.setDaemon(true);
pollerThread.start();
// Start acceptor threads
for (int i = 0; i < acceptorThreadCount; i++) {
Thread acceptorThread = new Thread(new Acceptor(), getName() + "-Acceptor-" + i);
acceptorThread.setPriority(threadPriority);
acceptorThread.setDaemon(daemon);
acceptorThread.start();
}
}
}
JBoss Web 中关于max-connections 的定义如下
protected int pollerSize = (org.apache.tomcat.util.Constants.LOW_MEMORY) ? 128 : (32 * 1024);
public void setPollerSize(int pollerSize) { this.pollerSize = pollerSize; }
public int getPollerSize() { return pollerSize; }
protected int maxThreads = (org.apache.tomcat.util.Constants.LOW_MEMORY) ? 64 : ((Constants.MAX_THREADS == -1) ? 512 * Runtime.getRuntime().availableProcessors() : Constants.MAX_THREADS);
public void setMaxThreads(int maxThreads) { this.maxThreads = maxThreads; }
public int getMaxThreads() { return maxThreads; }
JIoEndpoint 处理 Socket 请求如下图所示
如上,首先 Acceptor 线程(通常名字为 http-/127.0.0.1:8080-Acceptor-0)阻塞等待 Socket 连接,如下所示:
"http-/127.0.0.1:8080-Acceptor-0" daemon prio=10 tid=0x49ed5800 nid=0xbe9 runnable [0x49789000]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:398)
at java.net.ServerSocket.implAccept(ServerSocket.java:522)
at java.net.ServerSocket.accept(ServerSocket.java:490)
at org.apache.tomcat.util.net.DefaultServerSocketFactory.acceptSocket(DefaultServerSocketFactory.java:61)
at org.apache.tomcat.util.net.JIoEndpoint$Acceptor.run(JIoEndpoint.java:309)
at java.lang.Thread.run(Thread.java:722)
Locked ownable synchronizers:
- None