tomcat 解析(四)-处理http请求过程

声明:源码版本为Tomcat 6.0.35

前面的文章中介绍了Tomcat初始化的过程,本文将会介绍Tomcat对HTTP请求的处理的整体流程,更细节的。

在上一篇文章中,介绍到JIoEndpoint 中的内部类Acceptor用来接受Socket请求,并调用processSocket方法来进行请求的处理,所以会从本文这个方法开始进行讲解。

?


1

2

3

4

5

6

7

8

9

10

11

12

protected boolean processSocket(Socket socket) {

        try {

            if (executor == null) {

                getWorkerThread().assign(socket);

            else {

                executor.execute(new SocketProcessor(socket));

            }

        catch (Throwable t) {

            //……此处略去若干代码

        }

        return true;

    }

在以上的代码中,首先会判断是否在server.xml配置了进程池,如果配置了的话,将会使用该线程池进行请求的处理,如果没有配置的话将会使用JIoEndpoint中自己实现的线程池WorkerStack来进行请求的处理,我们将会介绍WorkerStack的请求处理方式。

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

protected Worker getWorkerThread() {

        // Allocate a new worker thread

        synchronized (workers) {

            Worker workerThread;

            while ((workerThread = createWorkerThread()) == null) {

                try {

                    workers.wait();

                catch (InterruptedException e) {

                    // Ignore

                }

            }

            return workerThread;

        }

    }

在以上的代码中,最终返回了一个Worker的实例,有其来进行请求的处理,在这里,我们再看一下createWorkerThread方法,该方法会生成或者在线程池中取到一个线程。

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

protected Worker createWorkerThread() {

        synchronized (workers) {

            if (workers.size() > 0) {

            //如果线程池中有空闲的线程,取一个

                curThreadsBusy++;

                return workers.pop();

            }

            if ((maxThreads > 0) && (curThreads < maxThreads)) {

                //如果还没有超过最大线程数,会新建一个线程

                curThreadsBusy++;

                return (newWorkerThread());

            else {

                if (maxThreads < 0) {

                    curThreadsBusy++;

                    return (newWorkerThread());

                else {

                    return (null);

                }

            }

        }

    }

到此,线程已经获取了,接下来,最关键的是调用线程实现Worker的run方法:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

public void run() {

            // Process requests until we receive a shutdown signal

            while (running) {

                // Wait for the next socket to be assigned

                Socket socket = await();

                if (socket == null)

                    continue;

                   if (!setSocketOptions(socket) || !handler.process(socket)) {

                    try {

                        socket.close();

                    catch (IOException e) {

                    }

                }

                socket = null;

                recycleWorkerThread(this);

            }

        }

这里跟请求处理密切相关的是handler.process(socket)这一句代码,此处handle对应的类是Http11Protocol中的内部类Http11ConnectionHandler,在此后的处理中,会有一些请求的预处理,我们用一个时序图来表示一下:

在这个过程中,会对原始的socket进行一些处理,到CoyoteAdapter时,接受的参数已经是org.apache.coyote.Request和org.apache.coyote.Response了,但是要注意的是,此时这两个类并不是我们常用的HttpServletRequest和HttpServletResponse的实现类,而是Tomcat内部的数据结构,存储了和输入、输出相关的信息。值得注意的是,在CoyoteAdapter的service方法中,会调用名为postParseRequest的方法,在这个方法中,会解析请求,调用Mapper的Map方法来确定该请求该由哪个Engine、Host和Context来处理。

在以上的信息处理完毕后,在CoyoteAdapter的service方法中,会调用这样一个方法:

?


1

connector.getContainer().getPipeline().getFirst().invoke(request, response);

这个方法会涉及到Tomcat组件中的Container实现类的重要组成结构,即每个容器类组件都有一个pipeline属性,这个属性控制请求的处理过程,在pipeline上可以添加Valve,进而可以控制请求的处理流程。可以用下面的图来表示,请求是如何流动的:

可以将请求想象成水的流动,请求需要在各个组件之间流动,中间经过若干的水管和水阀,等所有的水阀走完,请求也就处理完了,而每个组件都会有一个默认的水阀(以Standard作为类的前缀)来进行请求的处理,如果业务需要的话,可以自定义Valve,将其安装到容器中。

后面的处理过程就比较类似了,会按照解析出来的Engine、Host、Context的顺序来进行处理。这里用了两张算不上标准的时序图来描述这一过程:

在以上的流程中,会一层层地调用各个容器组件的Valve的invoke方法,其中StandardWrapperValve这个标准阀门将会调用StandardWrapper的allocate方法来获取真正要执行的Servlet(在Tomcat中所有的请求最终都会映射到一个Servlet,静态资源和JSP也是如此),并按照请求的地址来构建过滤器链,按照顺序执行各个过滤器并最终调用目标Servlet的service方法,来完成业务的真正处理。

以上的处理过程中,涉及到很多重要的代码,后续的文章会择期要者进行解析,如:

  • Mapper中的internalMapWrapper方法(用来匹配对应的Servlet)
  • ApplicationFilterFactory的createFilterChain方法(用来创建该请求的过滤器链)
  • ApplicationFilterChain的internalDoFilter方法(用来执行过滤器方法以及最后的Servlet)
  • Http11Processor中的process方法、prepareRequest方法以及prepareResponse方法(用来处理HTTP请求相关的协议、参数等信息)

至此,我们简单了解一个请求的处理流程。

时间: 2024-11-05 13:43:30

tomcat 解析(四)-处理http请求过程的相关文章

TOMCAT原理详解及请求过程(转)

https://www.cnblogs.com/hggen/p/6264475.html TOMCAT原理详解及请求过程 Tomcat: Tomcat是一个JSP/Servlet容器.其作为Servlet容器,有三种工作模式:独立的Servlet容器.进程内的Servlet容器和进程外的Servlet容器. Tomcat目录: tomcat |---bin:存放启动和关闭tomcat脚本 |---conf:存放不同的配置文件(server.xml和web.xml): |---doc:存放Tomc

TOMCAT原理详解及请求过程

Tomcat: Tomcat是一个JSP/Servlet容器.其作为Servlet容器,有三种工作模式:独立的Servlet容器.进程内的Servlet容器和进程外的Servlet容器. Tomcat目录: tomcat |---bin:存放启动和关闭tomcat脚本 |---conf:存放不同的配置文件(server.xml和web.xml): |---doc:存放Tomcat文档: |---lib/japser/common:存放Tomcat运行需要的库文件(JARS): |---logs:

tomcat 解析(二)-消息处理过程

接下来我们应该去了解一下 tomcat 是如何处理jsp和servlet请求的. 1.  我们以一个具体的例子,来跟踪TOMCAT, 看看它是如何把Request一层一层地递交给下一个容器, 并最后交给Wrapper来处理的. 以http://localhost:8080/web/login.jsp为例子 (以下例子, 都是以tomcat4 源码为参考) 这篇心得主要分为3个部分: 前期, 中期, 和末期. 前期:讲解了在浏览器里面输入一个URL,是怎么被tomcat抓住的. 中期:讲解了被to

Tomcat Server处理一个http请求过程

假设来自客户端的请求为: http://localhost:8080/lizhx/lizhx_index.jsp 请求被发送到本机端口8080,被在那里侦听的Coyote HTTP/1.1 Connector获得. Connector把该请求交给它的Service的Engine来处理,并等待Engine的回应. Engine获得请求localhost/lizhx/lizhx_index.jsp,匹配所有虚拟主机Host. Engine匹配到名为localhost的Host. localhost

tomcat 解析(五)-Tomcat的核心组成和启动过程

声明:源码版本为Tomcat 6.0.35 前面的文章中介绍了Tomcat的基本配置,每个配置项也基本上对应了Tomcat的组件结构,如果要用一张图来形象展现一下Tomcat组成的话,整个Tomcat的组成可以如下图所示: Tomcat在接收到用户请求时,将会通过以上组件的协作来给最终用户产生响应.首先是最外层的Server和Service来提供整个运行环境的基础设施,而Connector通过指定的协议和接口来监听用户的请求,在对请求进行必要的处理和解析后将请求的内容传递给对应的容器,经过容器一

servlet图解。1。。tomcat处理请求过程、servlet的生命周期

Tomcat的组成部分 Tomcat容器的处理请求过程 servlet的生命周期 HttpServletRequest HttpServletResponse

JBossWeb/Tomcat 初始化连接器和处理 Http 请求过程

概述 JBossWeb 是JBoss 中的 Web 容器,他是对 Tomcat 的封装,本文以 Http 连接器为例,简单说明 JBossWeb/Tomcat 初始化连接器和处理 Http 请求过程 .本文内容提要: Connector 初始化开始过程 如何理解 max-connections JIoEndpoint 处理 Socket 请求 Connector 初始化开始过程 如下图所示: WebConnectorService 指的是 `org.jboss.as.web.WebConnect

Tomcat Server处理一个HTTP请求的过程(转)

Tomcat Server处理一个HTTP请求的过程 1.用户点击网页内容,请求被发送到本机端口8080,被在那里监听的Coyote HTTP/1.1 Connector获得. 2.Connector把该请求交给它所在的Service的Engine来处理,并等待Engine的回应. 3.Engine获得请求localhost/test/index.jsp,匹配所有的虚拟主机Host. 4.Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被

Tomcat学习四步走:内核、集群、参数及性能

主题简介: 内核实现原理 分布式集群 生产部署关键参数 性能监控和分析 一.内核实现原理 HTTP Web服务器与浏览器之间以HTTP协议通信,浏览器要访问服务器即向服务器发送HTTP请求报文. 如图,此处用get方法访问了localhost的8080端口的Web.Index.JSP,服务器返回200状态码并将一些HTTP报文返回到客户端. HTTP报文 从图中可以看到,HTTP报文中的请求报文和响应报文都由三部分组成.请求报文由请求行.请求头和请求体三部分组成,其中请求行主要包括method.

web应用程序servlet的映射名称的规则及请求过程

首先用MyEclipse创建一个web Project(工程名起为TestServletProject),新建一个Servlet(这里servlet的名字起TestServlet),将请求的servlet映射名称设为/TestServlet,(具体步骤可以查看tomcat上servlet程序的配置与处理servlet请求过程).并在TestServlet的doGet方法中在控制台打印一句“this is TestServlet” jxf.servlet.TestServlet.java 1 pa