Tomcat源码学习--Http请求处理过程

250 阅读6分钟

首先上一张图片了解一下整体的流程:

整体流程.png 1.Tomcat启动后会有后台会有一个线程 一直监听对应的启动窗口(默认8080)。
2.请求到达Tomcat后 监听线程捕获到请求;

请求首先被Acceptor监听到。Acceptor实现了Runnable接口,在Tomcat启动后就一直在后台运行run方法。run方法中会调用endpoint.setSocketOptions()方法。

NioEndpoint.setSocketOptions(SocketChannel socket)

protected boolean setSocketOptions(SocketChannel socket) {
    NioSocketWrapper socketWrapper = null;
    try {
        // 根据 socket 封装处理生成 socketWrapper 
        ...
        // 会把 调用poller的 register 方法,把 socketWrapper 交给 poller
        poller.register(socketWrapper);
        return true;
    } catch (Throwable t) {
        // ...异常处理
    }
    // 返回 boolean 类型,如果为 false 则通知accept关闭,关闭socket
    return false;
}

接下来查看 Poller.register()方法(Poller是NioEndpoint的内部类)

// 向Poller注册一个新创建的套接字(socketWrapper)
public void register(final NioSocketWrapper socketWrapper) {
    socketWrapper.interestOps(SelectionKey.OP_READ);//this is what OP_REGISTER turns into.
    PollerEvent event = null;
    if (eventCache != null) {
        // 先从缓存中取
        event = eventCache.pop();
    }
    if (event == null) {
        // 如果为空,根据socketWrapper创建一个新的事件,实际上new方法 也是调用了reset方法
        event = new PollerEvent(socketWrapper, OP_REGISTER);
    } else {
        // 如果不为空,则将event重置,并将socketWrapper设置进去
        event.reset(socketWrapper, OP_REGISTER);
    }
    // 注意这一句,将创建好的event事件添加到当前队列中
    addEvent(event);
}

上面可以看到,每个请求进来之后,会通过 register 方法创建一个 PollerEvent 对象并添加到当前的 SynchronizedQueue events 队列中。
接下来看 Poller的run()方法,Poller 在Tomcat启动时在startInternal()方法调用的时候创建并一直在后台启动着。

public void run() {
    // 一直循环直到调用destroy()方法
    while (true) {
        boolean hasEvents = false;
        try {
            if (!close) {
                hasEvents = events();
                ...
            }
            ...
        } catch (Throwable x) {
            ...
        }
        Iterator<SelectionKey> iterator =
            keyCount > 0 ? selector.selectedKeys().iterator() : null;
        // 遍历所有的键,找到key之后调用processKey
        while (iterator != null && iterator.hasNext()) {
            SelectionKey sk = iterator.next();
            iterator.remove();
            NioSocketWrapper socketWrapper = (NioSocketWrapper) sk.attachment();
            // 如果另一个线程调用了 cancelledKey(),则attachment可能为空
            if (socketWrapper != null) {
                processKey(sk, socketWrapper);
            }
        }
        ...
    }
    getStopLatch().countDown();
}

processKey() 会根据配置的Executer调用SocketProcessorBaserun() 方法。
接下来看SocketProcessorBaserun()方法最终会调用doRun()方法,SocketProcessorBase是一个抽象类,doRun()是一个抽象方法,所以实际调用的是SocketProcessordoRun()方法。SocketProcessorSocketProcessorBase的子类,SocketProcessorNioEndpoint的内部类。在doRun()方法中会有调用 getHandler().process() ,接下来就是进入到AbstractProtocol.ConnectionHandler.process()
调用链:
Acceptor.run() -> endpoint.setSocketOptions() -> NioEndpoint.setSocketOptions() -> poller.register() -> addEvent () 将PollerEvent 对象并添加到Poller的events 队列中,Poller的run方法会判断队列中是否有event然后调用processKey()
Poller.run() -> processKey() -> SocketProcessorBase.run() -> doRun() ->NioEndpoint.SocketProcessor.doRun() -> getHandler() -> AbstractProtocol.ConnectionHandler.process()

进入handler处理socket.png

NioEndpoint.png

