详解Tomcat内部实现架构解析
即将开播:5月20日,基于kubernetes打造企业级私有云实践
Tomcat顶层架构
可以看到一个Server可以有多个Service,一个Service可以有多个Connector和一个Container,这两部分是tomcat的核心。
1,Connector用于处理连接相关额事情,并提供Socket与Reponse相关的转化
2,Container用于封装和管理Servlet,以及具体处理Request请求
多个Connector可以提供多个链接,例如同时提供http和https链接,亦可以提供相同协议不同端口的链接,示意如图:
多个Connector和一个Container就形成了一个Service,但是还需要一个环境来管理整个多个Service(但是一般也就只有一个Service,就是常见得Catalina),这个就必须是Server了,具体可以看
server.xml文件配置:
上面的配置用这张图更加清楚的理解:
下面来解析一下这个配置文件:
可以看到Server标签port设置为8005,shutdown="SHUTDOWN",表示8005端口监听到SHUTDOWN命令就关闭Tomcat服务。
Resource内配置 pathname="conf/tomcat-users.xml" 指定manageUI登录的用户以及其他的全局配置。
这个Server里只有一个Service名为Catalina,Catalina支持两个连接,分别是端口为8080的http连接和端口为8009的AJP连接,
Catalina这个服务里有一个站点名字叫localhoust,站点下的应用群为appBase="webapps",支持自动部署autoDeploy="true",
并设置了站点内应用打印的日志名称及日志格式。
Connector和Container架构分析
Connector用于接收请求并将请求封装成Request和Response,然后交给Container处理,处理之后在交给Connector返回给客户端。
可以分为四步:
- 1,Connector如何接受请求的?
- 2,如何将接受的请求封装成Request和Response的?
- 3,封装完成后的Request和Reponse是如何交给Container的?
- 4,Container处理完成后如何交给Connector并返回给客户端的?
Connector结构图:
Connector使用ProtocoHandler处理请求,不同的ProtocoHandler代表不同的类型,比如:Http11Protocol使用普通的Socke
t来连接,Http11NioProtocol使用NioSocket连接。
三个组件Endpoint用来处理底层Socket连接,Process用来将EndPoint接受到的Socket封装成Request,Adapetr将Request
交给Container进行具体的处理。
EndPoint底层处理Socket网络连接,所以EndPoint是用来实现TCP/IP协议的,而Processor是用来实现HTTP协议的,
Adapetr将请求是配到Servlet容器进行具体处理。AsyncTimeout用来监听请求是否超时。
现在1,2,3前三步已经处理完了就剩最后一步Container如何处理请求了
Container结构图:
四个子容器分别是:
1,Engine:引擎管理多个站点(Host),一个Service一个Engine
2,Host:代表一个站点,在server.xml配置Host可添加站点
3,Context:代表一个应该用程序,就是我们平时开发的程序,或一个WEB-INF目录及web.xml文件
4,Wrapper:每个Wrapper封装这一个Servlet
以上几个容器和Tomcat目录对应如下:
Context和Host的区别就是Context代表一个应用,我们的Tomcat默认webapps下的每一个文件夹都是一个Context,其中Root下放着主应用,
其他的目录都存放着子应用。而整个webapps就是一个Host站点。
访问应用时如果放在了Root下可以直接Host的name属性加Connector的端口就行,如果是自己建的就加上Context名称就行了。
Container如何处理请求的?
使用了Pipeline-Valve管道来处理,其中用到了责任链模式,每一个处理者负责做自己的处理,处理完后将处理结果返回,
再交给下个处理者继续处理,如图:
(1)Connector在接收到请求后会首先调用最顶层容器的Pipeline来处理,这里的最顶层容器的Pipeline就是EnginePipeline(Engine的管道);
(2)在Engine的管道中依次会执行EngineValve1、EngineValve2等等,最后会执行StandardEngineValve,在StandardEngineValve中会调用Host管道,然后再依次执行Host的HostValve1、HostValve2等,最后在执行StandardHostValve,然后再依次调用Context的管道和Wrapper的管道,最后执行到StandardWrapperValve。