tomcat分配请求之——请求如何流程Connection

 

首先摘自我的好友。傻博语录:人生就是悲剧

 

上次说到每一个请求会分配给一个Worker处理,而Worker与我们平时写代码都是围绕Servlet写的,到底又有些什么差别呢?

worker后面是委托给Handler处理的。

handler处理的时候分配给Http11Processor(Http11Processor被维护在一个先进先出队列当中)。

而所有的HttpProcessor共享Http11Protocal 的Adapter成员变量,Adapter会调用到Servlet,即所有Handler都用同一个Adapter。

首先请看图:



 讲述下每个部分的作用:

 

JioEndPointer:启动一个线程监听socket,并把到来的请求分配给相应的worker

Http11ConnectionHandler: Http协议的基于普通IO的处理方式.

Adapter:Http协议的请求 委托或 适配给 servlet容器处理的适配器

attributes:Http协议的相关属性设置


其中的对应关系也非常重要:

A,1个worker 必须对应一个 Http11ConnectionHandler 中的Http11ConnectionProcessor(是handler里面真正处理的Http协议的类)

 

B,所有的worker都持有同一个Adapter

 

 

 

详细类图下图所示:

 



 

 

我在HttpServlet的service方法里设置了一个断点,然后调试了下,可以看一下调用栈。 

 调用栈很清晰得说明了调用到哪些类和顺序:也可以看官方化得时序图: 

http://tomcat.apache.org/tomcat-6.0-doc/architecture/requestProcess/requestProcess.pdf

 

 

 

JIoEndpoint.java

/** * Create (or allocate) and return an available processor for use in * processing a specific HTTP request, if possible. If the maximum * allowed processors have already been created and are in use, return * <code>null</code> instead. */ protected Worker createWorkerThread() { synchronized (workers) { if (workers.size() > 0) { curThreadsBusy++; return workers.pop(); } if ((maxThreads > 0) && (curThreads < maxThreads)) {              // 默认maxThreads 为200 curThreadsBusy++; if (curThreadsBusy == maxThreads) { log.info(sm.getString("endpoint.info.maxThreads", Integer.toString(maxThreads), address, Integer.toString(port))); } return (newWorkerThread()); } else { if (maxThreads < 0) { curThreadsBusy++; return (newWorkerThread()); } else { return (null); } } } } /** * Create and return a new processor suitable for processing HTTP * requests and returning the corresponding responses. */ protected Worker newWorkerThread() { Worker workerThread = new Worker(); workerThread.start(); return (workerThread); }

 

 

 

从代码来看,如果没有到达请求最大值,首先会从栈中取得空闲的Worker,或者创建新的Worker。

 

所以来一个请求,会分配给一个Worker,而Worker做了一些接收Socket,设置一些socket和需要的环境类,然后就交给了Servlet实例,而servlet实例启动的时候就是对于一个context 中配置的一个servlet只启动一个实例。

 

 StandardWrapper.java

/** * Load and initialize an instance of this servlet, if there is not already * at least one initialized instance. This can be used, for example, to * load servlets that are marked in the deployment descriptor to be loaded * at server startup time. */ public synchronized Servlet loadServlet() throws ServletException { // Nothing to do if we already have an instance or an instance pool // 初始化servlet的时候,如果发现已经初始化完毕,则不再初始化 if (!singleThreadModel && (instance != null)) return instance;

 

 

 

所以首先servlet不是线程安全的。

其次 HttpSession不是线程安全的。

还有 Context不是现成安全的。

 

Request是线程安全的。

 

### Tomcat 接收 HTTP 请求的工作原理 Tomcat作为一个Web应用服务器,通过一系列组件协同工作来接收和处理HTTP请求。当客户端发起一个HTTP请求时,该请求首先进入到监听特定端口的Connector模块中[^3]。 #### Connector 组件的作用 Connector负责监听指定的网络端口以接受来自外部世界的连接尝试,并创建相应的Socket实例用于后续的数据交换过程。对于每一个成功的TCP/IP握手事件,都会触发一个新的线程或者异步任务去专门服务于此次会话,在此期间它将执行如下操作: - **读取消息体**:从输入流中获取原始二进制数据; - **解析消息头与主体内容**:依据所使用的传输协议(通常是HTTP),对上述字节数组进行语义层面的理解,提取出诸如URI路径、查询字符串以及POST表单字段等有用信息; 一旦完成了以上步骤,则可以构建起内部表示形式——即`Tomcat Request`对象,用来承载所有关于当前访问企图的知识点[^1]。 ```java // 创建并初始化Request对象 org.apache.coyote.Request tomcatRequest = new org.apache.coyote.Request(); tomcatRequest.setMethod("GET"); ... ``` 然而值得注意的是,尽管此时已经拥有了足够的上下文描述符供进一步分析之用,但为了能够顺利接入更高层次的应用逻辑框架内运行,还需要借助于适配机制完成最终转换成为符合Java Servlet API规范的对象结构——也就是所谓的`ServletRequest`实体[^2]。 --- ### 配置方法 要使Tomcat正确无误地接收到目标主机发送来的HTTP报文包,需确保其配置文件中的相应部分设置恰当合理。主要涉及以下几个方面: - `server.xml`: 此处定义了整个服务的核心属性及其下辖各子系统的启动参数,特别是有关Connector的部分最为关键。默认情况下,8080号端口被分配给了HTTP通信用途,当然也可以根据实际需求调整为其他可用数值。 ```xml <!-- server.xml --> <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> ``` - `web.xml`: 应用级别的部署描述符,虽然这里并不直接影响到物理链路层面上的行为表现,但对于某些特殊类型的资源映射规则却有着不可或缺的意义。例如静态网页文件夹位置设定、过滤器注册声明等等均在此处体现出来。 综上所述,只要按照官方文档指导妥善安排好这两份XML格式化文本的内容细节,就能让Tomcat具备良好的对外服务能力,从而实现高效稳定的Web应用程序托管环境搭建目的。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值