一: 生命周期
Tomcat 为了方便管理组件和容器的生命周期,定义了从创建、启动、到停止、销毁共 12 中状态,tomcat 生命周期管理了内部状态变化的规则控制,组件和容器只需实现相应的生命周期 方法即可完成各生命周期内的操作(initInternal、startInternal、stopInternal、 destroyInternal)。
Tomcat 的生命周期管理引入了事件机制,在组件或容器的生命周期状态发生变化时会通 知事件监听器,监听器通过判断事件的类型来进行相应的操作。事件监听器的添加可以在 server.xml 文件中进行配置。
Tomcat 各类容器的配置过程就是通过添加 listener 的方式来进行的,从而达到配置逻辑与 容器的解耦。
- EngineConfig:主要打印start和stop事件的debug日志
- HostConfig:主要处理部署应用,解析应用 META-INF/context.xml 并创建应用的 Context
- ContextConfig:主要解析并合并 web.xml,扫描应用的各类 web 资源 (filter、servlet、listener)
请求的处理流程
容器的责任链模式:
- 请求被Connector组件接收, 创建Request和Response对象。
- Connector将Request和Response交给Container,先通过Engine的pipeline组件流经内部的每个Valve。
- 请求流转到Host的pipeline组件中, 并且经过内部Valve的过滤。
- 请求流转到Context的pipeline组件中, 并且经过内部的Valve的过滤。
- 请求流转到Wrapper的pipeline组件中, 并且经过内部的Valve的过滤。
- Wrapper内部的WrapperValve创建FilterChain实例, 调用指定的Servlet实例处理请求。
- 返回结果
2: 类加载机制
双亲委派模型:
- Bootstrap ClassLoader :启动类加载器,负责加载 Java 的核心类,它不是 java.lang.ClassLoader 的子类,而是由 JVM自身实现,null c,c++实现的,加载jre/lib
- Extension ClassLoader :扩展类加载器,扩展类加载器的加载路径是 JDK 目录下 jre/lib/ext 。扩展加载器的 #getParent() 方法返回 null ,实际上扩展类加载器的父类加载器是启动类加载器。
- System ClassLoader :系统(应用)类加载器,它负责在 JVM 启动时加载来自 Java 命令的 -classpath 选项、java.class.path 系统属性或 CLASSPATH 环境变量所指定的 jar 包和类路径。程序可以通过 #getSystemClassLoader() 来获取系统类加载器。系统加载器的加载路径是程序运行的当前路径。
ClassLoader#loadClass(java.lang.String, boolean)
jvm如何确定一个class唯一性: 全类名(包名+类名)+ classLoader的id
类的加载过程:
类加载器:
Tomcat 拥有不同的自定义类加载器,以实现对各种资源库的控制。 Tomcat 主要用类加载器解决以下 4 个问题:
- 同一个 Web 服务器里,各个 Web 项目之间各自使用的 Java 类库要互相隔离。
- 同一个 Web 服务器里,各个 Web 项目之间可以提供共享的 Java 类库 。
- 为了使服务器不受 Web 项目的影响,应该使服务器的类库与应用程序的类库互相独立。
- 对于支持 JSP 的 Web 服务器,应该支持热插拔(HotSwap)功能 。
Tomcat提供了四组目录供用户存放第三方类库:
- 放置在/common目录中:类库可被Tomcat和所有的 Web应用程序共同使用。
- 放置在/server目录中:类库可被Tomcat使用,对所有的Web应用程序都不可见。
- 放置在/shared目录中:类库可被所有的Web应用程序共同使用,但对 Tomcat自己不可见。
- 放置在/WebApp/WEB-INF目录中:类库仅仅可以被此Web应用程序使用,对 Tomcat和其他Web应用程序都不可见。
Tomcat自定义了多个类加载器,CommonClassLoader、CatalinaClassLoader、SharedClassLoader和WebappClassLoader则是Tomcat自己定义的类加载器,它们分别加载/common/、/server/、/shared/和/WebApp/WEB-INF/中的Java类库。其中WebApp类加载器和Jsp类加载器通常会存在多个实例,每一个Web应用程序对应一个WebApp类加载器,每一个JSP文件对应一个Jsp类加载器。
LauncherHelper
3: 线程模型
Tomcat对IO模型支持
IO模型描述BIO (JIoEndpoint)同步阻塞式IO,即Tomcat使用传统的java.io进行操作。该模式下每个请求都会创建一个线程,对性能开销大,不适合高并发场景。优点是稳定,适合连接数目小且固定架构。NIO(NioEndpoint)同步非阻塞式IO,jdk1.4 之后实现的新IO。该模式基于多路复用选择器监测连接状态再同步通知线程处理,从而达到非阻塞的目的。比传统BIO能更好的支持并发性能。Tomcat 8.0之后默认采用该模式AIO (Nio2Endpoint)异步非阻塞式IO,jdk1.7后之支持 。与nio不同在于不需要多路复用选择器,而是请求处理线程执行完成进行回调调知,继续执行后续操作。Tomcat 8之后支持。APR(AprEndpoint)全称是 Apache Portable Runtime/Apache可移植运行库),是Apache HTTP服务器的支持库。可以简单地理解为,Tomcat将以JNI的形式调用Apache HTTP服务器的核心动态链接库来处理文件读取或网络传输操作。使用需要编译安装APR 库
通过修改server.xml中protocol配置来指定IO模型
<Connector protocol="HTTP/1.1">
Tomcat7连接器比较
Tomcat8连接器比较
JIOEndpoint原理
NioEndpoint原理
4: 性能调优
Tomcat启动参数
一般生产环境中Tomcat 程序目录和部署目录分开的,只需要在启动时指定CATALINA_HOME 与 CATALINA_BASE 参数即可。
启动参数描述说明JAVA_OPTSjvm 启动参数 , 设置内存 编码等 -Xms100m -Xmx200m -Dfile.encoding=UTF-8JAVA_HOME指定jdk 目录,如果未设置从java 环境变量当中去找。CATALINA_HOMETomcat 程序根目录CATALINA_BASE应用部署目录,默认为$CATALINA_HOMECATALINA_OUT应用日志输出目录:默认$
CATALINA_BASE/logCATALINA_TMPDIR应用临时目录:默认:$CATALINA_BASE/temp
并发相关参数
Connector属性:
名称描述address对于具有多个IP地址的服务器,此属性指定将用于监听指定端口的地址。默认情况下,连接器将侦听所有本地地址compression是否使用HTTP/1.1 GZIP压缩来节省服务器带宽,默认offconnectionTimeout客户端发起连接到服务端接收为止,中间最大的等待时间connectionUploadTimeout指定数据上传过程中使用的超时时间(以毫秒为单位)。只有将disableUploadTimeout设置为false时才会生效。disableUploadTimeouttrue 则使用
connectionTimeoutenableLookups如果需要调用request.getRemoteHost()来执行DNS查找以返回远程客户端的实际主机名,则将其设置为true。设置为false可以跳过DNS查找并以字符串形式返回IP地址(从而提高性能)。默认情况下,DNS查找是禁用的executorTerminationTimeoutMillis私有内部执行程序在继续停止连接器之前等待请求处理线程终止的时间。如果没有设置,默认值为5000(5秒)。acceptCount使用所有可能的请求处理线程时传入连接请求的最大队列长度。队列满时接收到的任何请求都将被拒绝。默认值是100。maxConnections服务器在任何给定时间将接受和处理的最大连接数。当到达此数值时,服务器将接受(但不处理)另一个连接。此附加连接将被阻塞,直到正在处理的连接数量低于maxConnections,此时服务器将再次开始接受和处理新连接。注意,一旦达到了限制,操作系统仍然可以基于acceptCount设置接受连接。默认值因连接器类型而异。对于NIO和NIO2,缺省值是10000。maxHttpHeaderSize请求和响应HTTP头的最大大小,默认8kmaxThreads可以处理的并发请求的最大数量,默认200 ,如果使用了executor,将被忽略minSpareThreads始终保持运行的最小线程数,默认10,如果使用了executor,将被忽略
Executor属性:
名称描述daemon是否是守护线程,默认truenamePrefix由执行程序创建的每个线程的名称前缀。单个线程的线程名将是namePrefix+threadNumbermaxThreads池中活动线程的最大数量,默认为200minSpareThreads保持活动的线程的最小数量(空闲和活动),默认为25maxIdleTime一个空闲线程关闭前的毫秒数,除非活动线程数小于或等于minSpareThreads。默认值为60000(1分钟)maxQueueSize在拒绝可运行任务之前,可以排队等待执行的最大可运行任务数。默认值是
Integer.MAX_VALUEprestartminSpareThreadsminSpareThreads是否应该在启动执行程序时启动,默认值都是false
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。