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请求相关的协议、参数等信息)
至此,我们简单了解一个请求的处理流程。
tomcat 解析(四)-处理http请求过程的更多相关文章
- TOMCAT原理详解及请求过程(转载)
转自https://www.cnblogs.com/hggen/p/6264475.html TOMCAT原理详解及请求过程 Tomcat: Tomcat是一个JSP/Servlet容器.其作为Ser ...
- TOMCAT原理详解及请求过程
Tomcat: Tomcat是一个JSP/Servlet容器.其作为Servlet容器,有三种工作模式:独立的Servlet容器.进程内的Servlet容器和进程外的Servlet容器. Tomcat ...
- Tomcat学习(二)------Tomcat原理详解及请求过程
Tomcat: Tomcat是一个JSP/Servlet容器.其作为Servlet容器,有三种工作模式:独立的Servlet容器.进程内的Servlet容器和进程外的Servlet容器. Tomcat ...
- tomcat 解析(二)-消息处理过程
接下来我们应该去了解一下 tomcat 是如何处理jsp和servlet请求的. 1. 我们以一个具体的例子,来跟踪TOMCAT, 看看它是如何把Request一层一层地递交给下一个容器, 并最后交 ...
- Tomcat Server处理一个http请求过程
假设来自客户端的请求为: http://localhost:8080/lizhx/lizhx_index.jsp 请求被发送到本机端口8080,被在那里侦听的Coyote HTTP/1.1 Conne ...
- 解析Tomcat内部结构和请求过程
Tomcat Tomcat的组织结构 由Server.xml的结构看Tomcat的体系结构 Tomca的两大组件:Connecter和Container Connecter组件 Container组件 ...
- 网站开发进阶(四)Tomcat Server处理一个http请求的过程
Tomcat Server处理一个http请求的过程 假设来自客户的请求为: http://localhost:8080/wsota/wsota_index.jsp 1) 请求被发送到本机端口8080 ...
- tomcat 解析(五)-Tomcat的核心组成和启动过程
声明:源码版本为Tomcat 6.0.35 前面的文章中介绍了Tomcat的基本配置,每个配置项也基本上对应了Tomcat的组件结构,如果要用一张图来形象展现一下Tomcat组成的话,整个Tomcat ...
- WEB请求过程(http解析,浏览器缓存机制,域名解析,cdn分发)
概述 发起一个http请求的过程就是建立一个socket通信的过程. 我们可以模仿浏览器发起http请求,譬如用httpclient工具包,curl命令等方式. curl "http://w ...
- 走进JavaWeb技术世界5:初探Tomcat的HTTP请求过程
初探Tomcat的HTTP请求过程 前言:1.作为Java开发人员,大多都对Tomcat不陌生,由Apache基金会提供技术支持与维护,因为其免费开源且易用,作为Web服务器深受市场欢迎,所以有必要对 ...
随机推荐
- 20141016--for 菱形
Console.Write("请输入一个数:"); int n = int.Parse(Console.ReadLine()); ; i <= n; i++) { ; b & ...
- AMQ学习笔记 - 07. 持久性订阅
概述 一般的订阅,订阅者必须时刻处于活跃状态,才不会遗漏任何信息:持久性订阅,当订阅者处于非活动状态时,代理会为它们保留信息,下一次连接之后推送给它们. 持久订阅 与一般的定于相比,持久性订阅需要: ...
- websphere中由于实际应用没有卸载干净,导致安装不了。以下是完全卸载应用程序的方法
出现此问题的原因之一:操作界面上没有卸载完成.进行一下操作:1.删除 $WAS_HOME/profiles/AppSrv01/config/cells/...cell/applications下对应 ...
- 暑假集训(4)第五弹——— 数论(hdu1222)
题意概括:那天以后,你好说歹说,都快炼成三寸不烂之舍之际,小A总算不在摆着死人脸,鼓着死鱼眼.有了点恢复的征兆.可孟子这家伙说的话还是有点道理,那什么天将降....额,总之,由于贤者法阵未完成,而小A ...
- 利用rsyslog 对linux 操作进行审计
环境:客户端和服务端都需要安装rsyslog服务 rsyslog server端 cd /etc/rsyslog.d/ cat server.conf $ModLoad imtcp $InputTC ...
- L014-oldboy-mysql-dba-lesson14
L014-oldboy-mysql-dba-lesson14 来自为知笔记(Wiz) 附件列表
- 四位数码管SH5461AS的问题,arduino学习实测.
arduino入门教程到第16课遇到些问题.效果一直是混乱的状态. 琢磨了半天发现一些问题,和大家分享下 1)接线图,原图没有问题,只是比较含糊,线比较多不好看. 我用红色数字标示数码管的12个脚,并 ...
- 《APUE》第四章笔记(4)
这算是在博客园写的第一篇文章啊,之前都在csdn写(虽然才写了几篇,因为开通也没多少天..),还是稍微期待下吧.我写博客的主要意图是一来能够记录下来自己所学过的东西,二来也想能够跟大家交流,能够得到更 ...
- win32开发基础
收集的,正在学习... 跟我一起玩Win32开发(1):关于C++的几个要点 跟我一起玩Win32开发(2):完整的开发流程 跟我一起玩Win32开发(3):窗口的重绘 跟我一起玩Win32开发(4) ...
- 加载页面遮挡耗时操作任务页面--第三方开源--AndroidProgressLayout
在Android的开发中,往往有这种需求,比如一个耗时的操作,联网获取网络图片.内容,数据库耗时读写等等,在此耗时操作过程中,开发者也许不希望用户再进行其他操作(其他操作可能会引起逻辑混乱),而此时需 ...