参考资料: Tomcat7.0源码分析——请求原理分析(上)
servlet应用放入tomcat中启动后就可以接受请求,那在tomcat中是怎么实现的呢?
1、ProtocolHandler接口是真正处理请求的地方,这个接口是在Connector中初始化的。在Connector中有两个方法用来初始化和启动ProtocolHandler
@Override
protected void initInternal() throws LifecycleException {
super.initInternal();
// 构造Adapter对象,Adapter用来适配不同的网络协议
adapter = new CoyoteAdapter(this);
protocolHandler.setAdapter(adapter);
if (null == parseBodyMethodsSet) {
setParseBodyMethods(getParseBodyMethods());
}
try {
// 初始化ProtocolHandler,ProtocolHandler用来处理请求
protocolHandler.init();
} catch (Exception e) {
throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerInitializationFailed"), e);
}
// 初始化MapperListener,MapperListener注册host
mapperListener.init();
}
@Override
protected void startInternal() throws LifecycleException {
if (getPort() < 0) {
throw new LifecycleException(sm.getString("coyoteConnector.invalidPort", Integer.valueOf(getPort())));
}
// 设置Connector已经启动
setState(LifecycleState.STARTING);
try {
// 启动protocolHandler
protocolHandler.start();
} catch (Exception e) {
String errPrefix = "";
if (this.service != null) {
errPrefix += "service.getName(): \"" + this.service.getName() + "\"; ";
}
throw new LifecycleException(errPrefix + " " + sm.getString("coyoteConnector.protocolHandlerStartFailed"), e);
}
// 启动MapperListener
mapperListener.start();
}
2、我们来看看初始化ProtocolHandler的方法,ProtocolHandler默认使用Http11Protocol实例化,Http11Protocol直接继承了AbstractProtocol的init方法。
@Override
public void init() throws Exception {
if (getLog().isInfoEnabled()) {
getLog().info(sm.getString("abstractProtocolHandler.init", getName()));
}
if (oname == null) {
oname = createObjectName();
if (oname != null) {
Registry.getRegistry(null, null).registerComponent(this, oname, null);
}
}
if (this.domain != null) {
try {
tpOname = new ObjectName(domain + ":type=ThreadPool,name=" + getName());
Registry.getRegistry(null, null).registerComponent(endpoint, tpOname, null);
} catch (Exception e) {
getLog().error(sm.getString("abstractProtocolHandler.mbeanRegistrationFailed", tpOname, getName()), e);
}
rgOname = new ObjectName(domain + ":type=GlobalRequestProcessor,name=" + getName());
Registry.getRegistry(null, null).registerComponent(getHandler().getGlobal(), rgOname, null);
}
String endpointName = getName();
endpoint.setName(endpointName.substring(1, endpointName.length() - 1));
try {
// 重点是这个方法,JIoEndpoint做为初始化的实现,创建服务器socket
endpoint.init();
} catch (Exception ex) {
getLog().error(sm.getString("abstractProtocolHandler.initError",
getName()), ex);
throw ex;
}
}
3、JioEndpoint创建socket的方法
@Override
public void bind() throws Exception {
// 初始化接受请求线程数量
if (acceptorThreadCount == 0) {
acceptorThreadCount = 1;
}
// 初始化socket最大连接数
if (getMaxConnections() == 0) {
setMaxConnections(getMaxThreads());
}
if (serverSocketFactory == null) {
if (isSSLEnabled()) {
// 创建Socket工厂
serverSocketFactory = handler.getSslImplementation().getServerSocketFactory(this);
} else {
serverSocketFactory = new DefaultServerSocketFactory(this);
}
}
if (serverSocket == null) {
try {
if (getAddress() == null) {
// 创建服务器socket
serverSocket = serverSocketFactory.createSocket(getPort(), getBacklog());
} else {
serverSocket = serverSocketFactory.createSocket(getPort(), getBacklog(), getAddress());
}
} catch (BindException orig) {
String msg;
if (getAddress() == null)
msg = orig.getMessage() + " <null>:" + getPort();
else
msg = orig.getMessage() + getAddress().toString() + ":" + getPort();
BindException be = new BindException(msg);
be.initCause(orig);
throw be;
}
}
}
4、现在我们的服务端socket已经创建好了,接下来启动这个socket,启动和初始化相似, Http11Protocol直接继承了 AbstractProtocol的start方法。
@Override
public void start() throws Exception {
if (getLog().isInfoEnabled())
getLog().info(sm.getString("abstractProtocolHandler.start", getName()));
try {
// 还是交给JIoEndpoint来启动
endpoint.start();
} catch (Exception ex) {
getLog().error(sm.getString("abstractProtocolHandler.startError", getName()), ex);
throw ex;
}
}
5、JioEndpoint启动socket的方法
@Override
public void startInternal() throws Exception {
if (!running) {
running = true;
paused = false;
if (getExecutor() == null) {
// 初始化线程池
createExecutor();
}
// 设置最大连接数,超过阻塞线程
initializeConnectionLatch();
// 启动接受请求的线程
startAcceptorThreads();
// 启动链接超时的线程
Thread timeoutThread = new Thread(new AsyncTimeout(), getName() + "-AsyncTimeout");
timeoutThread.setPriority(threadPriority);
timeoutThread.setDaemon(true);
timeoutThread.start();
}
}
public void createExecutor() {
internalExecutor = true;
// 创建任务队列
TaskQueue taskqueue = new TaskQueue();
// 创建线程工厂
TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", daemon, getThreadPriority());
// 初始化线程池
executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf);
// 任务队列使用线程池产生
taskqueue.setParent( (ThreadPoolExecutor) executor);
}
7、启动接受请求的线程
protected final void startAcceptorThreads() {
// 创建一个线程数组
int count = getAcceptorThreadCount();
acceptors = new Acceptor[count];
for (int i = 0; i < count; i++) {
// 实例化线程类
acceptors[i] = createAcceptor();
// 使用Thread 启动
Thread t = new Thread(acceptors[i], getName() + "-Acceptor-" + i);
t.setPriority(getAcceptorThreadPriority());
t.setDaemon(getDaemon());
t.start();
}
}
8、接受请求的线程类
protected class Acceptor extends AbstractEndpoint.Acceptor {
@Override
public void run() {
int errorDelay = 0;
// 无限循环直接接受到shutdown后退出
while (running) {
// 收到线程暂停的命令后暂停50ms
while (paused && running) {
state = AcceptorState.PAUSED;
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
}
if (!running) {
break;
}
state = AcceptorState.RUNNING;
try {
// 达到了最大连接数,线程阻塞
countUpOrAwaitConnection();
Socket socket = null;
try {
// 从服务端socket接受链接
socket = serverSocketFactory.acceptSocket(serverSocket);
} catch (IOException ioe) {
errorDelay = handleExceptionWithDelay(errorDelay);
throw ioe;
}
errorDelay = 0;
if (running && !paused && setSocketOptions(socket)) {
if (!processSocket(socket)) {
closeSocket(socket);
}
} else {
closeSocket(socket);
}
} catch (IOException x) {
if (running) {
log.error(sm.getString("endpoint.accept.fail"), x);
}
} catch (NullPointerException npe) {
if (running) {
log.error(sm.getString("endpoint.accept.fail"), npe);
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("endpoint.accept.fail"), t);
}
}
state = AcceptorState.ENDED;
}
}
到此为止,请求和服务器之间的链接已经建立好了。