Tomcat执行链源码指引

本文详细探讨了Tomcat处理HTTP请求的流程,从高层的浏览器请求到DNS解析,再到Tomcat内部的NioEndpoint、Acceptor线程、Poller线程、SocketProcessor线程的交互,最终如何转发到Servlet进行处理。重点解析了Http11NioProtocol协议的执行链,揭示了请求从Socket到Servlet的完整路径。

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

注:本文只关注于请求执行顺序,无初始化过程
高层执行链
浏览器—>http请求–>DNS服务–>三次握手–>tomcat处理–>四次挥手

DNS服务根据域名寻找ip
浏览器缓存–>系统缓存–>路由器缓存–>ISP DNS缓存–>DNS服务器

三次握手
客户端、服务器交换并确认序列号(SYN/ACK)

四次挥手
客户端、服务器双向通知对方结束并确认

Tomcat处理(以Http11NioProtocol为例)
监听端口–>包装Request–>转发到Container–>Servlet

监听端口
connector对象持有ProtocolHandler对象;ProtocolHandler持有AbstractEndpoint对象。AbstractEndpoint负责创建服务器套接字,并绑定到监听端口
NioEndpoint.bind()绑定serverSock监听端口
NioEndpoint
封装底层网络通信细节,提供基础的网络IO服务

Acceptor线程
负责监听serverSock绑定的端口,即循环调用serverSock.accept()获取SocketChannel对象
并将获取到的SocketChannel对象封装为NioChannel对象,并交给Poller线程,将之加入到Poller同步事件队列(PollerEvent队列)
Poller线程
以较少的资源轮询已经连接的套接字并保持连接,当数据可用时将之交给工作线程(而非每个套接字单独绑定一个线程)
每个Poller线程有一个独有的Selector对象(Selector与NioChannel的关系见NIO)
Poller线程会逐个调用PollerEvent线程对象的run()方法,将PollerEvent事件的IOChannel注册到Selector上
再获取Selector中所有已注册的NioChannel对象,逐个执行processKey(SelectionKey, NioSocketWrapper)
在该方法中调用processSocket()方法,封装为SocketProcessor对象,丢到线程池ThreadPoolExecutor中执行

PollerEvent线程队列
重写run()方法不会在单独线程中执行,而是Poller线程中逐个被同步调用
实现Runnable接口,只是用来表示一个轮询事件
run()中将本PollerEvent事件的IOChannel注册到Selector上

SocketProcessor线程
先检查握手,再调用由ConnectionHandler抽象类定义的process()方法
接下来就是由不同协议定义的由socketWrapper转换为Request的具体算法(终于到Request了)
就是这个方法:org.apache.coyote.http11.Http11Processor#service(不想看)
然后这个service中,getAdapter().service(request, response);

CoyoteAdapter
连接Connector与Container的桥梁,转换Request
并转发到Container的管道上,逐级执行阀门,到底层StandardWrapperValve

StandardWrapperValve
封装Servlet,先执行过滤器,再执行servlet
servlet.service(request, response)方法在ApplicationFilterChain内部,执行完过滤器链才会执行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值