深入了解Tomcat
2020-05-02 15:52:44 50 举报
AI智能生成
深入了解Tomcat思维导图
作者其他创作
大纲/内容
架构解析
Tomcat的目录结构
bin(执行目录)
lib(加载的jar包目录)
conf(配置文件目录)
catalina.policy(权限配置文件)
server.xml(核心配置文件)
Server(服务器)
Service(服务)
Executor(线程池)
name
线程池名称
namePrefix
线程名称前缀
maxThreads
最大线程数
minSpareThreads
最小空闲线程数
Connector(连接器)
port
tomcat连接器端口
protocol
连接器协议
maxThreads
最大线程数
acceptCount
连接等待队列的大小
connectionTimeout
连接超时时间
redirectPort
重定向端口
Executor与Connector的关系
Connector指客户端请求服务器,tomcat需要建立、维护、管理这些连接,当Connector建立连接后,服务器会分配一个线程(可能
是从线程池)去服务这个连接,即执行doPost等方法,执行完,回收线程,这是一个同步的过程,是交给tomcat的Executor去处理的
是从线程池)去服务这个连接,即执行doPost等方法,执行完,回收线程,这是一个同步的过程,是交给tomcat的Executor去处理的
web.xml(应用程序配置文件)
DefaultServlet(默认Servlet,加载静态文件)
JspServlet(专门处理Jsp)
mime-mapping(tomcat处理的文件类型)
logs(日志目录)
catalina日志
主要记录tomcat启动时候的信息
commons-daemon日志
主要存放利用服务方式启动tomcat作为守护进程的日志记录
localhost日志
主要存放应用初始化未处理的异常输出的日志,同时也包含部分tomcat的启动和暂停时的运行日志
localhost-access日志
主要存放访问tomcat的日志,记录请求时间、资源和状态码等信息
host-manager日志
主要存放tomcat的自带的manager项目的日志信息
manager日志
主要存放tomcat manager项目专有的日志文件
tomcat7-stderr日志
主要存放log4j的错误日志,因此在程序中要合理的捕捉异常
tomcat7-stdout日志
主要存放程序中的System语句打印的日志(包括系统抛出的异常)
webapps(应用程序目录)
Tomcat部署模式
显示部署
1. 在server.xml中添加content元素方式
2. 创建xml的方式
隐式部署
将一个war文件或者整个应用程序复制到tomcat到webapps目录下
Tomcat总体架构
Tomcat总体架构图
源码解析
Server接口
Server类接口关系图
Server接口由StandardServer类实现,并继承Lifecycle生命周期接口,实现对Server生命周期状态的管理
Service接口
Service类接口关系图
Service接口有StandService类实现,同样继承Lifecycle生命周期接口,实现对Service生命周期状态的管理
Tomcat启动流程
Tomcat启动时序图
类加载机制
Bootstrap中定义类加载器
BootstrapClassLoader 引导类加载器
ExtClassLoader 扩展类加载器
AppClassLoader 应用类加载器
CustomClassLoader 用户自定义类加载器
tomcat自定义类加载器原因
1 .tomcat可能要部署多个web项目,多个项目可以依赖同一个类库不同版本jar包,但是不同版本的jar包要进行隔离
2. 多个项目不能共享一份jar包的class,不同的项目不能直接共用同一个类加载器
3. 避免类加载器的内存泄漏
4. 服务器本身也有自己依赖的jar包
5. 多个项目如果依赖同一个类库的相同版本,tomcat提供了一个共享类加载器sharedLoader,解决这个问题
6. 实现项目热部署需要
设计模式
模版设计模式
模版设计模式定义:模板方法模式抽象出某个业务操作公共的流程,将流程分为几个步骤,其中有一些步骤是固定不变的,有一些步骤是变
化的,固定不变的步骤通过一个基类来实现,而变化的部分通过钩子方法让子类去实现,这样就实现了对系统中流程的统一化规范化管理
化的,固定不变的步骤通过一个基类来实现,而变化的部分通过钩子方法让子类去实现,这样就实现了对系统中流程的统一化规范化管理
tomcat中的模版设计模式:tomcat中关于生命周期管理的地方很好应用了模板方法模式,在一个组件的生命周期中都会涉及到init(初始化),
start(启动),stop(停止),destory(销毁),而对于每一个生命周期阶段其实都有固定一些事情要做,比如判断前置状态,设置后置状态,
以及通知状态变更事件的监听者等,而这些工作其实是可以固化的,所以Tomcat中就将每个生命周期阶段公共的部分固化,然后通过
initInternal,startInternal,stopInternal,destoryInternal这几个钩子方法开放给子类去实现具体的逻辑
start(启动),stop(停止),destory(销毁),而对于每一个生命周期阶段其实都有固定一些事情要做,比如判断前置状态,设置后置状态,
以及通知状态变更事件的监听者等,而这些工作其实是可以固化的,所以Tomcat中就将每个生命周期阶段公共的部分固化,然后通过
initInternal,startInternal,stopInternal,destoryInternal这几个钩子方法开放给子类去实现具体的逻辑
说明
1. 基类LifecycleBase实现了Lifecycle接口并实现init、start、stop、destroy等方法
2. init()方法内部模板化初始化流程,抽象具体的实现initInternal()方法
3. start()方法内部模板化启动流程,抽象具体的实现startInternal()方法
4. stop()方法内部模板化停止流程,抽象具体的实现stopInternal()方法
5. destroy()方法内部模板化释放流程,抽象具体的实现destroyInternal()方法
责任链设计模式
责任链设计模式定义:当系统在处理某个请求的时候,请求需要经过很多个节点进行处理,每个节点只关注自己的应该做的工作,做完自己的
工作以后,将工作转给下一个节点进行处理,直到所有节点都处理完毕
工作以后,将工作转给下一个节点进行处理,直到所有节点都处理完毕
tomcat中的责任链设计模式:tomcat中每一个容器都会有一个Pipeline,而一个Pipeline又会具有多个Valve阀门,其中StandardEngine对应
的阀门是StandardEngineValve,StandardHost对应的阀门是StandardHostValve,StandardContext对应的阀门是StandardContextValve,
StandardWrapper对应的阀门是StandardWrapperValve。这里每一Pipeline就好比一个管道,而每一Valve就相当于一个阀门,一个管道可以
有多个阀门,而对于阀门来说有两种,一种阀门在处理完自己的事情以后,只需要将工作委托给下一个和自己在同一管道的阀门即可,第二种阀
门是负责衔接各个管道的,它负责将请求传递给下个管道的第一个阀门处理,而这种阀门叫Basic阀门,它是每个管道中最后一个阀门,上面的
Standard*Valve都属于第二种阀门
的阀门是StandardEngineValve,StandardHost对应的阀门是StandardHostValve,StandardContext对应的阀门是StandardContextValve,
StandardWrapper对应的阀门是StandardWrapperValve。这里每一Pipeline就好比一个管道,而每一Valve就相当于一个阀门,一个管道可以
有多个阀门,而对于阀门来说有两种,一种阀门在处理完自己的事情以后,只需要将工作委托给下一个和自己在同一管道的阀门即可,第二种阀
门是负责衔接各个管道的,它负责将请求传递给下个管道的第一个阀门处理,而这种阀门叫Basic阀门,它是每个管道中最后一个阀门,上面的
Standard*Valve都属于第二种阀门
tomcat责任链处理过程:当用户请求服务器的时候,Connector会接受请求,从Socket连接中根据http协议解析出对应的数据,构造Request和
Response对象,然后传递给后面的容器处理,顶层容器是StandardEngine,StandardEngine处理请求其实是通过容器的Pipeline进行的,而
Pipeline其实最终是通过管道上的各个阀门进行的,当请求到达StandardEngineValve的时候,此阀门会将请求转发给对应StandardHost的
Pipeline的第一个阀门处理,然后以此最终到达StandardHostValve阀门,它又会将请求转发给StandardContext的Pipeline的第一个阀门,这样
以此类推,最后到达StandardWrapperValve,此阀门会根据Request来构建对应的Servelt,并将请求转发给对应的HttpServlet处理。从这里可
以看出其实Tomcat核心处理流程就是通过责任链一步步的组装起来的
Response对象,然后传递给后面的容器处理,顶层容器是StandardEngine,StandardEngine处理请求其实是通过容器的Pipeline进行的,而
Pipeline其实最终是通过管道上的各个阀门进行的,当请求到达StandardEngineValve的时候,此阀门会将请求转发给对应StandardHost的
Pipeline的第一个阀门处理,然后以此最终到达StandardHostValve阀门,它又会将请求转发给StandardContext的Pipeline的第一个阀门,这样
以此类推,最后到达StandardWrapperValve,此阀门会根据Request来构建对应的Servelt,并将请求转发给对应的HttpServlet处理。从这里可
以看出其实Tomcat核心处理流程就是通过责任链一步步的组装起来的
过程梳理
1. 请求被Connector组件接收,创建Request和Response对象
2. Connector将Request和Response交给Container,先通过Engine的Pipeline组件流经内部的每个Valve
3. 请求流转到Host的Pipeline组件中,并且经过内部Valve过滤
4. 请求流转到Context的Pipeline组件中,并且经过内部Valve过滤
5. 请求流转到Wrapper的Pipeline组件中,并且经过内部Valve过滤
6. Wrapper内部的WrapperValve创建FilterChain实例,调用指定的Servlet实例处理请求
7. 返回
嵌入式Tomcat
定义:非传统的部署方式,将tomcat嵌入到主程序中进行运行
优点:灵活部署、任意指定位置、通过复杂的条件判断
Maven集成Tomcat启动分析
分析它的启动
Tomcat7RunnerCli是引导类,有个main方法
进一步分析
Tomcat7RunnerCli主要依靠Tomcat7Runner
分析结论
原来嵌入式启动就是调用了Tomcat的API来实现的
tomcat API接口
实现嵌入式Tomcat的基础
Tomcat本身提供了外部可以调用的API
Tomcat类(在Tomcat6或之前的版本,这个类叫做Embedded)
1. 位于:org.apache.catalina.startup.Tomcat
2. 该类由public修饰,外部可调用
3. 该类有Server、Service、Engine、Connector、Host等属性
4. 该类有init()、start()、stop()、destroy()等方法
5. 了解这个类的时候结合server.xml来理解效果更佳
分析得出的结论
Tomcat类是外部调用Tomcat的接口(看源码的时候有注释的地方要特别注意)
手写嵌入式tomcat思路
1. 新建一个Tomcat对象
2. 设置Tomcat的端口号
3. 设置Context的目录
4. 添加Servlet容器
5. 调用Tomcat对象的start()方法
6. 强制Tomcat等待
Tomcat性能优化
性能优化的三个指标
降低响应时间
提高系统吞吐量(QPS)
提高服务的可用性
性能优化的原则
具体情况具体分析
积少成多
性能优化工具
JConsole
内置的Java性能分析器
JMeter
基于Java的压力测试工具
Tomcat中server.xml的优化
Connector优化
方法:连接器模式改为NIO模式
原因:NIO模式最大化压榨了CPU,把时间片更好利用起来;NIO适合大量长连接
Servlet优化
方法:去掉不必要的资源,例如:JspServlet;Session也可以移除
Valve优化
方法:移除掉AccessLogValve
原因:Valve实现都需要消耗Java应用的计算时间,一般可以使用Nginx计算日志
Context优化
方法:关闭自动加载
原因:自动加载增加运行开销,并且很容易内存溢出
Executor优化
方法:配置线程池
JSP预编译优化
方法:可以使用ant先编译Jsp
方法:Jspservlet开发模式(development)设置为false
SpringBoot中Tomcat的优化
1. 设置线程池
server.tomcat.max-threads
2. 关闭Accesslog日志
server.tomcat.accesslog
0 条评论
下一页