SocketProcessorBase 实现了Runnable接口
Connector 里面有一个属性:ProtocolHandler(是一个接口)
AbstractProtocol实现了 ProtocolHandler 接口
AbstractEndpoint 里面有一个属性: Handler(是一个内部接口)
AbstractProtocol有一个内部类:ConnectionHandler 实现了 Handler接口

SocketProcessorBase是一个抽象类,并且有一个抽象方法 doRun()
NioEndpoint中有一个内部类 SocketProcessor并且继承了SocketProcessorBase,实现了doRun()方法。
NioEndpoint继承了AbstractEndpoint,AbstractEndpoint有getHandler()方法并且返回的是Handler类型的,但是NioEndpoint没有getHandler()方法。
所以在NioEndpoint.SocketProcessor.doRun() 中调用getHandler()实际调用的父类的方法,同时返回的是实现了父类中Handle接口的对象。
因此getHandle()方法返回的就是AbstractProtocol.ConnectionHandler

ConnectionHandler.process()

protected static class ConnectionHandler<S> implements AbstractEndpoint.Handler<S> {
    ...
    @Override
    public SocketState process(SocketWrapperBase<S> wrapper, SocketEvent status) {
        //找到对应的processor
        ...
        processor.setSslSupport(wrapper.getSslSupport(getProtocol().getClientCertProvider()));
        // Associate the processor with the connection
        wrapper.setCurrentProcessor(processor);
        SocketState state = SocketState.CLOSED;
        do {
            state = processor.process(wrapper, status);
            // 后续是对处理结果的一些处理
            ...
        } while ( state == SocketState.UPGRADING);
        ...
    }
    ...
}

进入对应processor处理.png 从上图可以看到最后处理socket的processor是 Http11Processor

继续往下走,我们发现代码是进入到AbstractProcessorLight.process() ,这应该是一个模板方法,Http11Processor是没有process这个方法的,但是Http11Processor继承了AbstractProcessorLight,所以直接进入了AbstractProcessorLight的process方法。

AbstractProcessorLight.process(SocketWrapperBase<?> socketWrapper, SocketEvent status)

public SocketState process(SocketWrapperBase<?> socketWrapper, SocketEvent status)
        throws IOException {
    // socket状态    
    SocketState state = SocketState.CLOSED;
    // 调度类型
    Iterator<DispatchType> dispatches = null;
    do {
        // 根据不同的socket状态进行的一些操作
        if (dispatches != null) {
           ..
        } else if (status == SocketEvent.OPEN_READ) {
            // 正常情况请求会进到这一步,调用了service方法,但是AbstractProcessorLight没有service方法,所以实际调用的是子类的service方法
            state = service(socketWrapper);
        } else if (status == SocketEvent.CONNECT_FAIL) {
            // 如果失败,则添加日志
            logAccess(socketWrapper);
        } else {
            // 如果传入的 SocketEvent 与 Processor 当前状态不一致,则默认关闭套接字
            state = SocketState.CLOSED;
        }
        ...
    } while (state == SocketState.ASYNC_END || dispatches != null && state != SocketState.CLOSED);
    return state;
}

进入Http11Processor的service方法.png

处理之前经过一个AuthenticatorBase

实际是调用进入到DispatcherServlet,先看下一下DispatcherServlet的UML图:

DispatcherServlet.png DispatcherServlet、FrameworkServlet、HttpServletBean没有service(ServletRequest req, ServletResponse res)方法,注意req、res的参数类型。 FrameworkServlet的service方法是:service(HttpServletRequest request, HttpServletResponse response),所以进入到 HttpServlet.service(ServletRequest req, ServletResponse res)方法。

HttpServlet.service(ServletRequest req, ServletResponse res)

@Override
public void service(ServletRequest req, ServletResponse res)
    throws ServletException, IOException
{
    HttpServletRequest  request;
    HttpServletResponse response;
    // 判断 req 和 res 是否是 HttpServletRequest 、HttpServletResponse 类型的对象
    if (!(req instanceof HttpServletRequest &&
            res instanceof HttpServletResponse)) {
        throw new ServletException("non-HTTP request or response");
    }
    // 类型转换 HttpServletRequest和HttpServletResponse是两个接口,分别继承了ServletRequest、ServletResponse
    request = (HttpServletRequest) req;
    response = (HttpServletResponse) res;
    // 调用本类的service方法,而且上面对req、res进行了类型转换,所以下一步进入到的是FrameworkServlet.service(HttpServletRequest request, HttpServletResponse response)
    service(request, response);
}

