这次主要解析采用apr方式处理请求.apr用C实现,通过JNI调用,主要提升对静态资源(如HTML、图片、CSS、JS等)的访问性能.在tomcat下配置apr步骤:
1.下载本地库tcnative-1.dll,放在%jdk%\bin目录下(见附件).
2.在server.xml里配置listener,这个配置server.xml默认是有的
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
3.在server.xml里配置apr connector
<Connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol" connectionTimeout="20000" redirectPort="8443" />
在tomcat启动的时候,会调用Connector类的Start()方法,根据以上配置,Connector的start()方法里会调用Http11AprProtocol类的start()方法,如下:
try {
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));
}
Http11AprProtocol类的start()方法又会调用AprEndpoint类的start()方法,如下:
try {
endpoint.start();
} catch (Exception ex) {
log.error(sm.getString("http11protocol.endpoint.starterror"), ex);
throw ex;
}
AprEndpoint类的start()方法如下:
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 poller threads
pollers = new Poller[pollerThreadCount];
for (int i = 0; i < pollerThreadCount; i++) {
pollers[i] = new Poller(false);
pollers[i].init();
pollers[i].setName(getName() + "-Poller-" + i);
pollers[i].setPriority(threadPriority);
pollers[i].setDaemon(true);
pollers[i].start();
}
// Start comet poller threads
cometPollers = new Poller[pollerThreadCount];
for (int i = 0; i < pollerThreadCount; i++) {
cometPollers[i] = new Poller(true);
cometPollers[i].init();
cometPollers[i].setName(getName() + "-CometPoller-" + i);
cometPollers[i].setPriority(threadPriority);
cometPollers[i].setDaemon(true);
cometPollers[i].start();
}
// Start sendfile threads
if (useSendfile) {
sendfiles = new Sendfile[sendfileThreadCount];
for (int i = 0; i < sendfileThreadCount; i++) {
sendfiles[i] = new Sendfile();
sendfiles[i].init();
sendfiles[i].setName(getName() + "-Sendfile-" + i);
sendfiles[i].setPriority(threadPriority);
sendfiles[i].setDaemon(true);
sendfiles[i].start();
}
}
// Start acceptor threads
acceptors = new Acceptor[acceptorThreadCount];
for (int i = 0; i < acceptorThreadCount; i++) {
acceptors[i] = new Acceptor();
acceptors[i].setName(getName() + "-Acceptor-" + i);
acceptors[i].setPriority(threadPriority);
acceptors[i].setDaemon(getDaemon());
acceptors[i].start();
}
}
}
该方法主要初始化接受socket的线程和处理socket的线程池.Acceptor的run()方法如下:
public void run() {
// Loop until we receive a shutdown command
while (running) {
// Loop if endpoint is paused
while (paused && running) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// Ignore
}
}
if (!running) {
break;
}
try {
// Accept the next incoming connection from the server socket
long socket = Socket.accept(serverSock);
/*
* In the case of a deferred accept unlockAccept needs to
* send data. This data will be rubbish, so destroy the
* socket and don't process it.
*/
if (deferAccept && (paused || !running)) {
destroySocket(socket);
continue;
}
// Hand this socket off to an appropriate processor
if (!processSocketWithOptions(socket)) {//把socket交给woker线程进行转发
// Close socket and pool right away
destroySocket(socket);
}
} catch (Throwable t) {
if (running) {
String msg = sm.getString("endpoint.accept.fail");
if (t instanceof Error) {
Error e = (Error) t;
if (e.getError() == 233) {
// Not an error on HP-UX so log as a warning
// so it can be filtered out on that platform
// See bug 50273
log.warn(msg, t);
} else {
log.error(msg, t);
}
} else {
log.error(msg, t);
}
}
}
}
}
}
Socket.accept(serverSock)方法的Socket类是用JNI实现的不同于java的Socket类,所以 Socket.accept(serverSock)返回的参数是long类型的.processSocketWithOptions(socket)方法如下:
protected boolean processSocketWithOptions(long socket) {
try {
if (executor == null) {
getWorkerThread().assignWithOptions(socket);
} else {
executor.execute(new SocketWithOptionsProcessor(socket));
}
} catch (Throwable 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;
}
再来看一下woker线程的run方法():
public void run() {
// Process requests until we receive a shutdown signal
while (running) {
// Wait for the next socket to be assigned
long socket = await();
if (socket == 0)
continue;
if (!deferAccept && options) {
if (setSocketOptions(socket)) {
getPoller().add(socket);//将sokcet交给poller转发.poller最终会把socket交给worker处理不知道为什么这么做
} else {
// Close socket and pool
destroySocket(socket);
socket = 0;
}
} else {
// Process the request from this socket
if ((status != null) && (handler.event(socket, status) == Handler.SocketState.CLOSED)) {
// Close socket and pool
destroySocket(socket);
socket = 0;
} else if ((status == null) && ((options && !setSocketOptions(socket))
|| handler.process(socket) == Handler.SocketState.CLOSED)) {//Http11AprProtocol.Http11ConnectionHandler.process(socket)处理socket
// Close socket and pool
destroySocket(socket);
socket = 0;
}
}
// Finish up this request
recycleWorkerThread(this);
}
}
可以看到,woker的run()方法做了两件事.1.把socket交给poller.2.直接调用处理 Http11AprProtocol.Http11ConnectionHandler.process(socket)处理socket
handler.process(socket)方法如下:
public SocketState process(long socket) {
Http11AprProcessor processor = recycledProcessors.poll();
try {
if (processor == null) {
processor = createProcessor();
}
if (processor instanceof ActionHook) {
((ActionHook) processor).action(ActionCode.ACTION_START, null);
}
SocketState state = processor.process(socket);//真正的解析http请求的方法
if (state == SocketState.LONG) {//如果是长连接再放回线程池处理
// Associate the connection with the processor. The next request
// processed by this thread will use either a new or a recycled
// processor.
connections.put(socket, processor);
proto.endpoint.getCometPoller().add(socket);
} else {
recycledProcessors.offer(processor);
}
return state;
} catch (java.net.SocketException e) {
// SocketExceptions are normal
Http11AprProtocol.log.debug
(sm.getString
("http11protocol.proto.socketexception.debug"), e);
} catch (java.io.IOException e) {
// IOExceptions are normal
Http11AprProtocol.log.debug
(sm.getString
("http11protocol.proto.ioexception.debug"), e);
}
// Future developers: if you discover any other
// rare-but-nonfatal exceptions, catch them here, and log as
// above.
catch (Throwable e) {
// any other exception or error is odd. Here we log it
// with "ERROR" level, so it will show up even on
// less-than-verbose logs.
Http11AprProtocol.log.error
(sm.getString("http11protocol.proto.error"), e);
}
recycledProcessors.offer(processor);
return SocketState.CLOSED;
}
processor.process(socket)调用的是Http11AprProcessor类的process(long socket) 方法,用http协议对http请求进行解析