APR,全称Apache Portable Runtime,使用native server为Tomcat提供更好的伸缩性、更高的性能以及更强的集成能力。APR还是Apache HTTP Server2.x中的核心轻量级库,它可以提供更好的IO功能(如sendfile,epoll和OpenSSL)、OS功能和本地线程管理(共享内存、NT管道和UNIX套接字)。这些都可以使Tomcat变得更通用、更易扩展。
APR运行需要以下3个组件:APR Library、JNI Wapper for APR和OpenSSL Libary。如果以上功能已经安装,Tomcat在启动时会自动使用APR Connector。
与JIoEndPoint相比,AprEndpoint使用JNI的接口来获得对Socket的访问,功能实现要更为复杂,含有的线程更多:Acceptor Thread、Asynctimeout Thread、Poller Thread、Comet Poller Thread和Sendfile Thread。
Acceptor Thread、Asynctimeout Thread
功能与JIoEndpoint中的类似,同样是完成侦听和监控request的任务,不同的是这两个class直接继承Thread而不是实现Runnable接口。最终负责处理Socket的地方是在AjpConnectionHandler中,对应的处理线程(池)是Exector。
protected class Acceptor extends Thread {
.....
@Override
public void run() {
int errorDelay = 0;
// Loop until we receive a shutdown command
while (running) {
....
try {
//if we have reached max connections, wait
awaitConnection();
long socket = 0;
try {
// Accept the next incoming connection from the server
// socket
socket = Socket.accept(serverSock);
} catch (Exception e) {
// Introduce delay if necessary
errorDelay = handleExceptionWithDelay(errorDelay);
// re-throw
throw e;
}
// Successful accept, reset the error delay
errorDelay = 0;
//increment socket count
countUpConnection();
.....
} catch (Throwable t) {
....
}
}
// The processor will recycle itself when it finishes
}
}
}
protected class AsyncTimeout implements Runnable {
@Override
public void run() {
// Loop until we receive a shutdown command
while (running) {
....
long now = System.currentTimeMillis();
Iterator<SocketWrapper<Long>> sockets =
waitingRequests.iterator();
while (sockets.hasNext()) {
SocketWrapper<Long> socket = sockets.next();
if (socket.async) {
long access = socket.getLastAccess();
if ((now-access)>socket.getTimeout()) {
processSocketAsync(socket,SocketStatus.TIMEOUT);
}
}
}
.... }
}
}
}
Poller Thread
Poller类主要负责poll传入的socket连接(提供add(),由其他线程传入),如果发现有事件,交给AjpConnectionHandler处理。
public class Poller extends Thread {
............
public void add(long socket) {
synchronized (this) {
// Add socket to the list. Newly added sockets will wait
// at most for pollTime before being polled
if (addCount >= addS.length) {
// Can't do anything: close the socket right away
if (comet) {
processSocket(socket, SocketStatus.ERROR);
} else {
destroySocket(socket);
}
return;
}
addS[addCount] = socket;
addCount++;
this.notify();
}
}
@Override
public void run() {
try {
// Add sockets which are waiting to the poller
if (addCount > 0) {
synchronized (this) {
int successCount = 0;
try {
for (int i = (addCount - 1); i >= 0; i--) {
int rv = Poll.add(serverPollset, addS[i], Poll.APR_POLLIN);
if (rv == Status.APR_SUCCESS) {
successCount++;
} else {
// Can't do anything: close the socket right away
if (comet) {
processSocket(addS[i], SocketStatus.ERROR);
} else {
destroySocket(addS[i]);
}
}
}
} finally {
keepAliveCount += successCount;
addCount = 0;
}
}
}
maintainTime += pollTime;
// Pool for the specified interval
int rv = Poll.poll(serverPollset, pollTime, desc, true);
if (rv > 0) {
keepAliveCount -= rv;
for (int n = 0; n < rv; n++) {
// Check for failed sockets and hand this socket off to a worker
if (((desc[n*2] & Poll.APR_POLLHUP) == Poll.APR_POLLHUP)
|| ((desc[n*2] & Poll.APR_POLLERR) == Poll.APR_POLLERR)
|| (comet && (!processSocket(desc[n*2+1], SocketStatus.OPEN)))
|| (!comet && (!processSocket(desc[n*2+1])))) {
// Close socket and clear pool
if (comet) {
processSocket(desc[n*2+1], SocketStatus.DISCONNECT);
} else {
destroySocket(desc[n*2+1]);
}
continue;
}
}
}
..............
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("endpoint.poll.error"), t);
}
}
synchronized (this) {
this.notifyAll();
}
}
}
Sendfile Thread
用于实现sendfile功能,它的工作流程跟Poller类似,add()中,将文件写入socket中。在run()中用Poll来轮询socket的状态,处理文件写入.
代码略....
初始化和启动
在bind()中完成对socket/SSL(如果要支持的话)等资源的初始化,在startInternal(),启动Poller线程组, Comet Poller线程组(两个都是Poller类),Sendfile线程组,Acceptor线程组和1个运行AsyncTimeout接口的线程组.
分享到:
相关推荐
Tomcat源码Tomcat源码Tomcat源码Tomcat源码Tomcat源码Tomcat源码Tomcat源码
tomcat的源码解析资料,加上tomcat的pdf解析中文版的,tomcat的源码。 挺不错的资源,大家可以学习下。
MyEclipse导入Tomcat源码.wps文档说明 apache-tomcat-6.0.37-src.zip源码
how tomcat work源码及中文翻译
1.tomcat源码文件 2.tomcat程序文件 3.Ant程序文件 4.tomcat源码在eclipse运行,重新编译,重新打包步骤文件 5.一个tomcat源码在eclipse上运行的java工程 作用: 1.用于学习tomcat源码和了解tomcat运行机制 2.学习...
手把手教你搭建Tomcat7源码开发环境,如果有了如下说明还搭建不成功,建议考虑下自己的理解能力,能不能走编码这条路。附近包括Tomcat源码、Tomcat源码开发环境依赖的包、Tomcat的环境编译工具ant 1、建立如下...
Tomcat源码剖析 : 整体架构 层层分析 源码解析 架构分析 (Http服务器功能:Socket通信(TCP/IP)、解析Http报文 Servlet容器功能:有很多Servlet(自带系统级Servlet+自定义Servlet),Servlet处理具体的业务逻辑...
tomcat7源码下载tomcat7源码下载tomcat7源码下载tomcat7源码下载tomcat7源码下载tomcat7源码下载tomcat7源码下载tomcat7源码下载
tomcat 源码分析系列文档 http深入分析,tomcat中类的加载,tomcat的启动,tomcat的容器思想,
tomcat源码导入myeclipse,里面包括所支持的jar文件与详细的导入说明
tomcat的源码包
tomcat 源码tomcat 源码tomcat 源码tomcat 源码tomcat 源码tomcat 源码tomcat 源码tomcat 源码tomcat 源码tomcat 源码tomcat 源码tomcat 源码tomcat 源码tomcat 源码tomcat 源码
tomcat源码解析
tomcat源码研读笔记涉及到了tomcat的版本,笔记是基于这个版本的tomcat源码进行研读并写下的笔记
tomcat7的源码项目,可以导入到eclipse,自己编译运行tomcat。
Tomcat源码研究.pdf
Tomcat源码解析.pdf
编译运行tomcat源码需要的jar包,junit在Eclipse中本来就有,就不提供了。另外ecj-4.3.1.jar就是Eclipse的JDT插件:org.eclipse.jdt.core_3.3.1.v_780_R33x.jar。将jar添加到eclipse中并增加到build path就可以运行...