07-tomcat处理请求
在上一章06-tomcat的容器启动过程中,我们知道了处理请求的逻辑在Accptor里面。本章我们直接从这里往后描述。
1. JIoEndpoint.processSocket()
protected boolean processSocket(Socket socket) {
try {
SocketWrapper<Socket> wrapper = new SocketWrapper<Socket>(socket);
wrapper.setKeepAliveLeft(getMaxKeepAliveRequests());
wrapper.setSecure(isSSLEnabled());
if (!running) {
return false;
}
getExecutor().execute(new SocketProcessor(wrapper));
} catch (RejectedExecutionException x) {
return false;
} catch (Throwable t) {
return false;
}
return true;
}
getExecutor()在上一章中讲过是创建了一个默认200最大线程数的线程池,tomcat使用自己的TaskQueue“修复”了线程池的无界队列最大线程池无效的“bug”,具体可以自行百度。
所以这里是开启了一个SocketProcessor线程继续执行请求。从而实现并发处理请求的业务。
2. SocketProcessor.run()
public void run() {
boolean launch = false;
synchronized (socket) {
try {
SocketState state = SocketState.OPEN;
try {
serverSocketFactory.handshake(socket.getSocket()); //在我们当前逻辑中是DefaultServerSocketFactory.handshake(),这里是一个空实现
} catch (Throwable t) {
}
if ((state != SocketState.CLOSED)) {
if (status == null) { //因为我们是从一个参数的构造进入SocketProcessor,所以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) {
}
} 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 {
}
socket = null;
// Finish up this request
}
2.1. AbstractProtocol.process()
public SocketState process(SocketWrapper<S> wrapper,
SocketStatus status) {
S socket = wrapper.getSocket();
Processor<S> processor = connections.get(socket);
wrapper.setAsync(false);
try {
if (processor == null) {
processor = recycledProcessors.poll();
}
if (processor == null) {
processor = createProcessor(); //创建一个Http11Processor
}
initSsl(wrapper, processor); //未用到ssl,暂不关注
SocketState state = SocketState.CLOSED;
do {
if (status == SocketStatus.DISCONNECT &&
!processor.isComet()) {
} else if (processor.isAsync() ||
state == SocketState.ASYNC_END) {
state = processor.asyncDispatch(status);
} else if (processor.isComet()) {
state = processor.event(status);
} else if (processor.getUpgradeInbound() != null) {
state = processor.upgradeDispatch();
} else if (processor.isUpgrade()) {
state = processor.upgradeDispatch(status);
} else { //上面createProcessor的processor没有设置条件中的值,故直接走的这里
state = processor.process(wrapper);
}
if (state != SocketState.CLOSED && processor.isAsync()) {
state = processor.asyncPostProcess();
}
if (state == SocketState.UPGRADING) {
HttpUpgradeHandler httpUpgradeHandler =
processor.getHttpUpgradeHandler();
release(wrapper, processor, false, false);
processor = createUpgradeProcessor(
wrapper, httpUpgradeHandler);
wrapper.setUpgraded(true);
connections.put(socket, processor);
httpUpgradeHandler.init((WebConnection) processor);
} else if (state == SocketState.UPGRADING_TOMCAT) {
org.apache.coyote.http11.upgrade.UpgradeInbound inbound =
processor.getUpgradeInbound();
release(wrapper, processor, false, false);
processor = createUpgradeProcessor(wrapper, inbound);
inbound.onUpgradeComplete();
}
state == SocketState.UPGRADING ||
state == SocketState.UPGRADING_TOMCAT);
if (state == SocketState.LONG) {
connections.put(socket, processor);
longPoll(wrapper, processor);
} else if (state == SocketState.OPEN) {
connections.remove(socket);
release(wrapper, processor, false, true);
} else if (state == SocketState.SENDFILE) {
connections.remove(socket);
release(wrapper, processor, false, false);
} else if (state == SocketState.UPGRADED) {
connections.put(socket, processor);
if (status != SocketStatus.OPEN_WRITE) {
longPoll(wrapper, processor);
}
} else {
connections.remove(socket);
if (processor.isUpgrade()) {
processor.getHttpUpgradeHandler().destroy();
} else if (processor instanceof org.apache.coyote.http11.upgrade.UpgradeProcessor) {
} else {
release(wrapper, processor, true, false);
}
}
return state;
} catch(java.net.SocketException e) {
} catch (java.io.IOException e) {
} catch (Throwable e) {
}
connections.remove(socket);
if (!(processor instanceof org.apache.coyote.http11.upgrade.UpgradeProcessor)
&& !processor.isUpgrade()) {
release(wrapper, processor, true, false);
}
return SocketState.CLOSED;
}
2.2 AbstractHttp11Processor.process()
public SocketState process(SocketWrapper<S> socketWrapper)
throws IOException {
RequestInfo rp = request.getRequestProcessor();
rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
setSocketWrapper(socketWrapper);
//input和output都在Http11Processor的构造里面创建的
getInputBuffer().init(socketWrapper, endpoint); //把socket的inputStream赋值给processor
getOutputBuffer().init(socketWrapper, endpoint);//把socket的outputStream赋值给processor
error = false;
keepAlive = true;
comet = false;
openSocket = false;
sendfileInProgress = false;
readComplete = true;
if (endpoint.getUsePolling()) { //JIoEndpoint不支持,直接返回false
keptAlive = false;
} else {
keptAlive = socketWrapper.isKeptAlive(); //默认false
}
if (disableKeepAlive()) { //如果当前请求数,也就是当前线程池活跃线程除以最大线程*100大于默认75,返回true。 最大线程之前讲过默认为200。所以就是大于同时150个请求。
socketWrapper.setKeepAliveLeft(0);
}
while (!error && keepAlive && !comet && !isAsync() &&
upgradeInbound == null &&
httpUpgradeHandler == null && !endpoint.isPaused()) {
try {
setRequestLineReadTimeout(); //调整超时时间
if (endpoint.isPaused()) {
response.setStatus(503);
error = true;
} else {
if (request.getStartTime() < 0) {
request.setStartTime(System.currentTimeMillis());
}
keptAlive = true;
// Set this every time in case limit has been changed via JMX
request.getMimeHeaders().setLimit(endpoint.getMaxHeaderCount());
// Currently only NIO will ever return false here
if (!getInputBuffer().parseHeaders()) { //解析请求头
openSocket = true;
readComplete = false;
break;
}
}
} catch (IOException e) {
break;
} catch (Throwable t) {
}
if (!error) {
// Setting up filters, and parse some request headers
rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
try {
prepareRequest(); //预处理请求。
} catch (Throwable t) {
}
}
if (maxKeepAliveRequests == 1) {
keepAlive = false;
} else if (maxKeepAliveRequests > 0 &&
socketWrapper.decrementKeepAlive() <= 0) {
keepAlive = false;
}
// Process the request in the adapter
if (!error) {
try {
rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
adapter.service(request, response); //开始处理请求
if(keepAlive && !error) { // Avoid checking twice.
error = response.getErrorException() != null ||
(!isAsync() &&
statusDropsConnection(response.getStatus()));
}
setCometTimeouts(socketWrapper);
} catch (InterruptedIOException e) {
} catch (HeadersTooLargeException e) {
} catch (Throwable t) {
}
}
// Finish the handling of the request
rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
if (!isAsync() && !comet) {
if (error) {
getInputBuffer().setSwallowInput(false);
}
if (response.getStatus() < 200 || response.getStatus() > 299) {
if (expectation) {
getInputBuffer().setSwallowInput(false);
keepAlive = false;
}
}
endRequest();
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
if (error) {
response.setStatus(500);
}
request.updateCounters();
if (!isAsync() && !comet || error) {
getInputBuffer().nextRequest();
getOutputBuffer().nextRequest();
}
if (!disableUploadTimeout) {
if(endpoint.getSoTimeout() > 0) {
setSocketTimeout(endpoint.getSoTimeout());
} else {
setSocketTimeout(0);
}
}
rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
if (breakKeepAliveLoop(socketWrapper)) {
break;
}
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
if (error || endpoint.isPaused()) {
return SocketState.CLOSED;
} else if (isAsync() || comet) {
return SocketState.LONG;
} else if (isUpgrade()) {
return SocketState.UPGRADING;
} else if (getUpgradeInbound() != null) {
return SocketState.UPGRADING_TOMCAT;
} else {
if (sendfileInProgress) {
return SocketState.SENDFILE;
} else {
if (openSocket) {
if (readComplete) {
return SocketState.OPEN;
} else {
return SocketState.LONG;
}
} else {
return SocketState.CLOSED;
}
}
}
}
request和response是在new Http11Processor的时候在其父类的AbstractProcessor的构造方法中初始化的。如下:
public AbstractProcessor(AbstractEndpoint endpoint) {
this.endpoint = endpoint;
asyncStateMachine = new AsyncStateMachine<S>(this);
request = new Request();
response = new Response();
response.setHook(this);
request.setResponse(response);
}
CoyoteAdapter.service()处理请求如下:
public void service(org.apache.coyote.Request req,
org.apache.coyote.Response res)
throws Exception {
Request request = (Request) req.getNote(ADAPTER_NOTES); //这就是httpservletRequest
Response response = (Response) res.getNote(ADAPTER_NOTES);
boolean comet = false;
boolean async = false;
try {
req.getRequestProcessor().setWorkerThreadName(Thread.currentThread().getName());
//解析请求参数,cookie,session等等请求信息。
boolean postParseSuccess = postParseRequest(req, request, res, response);
if (postParseSuccess) {
request.setAsyncSupported(connector.getService().getContainer().getPipeline().isAsyncSupported());
connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
//真正处理请求的地方
}
} catch (IOException e) {
} finally {
}
}
上面处理请求的地方,根据debug最终调用到StandardWrapperValue.invoke()里面。
public final void invoke(Request request, Response response)
throws IOException, ServletException {
Servlet servlet = null;
try {
if (!unavailable) {
servlet = wrapper.allocate(); //获取StandardWrapper的servlet对象,springmvc就是dispatcherServlet
}
} catch (UnavailableException e) {
} catch (ServletException e) {
} catch (Throwable e) {
}
ApplicationFilterFactory factory =
ApplicationFilterFactory.getInstance();
ApplicationFilterChain filterChain =
factory.createFilterChain(request, wrapper, servlet); //创建一个包装servlet的filterChain。
try {
if ((servlet != null) && (filterChain != null)) {
if (context.getSwallowOutput()) {
} else {
if (request.isAsyncDispatching()) {
} else if (comet) {
} else {
filterChain.doFilter
(request.getRequest(), response.getResponse()); //调用filter和servlet。
}
}
}
} catch (ClientAbortException e) {
} catch (IOException e) {
} catch (UnavailableException e) {
} catch (ServletException e) {
} catch (Throwable e) {
}
if (filterChain != null) {
if (request.isComet()) {
filterChain.reuse();
} else {
filterChain.release();
}
}
try {
if (servlet != null) {
wrapper.deallocate(servlet);
}
} catch (Throwable e) {
}
}
ApplicationFilterChain.doFilter() ==》 internalDoFilter()
private void internalDoFilter(ServletRequest request,
ServletResponse response)
throws IOException, ServletException {
if (pos < n) {
ApplicationFilterConfig filterConfig = filters[pos++];
Filter filter = null;
try {
filter = filterConfig.getFilter();
if( Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
Principal principal =
((HttpServletRequest) req).getUserPrincipal();
Object[] args = new Object[]{req, res, this};
SecurityUtil.doAsPrivilege
("doFilter", filter, classType, args, principal);
} else {
filter.doFilter(request, response, this); //调用filter。filter中chain.doFilter()在继续递归调用
}
} catch (IOException e) {
} catch (ServletException e) {
} catch (RuntimeException e) {
} catch (Throwable e) {
}
return;
}
// We fell off the end of the chain -- call the servlet instance
try {
if ((request instanceof HttpServletRequest) &&
(response instanceof HttpServletResponse)) {
if( Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
Principal principal =
((HttpServletRequest) req).getUserPrincipal();
Object[] args = new Object[]{req, res};
SecurityUtil.doAsPrivilege("service",
servlet,
classTypeUsedInService,
args,
principal);
} else {
servlet.service(request, response); //最后一个filter走完,不会进入上面的filter的if语句了,就会走到这里。调用我们熟悉的Servlet.service()方法,也就是把请求传达到我们的servlet了。
}
} else {
servlet.service(request, response);
}
} catch (IOException e) {
} catch (ServletException e) {
} catch (RuntimeException e) {
} catch (Throwable e) {
} finally {
}
}
至此,一个完整的http请求到servlet的过程就已完成了。
总结:
处理请求过程就是在解析和封装socket的输入输出流。
默认最大有200个线程处理请求,最大连接数默认等于最大线程数。
filter的调用是通过递归实现的,所以如果我们在doFilter里面不放行,也就是手动调用chain.doFilter()的话,就不会继续执行后面的filter,也就不能跳出filter的位置那个if判断直接return掉前面所有,所以就不能在执行servlet.service()方法,也就是调用到我们的servlet。
之前讲过endpoint的属性基本都可以通过Connector节点指定,所以我们也可以定义自己想要的最大处理请求线程,最大连接数等等,比如:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" maxThreads="300" maxConnections="250"
acceptorThreadCount="3"/>