在上一篇文章中,我们知道Tomcat在启动后,会在Connector中开启一个Acceptor(接收器)绑定线程然后用于监听socket的连接,那么当我们发出请求时,第一步也就是建立TCP连接,则会从Acceptor的run方法处进入。
Acceptor:
public void run() {
int errorDelay = 0;
//只有运行状态才进入while循环
while (running) {
while (paused && running) {
state = AcceptorState.PAUSED;
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// Ignore
}
}
if (!running) {
break;
}
state = AcceptorState.RUNNING;
try {
countUpOrAwaitConnection();
Socket socket = null;
try {
//阻塞接受TCP连接
socket = serverSocketFactory.acceptSocket(serverSocket);
} catch (IOException ioe) {
//...省略
}
errorDelay = 0;
//设置socket参数
if (running && !paused && setSocketOptions(socket)) {
//处理该socket(关键)
if (!processSocket(socket)) {
countDownConnection();
//处理不了则关闭socket
closeSocket(socket);
}
} else {
countDownConnection();
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;
}
protected boolean processSocket(Socket socket) {
try {
SocketWrapper<Socket> wrapper = new SocketWrapper<Socket>(socket);
wrapper.setKeepAliveLeft(getMaxKeepAliveRequests());
wrapper.setSecure(isSSLEnabled());
// During shutdown, executor may be null - avoid NPE
if (!running) {
return false;
}
//包装成一个socket执行器然后丢入线程池中处理(服务器是一对多的,所以不能阻塞TCP接收线程,必须异步处理)
getExecutor().execute(new SocketProcessor(wrapper));
} catch (RejectedExecutionException x) {
log.warn("Socket processing request was rejected for:"+socket,x);
return false;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("endpoint.process.fail"), t);
return false;
}
return true;
}
在Acceptor的run方法中进行while循环,然后阻塞接受一个TCP的连接,设置一些参数后包装成一个SocketProcessor丢入线程池中异步执行(因为服务器是一对多的,不能阻塞当前的接收TCP连接)。
SocketProcessor:
public void run() {
boolean launch = false;
synchronized (socket) {
try {
SocketState state = SocketState.OPEN;
try {
//SSL的预处理
// SSL handshake
serverSocketFactory.handshake(socket.getSocket());
} catch (Throwable t) {
//省略
}
if ((state != SocketState.CLOSED)) {
if (status == null) {
//交给对应的协议处理器去处理,因为Tomcat还支持AJP协议
state = handler.process(socket, SocketStatus.OPEN_READ);
} else {
state = handler.process(socket,status);
}
}
//处理过程中状态被设置为关闭则直接关闭socket
if (state == SocketState.CLOSED) {
countDownConnection();
try {
socket.getSocket().close();
} catch (IOException e) {
// Ignore
}
}
//...省略
} finally {
if (launch) {
//如果不能处理,则兜底关闭连接
handler.process(socket, SocketStatus.DISCONNECT);
}
}
}
Http11ConnectionHandler:
public SocketState process(SocketWrapper<S> wrapper,
SocketStatus status) {
//拿到对应的socket(因为Tomcat支持NIO、JIO、APR三种运行模式,所以需要用泛型)
S socket = wrapper.getSocket();
if (socket == null) {
// Nothing to do. Socket has been closed.
return SocketState.CLOSED;
}
//拿到最终的协议处理器
Processor<S> processor = connections.get(socket);
if (status == SocketStatus.DISCONNECT && processor == null) {
return SocketState.CLOSED;
}
//...省略
try {
//真正的处理SSL
initSsl(wrapper, processor);
SocketState state = SocketState.CLOSED;
do {
if (status == SocketStatus.CLOSE_NOW) {
processor.errorDispatch();
state = SocketState.CLOSED;
//...省略
} else {
//此处根据状态最终调用处理
state = processor.process(wrapper);
}
}
//...省略
}
}
Http11Processor:
public SocketState process(SocketWrapper<S> socketWrapper)
throws IOException {
//获取IO
setSocketWrapper(socketWrapper);
getInputBuffer().init(socketWrapper, endpoint);
getOutputBuffer().init(socketWrapper, endpoint);
//基本请求参数设值,keepAlive默认是true
keepAlive = true;
comet = false;
openSocket = false;
sendfileInProgress = false;
readComplete = true;
try {
setRequestLineReadTimeout();
//解析请求行 HTTP协议三部分(请求首行、请求头、请求体,其中请求体一般是用户自己使用时解析)
if (!getInputBuffer().parseRequestLine(keptAlive)) {
if (handleIncompleteRequestLineRead()) {
break;
}
}
//读取请求头(只是把请求头解析成Map形式,并没有根据里面的值做一些处理,也就是初步解析)
if (!getInputBuffer().parseHeaders()) {
openSocket = true;
readComplete = false;
break;
}
if (!getErrorState().isError()) {
try {
//真正的解析请求头,解析请求头每个Key里面的value,常用的则校验数据格式等
prepareRequest();
} catch (Throwable t) {
//...省略
}
}
//如果没有错误,则继续处理
if (!getErrorState().isError()) {
try {
rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
//调用适配器转交给最顶级容器(Engine)处理(关键)
adapter.service(request, response);
if(keepAlive && !getErrorState().isError() && (
response.getErrorException() != null ||
(!isAsync() &&
statusDropsConnection(response.getStatus())))) {
setErrorState(ErrorState.CLOSE_CLEAN, null);
}
setCometTimeouts(socketWrapper);
} catch (InterruptedIOException e) {
setErrorState(ErrorState.CLOSE_NOW, e);
} catch (HeadersTooLargeException e) {
if (response.isCommitted()) {
setErrorState(ErrorState.CLOSE_NOW, e);
} else {
}
} catch (Throwable t) {
//...省略
}
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
if (!isAsync() && !comet) {
if (getErrorState().isError()) {
getInputBuffer().setSwallowInput(false);
} else {
checkExpectationAndResponseStatus();
}
//结束一个请求
endRequest();
}
//设置状态和一些响应信息
rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
if (getErrorState().isError()) {
response.setStatus(500);
}
request.updateCounters();
if (!isAsync() && !comet || getErrorState().isError()) {
if (getErrorState().isIoAllowed()) {
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;
}
}
//...省略
}
Adapter:
public void service(org.apache.coyote.Request req,
org.apache.coyote.Response res)
throws Exception {
//解析其它的HTTP参数,如?param=value(查询参数)、session和cookie处理、根据URL找到对应的Host和Contxt、Wrapper容器(因为要符合Servlet规范,很多参数都需要Tomcat为用户解析好)
boolean postParseSuccess = postParseRequest(req, request, res, response);
//真正转发给容器处理
connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
}
在SocketProcessor的run方法中,异步的进行解析,用对应的协议处理器处理,然后开始解析请求首行,请求头,等到解析完成并且没有错误时,则通过Adapter(适配器)的service方法,将请求传递给容器(Engine、Host、Context、Wrapper)。
在组件介绍的文章中,我们知道Engine、Host、Context、Wrapper都属于容器Container,有共同的特性,如一样的生命周期、都有Pipeline(管道)、管道中都存在Valve(阀)。
在Adapter的service方法中,获取的是Engine中Pipeline的第一个Valve去处理。
Pipeline中有两种Valve,一种是普通Valve,一种是基础Valve。普通Valve也就是用户自定义添加使用的,而基础Vavle是用于当前容器兜底和传递给下一个容器使用的,所以在Adapter中传递下去的Request和Response最终要从上至下经过一个个的容器中的Vavle处理。
StandardEngineValve:
public final void invoke(Request request, Response response)
throws IOException, ServletException {
//从请求中获取对应的Host
Host host = request.getHost();
//调用Host的Valve
host.getPipeline().getFirst().invoke(request, response);
}
StandardHostValve:
public final void invoke(Request request, Response response)
throws IOException, ServletException {
Context context = request.getContext();
if( context.getLoader() != null ) {
//此处为当前线程设置应用的类加载器,从而实现应用之间class隔离(重点)
Thread.currentThread().setContextClassLoader
(context.getLoader().getClassLoader());
}
//...省略
//调用Context的Valve
context.getPipeline().getFirst().invoke(request, response);
}
StandardContextValve:
public final void invoke(Request request, Response response)
throws IOException, ServletException {
//确认请求
response.sendAcknowledgement();
//...省略
//传递到最后一个Wrapper容器中处理
wrapper.getPipeline().getFirst().invoke(request, response);
}
StandardWrapperValve:
public final void invoke(Request request, Response response)
throws IOException, ServletException {
boolean unavailable = false;
StandardWrapper wrapper = (StandardWrapper) getContainer();
Servlet servlet = null;
Context context = (Context) wrapper.getParent();
if (!unavailable) {
//通过Wrapper容器获取或创建一个Servlet
servlet = wrapper.allocate();
}
//...省略
//根据请求信息创建一条过滤器链
ApplicationFilterFactory factory =
ApplicationFilterFactory.getInstance();
ApplicationFilterChain filterChain =
factory.createFilterChain(request, wrapper, servlet);
try {
//调用过滤器链处理请求,这就是我们经常配置的Filter过滤器
filterChain.doFilter(request.getRequest(), response.getResponse());
} catch (Throwable e) {
//异常处理
exception(request, response, e);
}
}
StandardWrapper:
public Servlet allocate() throws ServletException {
if (!singleThreadModel) {
//此处可以看到使用的是双重校验加锁的单例模式,所以Wrapper容器其实就是Servlet的包装,一个Wrapper容器对应一个单例的Servlet
if (instance == null) {
synchronized (this) {
if (instance == null) {
//通过反射创建自定义的Servlet对象
instance = loadServlet();
if (!singleThreadModel) {
newInstance = true;
countAllocated.incrementAndGet();
}
}
}
}
//如果没有初始化则初始化
if (!instanceInitialized) {
initServlet(instance);
}
}
private synchronized void initServlet(Servlet servlet)
throws ServletException {
//初始化调用Servlet的init方法
servlet.init(facade);
}
ApplicationFilterChain:
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
internalDoFilter(request,response);
}
private void internalDoFilter(ServletRequest request,
ServletResponse response)
throws IOException, ServletException {
ApplicationFilterConfig filterConfig = filters[pos++];
Filter filter = null;
try {
filter = filterConfig.getFilter();
//调用过滤器执行
filter.doFilter(request, response, this);
} catch (Throwable e) {
//省略...异常处理
}
if ((request instanceof HttpServletRequest) &&
(response instanceof HttpServletResponse)) {
//最终调用到用户自定义的Servlet的service方法中
servlet.service(request, response);
}
}
Engine把Request通过PipeLine中的Valve传递到最终的Wrapper中,用户可以在这几个容器(Engine、Host、Context、Wrapper)的PipeLine添加普通的Valve进行一些操作。
终于,在Wrapper中,Tomcat通过单例模式创建出用户自定义的Servlet,然后经过过滤器链的处理后,调用到Servlet的service方法中,此方法也是给用户实现处理请求的最终方法。
时序图: