在上一篇文章中,我们知道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();//处理不了则关闭socketcloseSocket(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 NPEif (!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 handshakeserverSocketFactory.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);}}//处理过程中状态被设置为关闭则直接关闭socketif (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 {//真正的处理SSLinitSsl(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 {//获取IOsetSocketWrapper(socketWrapper);getInputBuffer().init(socketWrapper, endpoint);getOutputBuffer().init(socketWrapper, endpoint);//基本请求参数设值,keepAlive默认是truekeepAlive = 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 {//从请求中获取对应的HostHost host = request.getHost();//调用Host的Valvehost.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的Valvecontext.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容器获取或创建一个Servletservlet = 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容器对应一个单例的Servletif (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方法中,此方法也是给用户实现处理请求的最终方法。
时序图: