Tomcat请求处理一个请求的过程

本文详细介绍了Tomcat处理请求的过程,从Connector组件接收TCP连接,创建Request和Response对象,到通过Adapter解析成HttpServletRequest和HttpServletResponse,再到Container的逐层Valve调用,最后由Servlet处理请求。涉及到的关键组件包括Acceptor、SocketProcessor、Http11ConnectionHandler、AbstractHttp11Processor和StandardWrapperValve。整个流程确保了请求从网络层到应用层的顺利传递。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Connector组件是Tomcat两个核心组件之一(另一个是Container),主要任务是负责接收客户端发过来的TCP连接请求,创建一个Request和Response对象用于和请求端交换数据。

Tomcat使用Apache Coyote库来处理网络I/O的。

Connector是通过适配器将自己“置入”这个框架中的,具体是org.apache.catalina.connector.CoyoteAdapter。Adapter位于Coyote框架处理请求的末端,解析和得到的org.apache.coyote.Request和org.apache.coyote.Response将会传入Adapter,该对象负责将http request解析成HttpServletRequest对象,之后绑定相应的容器,然后从engine开始逐层调用valve直至该servlet。

Connector负责创建Adapter(CoyoteAdapter)和ProtocolHandler,
ProtocolHandler负责根据具体的协议和I/O模型对请求数据进行接受,解析和处理,然后创建并委托Endpoint进行具体的处理。
Endpoint经过一层处理后将请求传入Processor,最终由Processor将请求传入Adapter进而进入容器。

Tomcat有四种不同的协议可供选择,类型包括BIO,AIO,NIO,APR,接口的具体实现是:

ProtocolHandler——>Http11NioProtocol;
Endpoint——>NioEndpoint;
Processor——Http11NioProcessor;


Request和Response对象的创建:

AbstractProcessor负责创建org.apache.coyote.Request和org.apache.coyote.Response;

CoyoteAdapter调用Connector.createRequset()和createResponse()创建org.apache.catalina.connector.Request和Response这就是实现了我们熟悉的HttpServletRequest和HttpServletResponse接口的贯穿整个容器,Filter&Servlet生命周期的两个对象了。


请求是如何传入容器的最终到达Servlet的:

Acceptor: 负责在一个后台线程中指定端口上接收客户端发送的请求,
SocketProcessor: 根据socket的状态进行第一层处理,另外SSL的握手也是由它负责.
Http11ConnectionHandler: SocketProcessor将会调用handler.process()将socket请求内容传入Processor.process().
AbstractHttp11Processor: AbstractHttp11Processor.process()调用CoyoAdapter.service(),
CoyoAdapter: 调用Service拥有的容器(也就是Engine)对应Pipeline的第一个Valve的invoke方法

这样Request和Response对象就进入容器。每个容器Pipeline上的最后一个Valve负责将Request和Response传入下一个容器(也就是每个容器的第一个Valve)。经过了Pipeline上所有的Valve,最后一个Valve也就是StandardWrapperValve,它的invoke方法将调用FilterChain.doFIlter(),将把设置好的Request和Response对象传入Filter链,这就进入我们熟悉的部分了,最终将被分派的正确的Servlet进行处理。

请求流程图如下:
这里写图片描述


请求流程简述:

  1. 接收到请求的serverSocket会被wrapper包装一下,之后放到线程池里面,由线程池分配一个线程来处理这个请求
  2. Http11Processor解析http的请求,生产并封装request和response对象
  3. 通过connector.getService()调用一系列的invoke(request,response)方法,传递request和response顺着Containter的Pipeline一直到StandardWrapperValve,在StandardWrapperValve中,创建FilterChain并执行,包括我们自己定义的,到我们的应用中,完成响应