FrameworkServlet.service(HttpServletRequest request, HttpServletResponse response)

protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
   // 获取方法类型: GTE、POST、PUT......
   HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
   if (httpMethod == HttpMethod.PATCH || httpMethod == null) {
      processRequest(request, response);
   } else {
      // 调用父类的service(HttpServletRequest request, HttpServletResponse response),HttpServletBean没有该方法,故进入到HttpServlet.service(HttpServletRequest req, HttpServletResponse resp)
      super.service(request, response);
   }
}

HttpServlet.service(HttpServletRequest req, HttpServletResponse resp)

protected void service(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException
{
    // 获得方法类型: GET、POST...
    String method = req.getMethod();
    if (method.equals(METHOD_GET)) {
        //  ???
        long lastModified = getLastModified(req);
        if (lastModified == -1) {
            // 执行doGet方法,代码执行到这里实际上当前对象this一直是DispatcherServlet的类型,所以doGet还是优先去找DispatcherServlet中的方法,找不到再一级一级向上找,这里实际会进入到FrameworkServlet.doGet(HttpServletRequest request, HttpServletResponse response)
            doGet(req, resp);
        } else {
            ...
        }
    } else if (method.equals(METHOD_POST)) {
            doPost(req, resp);
    } 
    //根据同的方法类型做执行对应的逻辑
    ...
}

FrameworkServlet.doGet(HttpServletRequest request, HttpServletResponse response)

protected final void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
   processRequest(request, response);
}
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
   ...
   try {
      // 主要就这一行代码,此时才是真正执行到 DispatcherServlet.doService(HttpServletRequest request, HttpServletResponse response)
      doService(request, response);
   } catch (ServletException | IOException ex) {
     ...
   }
}

DispatcherServlet.doService(HttpServletRequest request, HttpServletResponse response)

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
   ...
   try {
      // 核心代码就这一行
      doDispatch(request, response);
   }
   ...
}
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
   HttpServletRequest processedRequest = request;
   HandlerExecutionChain mappedHandler = null;
   boolean multipartRequestParsed = false;
   WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
   try {
      ModelAndView mv = null;
      Exception dispatchException = null;
      try {
         processedRequest = checkMultipart(request);
         multipartRequestParsed = (processedRequest != request);
         // 确定当前请求的Handler
         mappedHandler = getHandler(processedRequest);
         ...
         // 实际上调用handler
         mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
         if (asyncManager.isConcurrentHandlingStarted()) {
            return;
         }
         applyDefaultViewName(processedRequest, mv);
         mappedHandler.applyPostHandle(processedRequest, response, mv);
      }
      ...
      processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
   }
   ...
}
// 返回此请求的 HandlerExecutionChain。 按顺序尝试所有处理程序映射
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
   if (this.handlerMappings != null) {
      for (HandlerMapping mapping : this.handlerMappings) {
         HandlerExecutionChain handler = mapping.getHandler(request);
         if (handler != null) {
            return handler;
         }
      }
   }
   return null;
}

找到对应的handler后,handler负责处理请求,最终实际就是使用反射调用业务代码的方法,将请求交由业务逻辑处理,adapter根据请求返回确定对应的视图或者页面。

ServletInvocableHandlerMethod.invokeAndHandle()

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
      Object... providedArgs) throws Exception {
   // 拿到返回值
   Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
   setResponseStatus(webRequest);
   ...  
   try {
      // 根据返回值,继续处理接下来的流程
      this.returnValueHandlers.handleReturnValue(
            returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
   }...
}

InvocableHandlerMethod.invokeForRequest()

public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
   ...
   return doInvoke(args);
}
protected Object doInvoke(Object... args) throws Exception {
   ReflectionUtils.makeAccessible(getBridgedMethod());
   try {
      // 主要就是一行,getBean通过反射获得对象,并执行反射执行对应的方法,最后进入到业务代码
      return getBridgedMethod().invoke(getBean(), args);
   }
   ...
}