请求处理流程
-
-
- 请求流程
-
- 源码跟踪
-
- 源码入口
-
- 执行AbstractEndpoint.processSocket
- 执行SocketWrapperBase.run
- 执行AbstractProtocol.process
- 执行AbstractProcessorLight.process
- 执行Http11Processor.service
- 执行CoyoteAdaptor.service
- 执行责任链xxxValve.invoke
- 获取Servlet -- Wrapper.invoke
- 执行过滤器链中的filter
- 执行HttpServlet.service
- Http长连接的支持
请求流程
Mapper组件
- mapper组件将用户请求URL定位到具体的Servlet
工作原理(同SpringMVC)
- mapper组件中保存了Web应用的配置信息,即容器组件与访问路径的映射关系
- 映射关系,如多层次的Map:
○ Host容器中配置域名
○ Context容器的web应用路径
○ Wrapper容器里的Servlet映射的路径
- 当一个请求进来时
○ Mapper组件会解析请求的URL的域名和路径
○ 到自己的映射关系Map中查找Wrapper,定位到唯一的Servlet
具体流程
请求连接和协议解析
- Connector组件的Endpoint中的Acceptor监听客户端套接字连接并接收Socket
- 将连接交给线程池Exectuor处理,开始执行请求响应任务
- Processor组件读取到消息报文,解析请求行、请求头、请求体,封装成Request对象
请求路由和处理
- Mapper组件根据请求行的URL值和请求头的Host值匹配由那个host、context、wrapper容器进行处理
- CoyoteAdaptor组件负责将Connector组件和Engine容器适配关联,把生成的Request对象和响应的Response对象传递给Engine容器,并调用Pipeline
- Engine容器的管道开始处理,管道中包含若干个Valve,每个Valve负责部分处理逻辑,执行完Valve后会执行基础的Valve – StandardEngineValve,负责调用Host容器的Pipeline
- Host容器的管道开始同上流程处理,最后执行Content容器的Pipeline
- Content容器的管道开始同上流程处理,最后执行Wrapper容器的Pipeline
- Wrapper容器的管道开始同上流程处理
- 最后执行Wrapper容器对应的Servlet对象的处理方法
源码跟踪
请求流程图
请求时序图
源码入口
- org.apache.tomcat.util.net.NioEndpoint#startInternal (启动完成,接收请求)
- org.apache.tomcat.util.net.NioEndpoint.Poller#run (处理接收的请求)
- org.apache.tomcat.util.net.NioEndpoint.Poller#processKey
- org.apache.tomcat.util.net.AbstractEndpoint#processSocket
执行AbstractEndpoint.processSocket
- org.apache.tomcat.util.net.AbstractEndpoint#processSocket
- 由Executor线程池执行业务SocketWrapperBase.run
- Connector组件的Endpoint中的Acceptor监听客户端套接字连接并接收Socket
public boolean processSocket(SocketWrapperBase<S> socketWrapper,
SocketEvent event, boolean dispatch) {
Executor executor = getExecutor();
if (dispatch && executor != null) {
executor.execute(sc);
} else {
sc.run();
}
}
执行SocketWrapperBase.run
- org.apache.tomcat.util.net.SocketProcessorBase#run
- 调用doRun方法
○ 执行3次握手
○ 获取handler并进行请求处理
- 将连接交给线程池Exectuor处理,开始执行请求响应任务
public final void run() {
synchronized (socketWrapper) {
doRun();
}
}
protected void doRun() {
Poller poller = NioEndpoint.this.poller;
if (poller == null) {
socketWrapper.close();
return;
}
int handshake = -1;
if (handshake == 0) {
SocketState state = SocketState.OPEN;
if (event == null) {
state = getHandler().process(socketWrapper, SocketEvent.OPEN_READ);
} else {
state = getHandler().process(socketWrapper, event);
}
if (state == SocketState.CLOSED) {
poller.cancelledKey(getSelectionKey(), socketWrapper);
}
}
}
执行AbstractProtocol.process
- 获取当前Processor
- 调用processor的process方法(在此Endpoint将请求的信息交给Processor)
- Processor组件读取到消息报文,解析请求行、请求头、请求体,封装成Request对象
public SocketState process(SocketWrapperBase<S> wrapper, SocketEvent status) {
S socket = wrapper.getSocket();
Processor processor = (Processor) wrapper.getCurrentProcessor();
SocketState state = SocketState.CLOSED;
state = processor.process(wrapper, status);
}
执行AbstractProcessorLight.process
public SocketState process(SocketWrapperBase<?> socketWrapper, SocketEvent status) throws IOException {
SocketState state = SocketState.CLOSED;
Iterator<DispatchType> dispatches = null;
do {
if (dispatches != null) {
DispatchType nextDispatch = dispatches.next();
state = dispatch(nextDispatch.getSocketStatus());
if (!dispatches.hasNext()) {
state = checkForPipelinedData(state, socketWrapper);
}
} else if (status == SocketEvent.DISCONNECT) {
} else if (isAsync() || isUpgrade() || state == SocketState.ASYNC_END) {
state = dispatch(status);
state = checkForPipelinedData(state, socketWrapper);
} else if (status == SocketEvent.OPEN_WRITE) {
state = SocketState.LONG;
} else if (status == SocketEvent.OPEN_READ) {
state = service(socketWrapper);
}
} while (state == SocketState.ASYNC_END ||
dispatches != null && state != SocketState.CLOSED);
return state;
}
执行Http11Processor.service
- org.apache.coyote.http11.Http11Processor#service
- 解析请求行、请求头、请求体,封装成Request对象
- 获取adapter(CoyoteAdaptor),调用service方法
- CoyoteAdaptor组件负责将Connector组件和Engine容器适配关联
public SocketState service(SocketWrapperBase<?> socketWrapper) throws IOException {
getAdapter().service(request, response);
}
执行CoyoteAdaptor.service
- 获取到Request和Response对象
- 调用容器,把生成的Request对象和响应的Response对象传递给Engine容器
public void service(org.apache.coyote.Request req, org.apache.coyote.Response res)
throws Exception {
Request request = (Request) req.getNote(ADAPTER_NOTES);
Response response = (Response) res.getNote(ADAPTER_NOTES);
postParseSuccess = postParseRequest(req, request, res, response);
connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
}
执行责任链xxxValve.invoke
- 执行StandardServiceValve.invoke
a. 获取Host,调用Host容器的Pipeline
b. Engine容器的管道开始处理,管道中包含若干个Valve,每个Valve负责部分处理逻辑,执行完Valve后会执行基础的Valve
- 执行StandardHostValve.invoke
a. 获取Context,调用Context容器的Pipeline
- 执行StandardContextValve.invoke
a. 获取Wrapper,调用Wrapper容器的Pipeline
获取Servlet – Wrapper.invoke
- 从Container中获取Wrapper
- 从Wrapper中获取到Servlet,至此拿到的就是具体业务Servlet
- 将Servlet封装到构造的FilterChain过滤器链中
- 执行过滤器链中的filter,并传入ServletRequest和ServletResponse
public final void invoke(Request request, Response response) throws IOException, ServletException {
StandardWrapper wrapper = (StandardWrapper) getContainer();
Servlet servlet = null;
Context context = (Context) wrapper.getParent();
servlet = wrapper.allocate();
ApplicationFilterChain filterChain = ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
filterChain.doFilter(request.getRequest(),response.getResponse());
}
执行过滤器链中的filter
- 获取到ServletRequest、ServletResponse执行过滤器
- 调用servlet.service方法
- 调用HttpServlet.service
○ 执行doGet、doPost方法
public void doFilter(ServletRequest request, ServletResponse response){
internalDoFilter(request,response);
}
private void internalDoFilter(ServletRequest request,
ServletResponse response){
servlet.service(request, response);
}
执行HttpServlet.service
- 获取请求方式
- 执行对应的请求方法,如:doPost、doGet等
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String method = req.getMethod();
if (method.equals(METHOD_GET)) {
doGet(req, resp);
} else if (method.equals(METHOD_HEAD)) {
doHead(req, resp);
} else if (method.equals(METHOD_POST)) {
doPost(req, resp);
} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);
} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);
} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp);
} else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp);
}
}
Http长连接的支持
- 客户端请求会携带Connection: keep-alive
- service方法会解析,并使用keepAlive参数记录是否满足长连接条件
- 不满足长连接条件则返回的响应头携带Connection: close,表示关闭连接
- 满足长连接条件则不返回Connection参数
org.apache.coyote.http11.Http11Processor#service
public SocketState service(SocketWrapperBase<?> socketWrapper)
throws IOException {
RequestInfo rp = request.getRequestProcessor();
rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
setSocketWrapper(socketWrapper);
keepAlive = true;
openSocket = false;
readComplete = true;
boolean keptAlive = false;
SendfileState sendfileState = SendfileState.DONE;
while (!getErrorState().isError() && keepAlive && !isAsync() && upgradeToken == null &&
sendfileState == SendfileState.DONE && !protocol.isPaused()) {
try {
if (!inputBuffer.parseRequestLine(keptAlive, protocol.getConnectionTimeout(),
protocol.getKeepAliveTimeout())) {
if (inputBuffer.getParsingRequestLinePhase() == -1) {
return SocketState.UPGRADING;
} else if (handleIncompleteRequestLineRead()) {
break;
}
}
if (protocol.isPaused()) {
response.setStatus(503);
setErrorState(ErrorState.CLOSE_CLEAN, null);
} else {
keptAlive = true;
request.getMimeHeaders().setLimit(protocol.getMaxHeaderCount());
if (!inputBuffer.parseHeaders()) {
openSocket = true;
readComplete = false;
break;
}
if (!protocol.getDisableUploadTimeout()) {
socketWrapper.setReadTimeout(protocol.getConnectionUploadTimeout());
}
}
} catch (IOException e) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("http11processor.header.parse"), e);
}
setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e);
break;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
UserDataHelper.Mode logMode = userDataHelper.getNextMode();
if (logMode != null) {
String message = sm.getString("http11processor.header.parse");
switch (logMode) {
case INFO_THEN_DEBUG:
message += sm.getString("http11processor.fallToDebug");
case INFO:
log.info(message, t);
break;
case DEBUG:
log.debug(message, t);
}
}
response.setStatus(400);
setErrorState(ErrorState.CLOSE_CLEAN, t);
}
Enumeration<String> connectionValues = request.getMimeHeaders().values("Connection");
boolean foundUpgrade = false;
while (connectionValues.hasMoreElements() && !foundUpgrade) {
String connectionValue = connectionValues.nextElement();
if (connectionValue != null) {
foundUpgrade = connectionValue.toLowerCase(Locale.ENGLISH).contains("upgrade");
}
}
if (foundUpgrade) {
String requestedProtocol = request.getHeader("Upgrade");
UpgradeProtocol upgradeProtocol = protocol.getUpgradeProtocol(requestedProtocol);
if (upgradeProtocol != null) {
if (upgradeProtocol.accept(request)) {
response.setStatus(HttpServletResponse.SC_SWITCHING_PROTOCOLS);
response.setHeader("Connection", "Upgrade");
response.setHeader("Upgrade", requestedProtocol);
action(ActionCode.CLOSE, null);
getAdapter().log(request, response, 0);
InternalHttpUpgradeHandler upgradeHandler =
upgradeProtocol.getInternalUpgradeHandler(
socketWrapper, getAdapter(), cloneRequest(request));
UpgradeToken upgradeToken = new UpgradeToken(upgradeHandler, null, null);
action(ActionCode.UPGRADE, upgradeToken);
return SocketState.UPGRADING;
}
}
}
if (getErrorState().isIoAllowed()) {
rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
try {
prepareRequest();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
if (log.isDebugEnabled()) {
log.debug(sm.getString("http11processor.request.prepare"), t);
}
response.setStatus(500);
setErrorState(ErrorState.CLOSE_CLEAN, t);
}
}
int maxKeepAliveRequests = protocol.getMaxKeepAliveRequests();
if (maxKeepAliveRequests == 1) {
keepAlive = false;
} else if (maxKeepAliveRequests > 0 &&
socketWrapper.decrementKeepAlive() <= 0) {
keepAlive = false;
}
if (getErrorState().isIoAllowed()) {
try {
rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
getAdapter().service(request, response);
if(keepAlive && !getErrorState().isError() && !isAsync() &&
statusDropsConnection(response.getStatus())) {
setErrorState(ErrorState.CLOSE_CLEAN, null);
}
} catch (InterruptedIOException e) {
setErrorState(ErrorState.CLOSE_CONNECTION_NOW, e);
} catch (HeadersTooLargeException e) {
log.error(sm.getString("http11processor.request.process"), e);
if (response.isCommitted()) {
setErrorState(ErrorState.CLOSE_NOW, e);
} else {
response.reset();
response.setStatus(500);
setErrorState(ErrorState.CLOSE_CLEAN, e);
response.setHeader("Connection", "close");
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("http11processor.request.process"), t);
response.setStatus(500);
setErrorState(ErrorState.CLOSE_CLEAN, t);
getAdapter().log(request, response, 0);
}
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
if (!isAsync()) {
endRequest();
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
if (getErrorState().isError()) {
response.setStatus(500);
}
if (!isAsync() || getErrorState().isError()) {
request.updateCounters();
if (getErrorState().isIoAllowed()) {
inputBuffer.nextRequest();
outputBuffer.nextRequest();
}
}
if (!protocol.getDisableUploadTimeout()) {
int connectionTimeout = protocol.getConnectionTimeout();
if(connectionTimeout > 0) {
socketWrapper.setReadTimeout(connectionTimeout);
} else {
socketWrapper.setReadTimeout(0);
}
}
rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
sendfileState = processSendfile(socketWrapper);
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
if (getErrorState().isError() || protocol.isPaused()) {
return SocketState.CLOSED;
} else if (isAsync()) {
return SocketState.LONG;
} else if (isUpgrade()) {
return SocketState.UPGRADING;
} else {
if (sendfileState == SendfileState.PENDING) {
return SocketState.SENDFILE;
} else {
if (openSocket) {
if (readComplete) {
return SocketState.OPEN;
} else {
return SocketState.LONG;
}
} else {
return SocketState.CLOSED;
}
}
}
}