tomcat的体系结构
抽象理解:
Tomcat请求流程
Tomcat PipeLine机制: 每个组件上都会存在多个Value,配置信息不去添加Value 那么每次请求流程都只会走过默认的Value 。Value的作用:可以实现某某站点或某某上下文进行日志捕获,也可以是某某Engine下进行日志捕获,或是封禁IP等等,具体配置:
<!-- 日志记录 -->
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs"
prefix="localhost_access_log"
suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
<!-- IP禁止访问 -->
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
deny="192.168.1.100,10.0..*" />
默认Value:
Tomcat请求流程源代码分析
在分析之前请牢记上面默认的tomcatPipeLine关系,简单配置一份server.xml文件
将断点打在serverlet内
捕获断点后去,去查看CoyoteAdapter.class 346行,映入眼帘的是一个链接器connector 去获取对应的Service服务器中的容器中的Pipeline
通过计算值可以知道他取出的第一个Value就是默认的StanderEngine
走入我们的StanderEngine 查看一下对应的逻辑
在做一个简单的取请求的host进行匹配,如果为空就是返回404,而这个匹配和我们配置的server.xml中的host是一致的,匹配到就走入对应的上下文去处理请求。
然后在调用host组件下的容器中的Pipeline的第一个AccessLogValve对象进行实例化
进入host对象下的记录日志的Value,跟入AccessLogValve查看对应逻辑:
调用其他方法进行host组件下的日志记录,有趣的是this.getNext又取下一个Value进行调用
ErrorReportValve是我们host组件下默认的记录异常的Value ,跟入该类
逻辑大概也就是处理系统抛出的异常,不让程序宕机。再次进入host组件下最后一个标准Stander
走入实例化组件下的标准stander中了,不断不断的这种Line调用最后走入Severlet下,和上面给出的Value调用默认图是一致的。
最后一个标准StandardWrapperValve是通过Filter拦截器进入的severlet下的
filterChain.doFilter(request.getRequest(), response.getResponse());
自定义我们的Value
刚刚介绍了tomcatPipeLine下的默认Value的流程,那么tomcat肯定支持我们在默认流程下添加我们自己的Value,并且查看一下是不是真的添加上我们自己实现的Value了?
在刚刚的配置文件中添加一个拦截黑名单IP的Value,添加在Engine层下
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
deny="192.168.1.100,10.0..*" />
那么开始的StanderEngine上要多出一个Value,代码层面去分析:
可以发现已经出现我们配置远程地址的Value了,并且堆栈上查看也是调用了对应的Value了
总结
在 Tomcat 中,Pipeline 是由一系列组件构成的链条(链式结构),每个组件负责处理请求的某个特定方面。一个请求会经过这个处理链,最终生成响应。Pipeline 的设计使得处理请求的各个阶段可以通过添加、删除或替换组件来灵活配置。
学习Pipeline可以帮助后面的(学了以后更好帮助Tomcat-Valve类型内存马理解)
建议去看看视频食用:https://www.bilibili.com/video/BV11w411f7XC
个人总结有理解错误,望大家理解。
原文始发于微信公众号(T3Ysec):Tomcat中容器的pipeline机制
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论