//1.
protected class Acceptor extends AbstractEndpoint.Acceptor {
  @Override
  public void run() {
      // Loop until we receive a shutdown command
      while (running) {
      // block线程,等待请求的到来
          socket = serverSocketFactory.acceptSocket(serverSocket); 
          //接受到请求之后处理请求
          if (!processSocket(socket)) {
              closeSocket(socket);
          }               
  }
}

// 调用本类的processSocket方法
//org.apache.tomcat.util.net.JIoEndpoint#processSocket
protected boolean processSocket(Socket socket) {
        // Process the request from this socket
        try {
            // 把socket包装成SocketWrapper
            SocketWrapper<Socket> wrapper = new SocketWrapper<Socket>(socket);
            wrapper.setKeepAliveLeft(getMaxKeepAliveRequests());
            wrapper.setSecure(isSSLEnabled());
            // 从线程池中新起一个线程执行包装类
            getExecutor().execute(new SocketProcessor(wrapper));
        }
        return true;
    }

//2. 
//org.apache.tomcat.util.net.JIoEndpoint.SocketProcessor#run
public void run() {
 if ((state != SocketState.CLOSED)) {
      if (status == null) {
          // AbstractProtocol.AbstractConnectionHandler.process()
          state = handler.process(socket, SocketStatus.OPEN_READ);
      } else {
          state = handler.process(socket,status);
      }
  }
}

1.处Acceptor 为JIoEndpoint的内部类, 该类监听TCP/IP请求,并将请求发送给合适的Processor.
2.处从线程池获取一个线程执行SocketProcessor. SocketProcessor 同样是内部类, 但只被用于线程池中, 当做工作线程使用(Worker), 其run方法总会调用AbstractProtocol.AbstractConnectionHandler.process()方法处理socket.

AbstractProtocol.AbstractConnectionHandler.process()方法,会根据请求的协议类型创建相应的类型处理类,协议类型的来源就是con/server.xml中connector元素的protocol属性值。我们这里配置的是HTTP/1.1,所以类型为Http11Protocol,接着调用其处理器AbstractHttp11Processor的process()方法继续处理包装socket的SocketeWrapper类,处理的目的是生成request和response对象

注意Http11Protocol 的基类是AbstractHttp11Processor, Http11Protocol 初始化的时候会创建一对request和response, 其类型分别为Corg.apache.coyote.Request,org.apache.coyote.Response, 这是最原始的tomcat使用的类,非我们web程序中的类, 构造函数源码如下:

//org.apache.coyote.AbstractProcessor#AbstractProcessor 
//构造函数.
public AbstractProcessor(AbstractEndpoint endpoint) {
   this.endpoint = endpoint;
   asyncStateMachine = new AsyncStateMachine(this);        
   request = new Request();
   response = new Response();
   response.setHook(this);
   request.setResponse(response);
}

具体process请求如下:

//org.apache.coyote.http11.AbstractHttp11Processor#process

public SocketState process(SocketWrapper<Socket> socketWrapper){
    // 这个request和response是通过父类的构造方法new出来的
    RequestInfo rp = request.getRequestProcessor();

    // Setting up the I/O
    setSocketWrapper(socketWrapper);

    // Setting up filters, and parse some request headers,设置request.serverPort等
    prepareRequest();

    // Process the request in the adapter
     adapter.service(request, response);
        endRequest();
        request.updateCounters();
    }

org.apache.catalina.connector.CoyoteAdapter#service 源码如下


    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);

        if (request == null) {

            // Create objects
            request = connector.createRequest();
            request.setCoyoteRequest(req);
            response = connector.createResponse();
            response.setCoyoteResponse(res);

            // Link objects
            request.setResponse(response);
            response.setRequest(request);

            // Set as notes
            req.setNote(ADAPTER_NOTES, request);
            res.setNote(ADAPTER_NOTES, response);

            // Set query string encoding
            req.getParameters().setQueryStringEncoding
                (connector.getURIEncoding());

        }

        if (connector.getXpoweredBy()) {
            response.addHeader("X-Powered-By", POWERED_BY);
        }

        boolean comet = false;
        boolean async = false;

         // 正式将请求转发到Container中. 正式进入Engine管道
         connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
    }

进入管道后的操作见本人博客:
https://blog.youkuaiyun.com/yangsnow_rain_wind/article/details/80053703

附录:
代码的异常栈可以清楚地看到请求的执行逻辑

at com.XXXX.XXXXX.core.security.SecurityAspect.execute(SecurityAspect.java:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:68)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
at com.XXXX.XXXXX.pc.controller.IndexController$$EnhancerBySpringCGLIB$$10cfddca.confirm(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:776)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:108)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:522)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:620)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:1096)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:760)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1480)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)

Notes

  1. Tomcat接收到请求后创建org.apache.coyote.Requestorg.apache.coyote.Resposne,这两个类是轻量级的类,对象很小;这是有Tomcat内部工作线程创建的;
  2. org.apache.coyote.Requestorg.apache.coyote.Resposne传递给用户线程,创建org.apache.catalina.connector.Requestorg.apache.catalina.connector.Resposne,这两个对象一直整个Servlet容器直到要传给Servlet;
  3. 创建门面类RequestFacadeResponseFacade给Servlet;

注: 部分代码引用自:
https://blog.youkuaiyun.com/mingliangniwo/article/details/54575168

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值