模块组成结构:Tomcat 的核心组件就 Connector 和 Container,一个Connector+一个Container(Engine)构成一个Service,Service就是对外提供服务的组件,有了Service组件Tomcat就能对外提供服务了,但是光有服务还不行,还需要有环境让你提供服务才行,所以最外层的Server就是为Service提供了生存的土壤。
Connector是一个连接器,主要负责接受请求并把请求交给Container,Container就是一个容器,主要装的是具有处理请求的组件。Service主要是为了关联 Container与 Connect,只有两个结合起来才能够处理一个请求。Server负责管理 Service集合,从图中我们可以看到Tomcat可以提供多种服务,那么这些Service就是由Server来管理的。具体工作包括:对外提供一个接口访问Service,对内维护 Service集合,维护 Service集合包括管理 Service声明周期等等。
【红色虚线表示】:应用需要到某个类时,则会按照下面的顺序进行类加载。
当tomcat启动时,会创建几种类加载器:
1 Bootstrap 引导类加载器
加载JVM启动所需的类,以及标准扩展类(位于jre/lib/ext下)
2 System 系统类加载器
加载tomcat启动的类,比如bootstrap.jar,通常在catalina.bat或者catalina.sh中指定。位于CATALINA_HOME/bin下。
3 Common 通用类加载器
加载tomcat使用以及应用通用的一些类,位于CATALINA_HOME/lib下,比如servlet-api.jar
4 webapp 应用类加载器
每个应用在部署后,都会创建一个唯一的类加载器。该类加载器会加载位于 WEB-INF/lib下的jar文件中的class 和 WEB-INF/classes下的class文件。
当应用需要到某个类时,则会按照下面的顺序进行类加载:
1 使用bootstrap引导类加载器加载
2 使用system系统类加载器加载
3 使用应用类加载器在WEB-INF/classes中加载
4 使用应用类加载器在WEB-INF/lib中加载
5 使用common类加载器在CATALINA_HOME/lib中加载
通过对上面tomcat类加载机制的理解,就不难明白 为什么java文件放在Eclipse中的src文件夹下会优先jar包中的class?
这是因为Eclipse中的src文件夹中的文件java以及webContent中的JSP都会在tomcat启动时,被编译成class文件放在 WEB-INF/class 中。
而Eclipse外部引用的jar包,则相当于放在 WEB-INF/lib 中。
因此肯定是 java文件或者JSP文件编译出的class优先加载。
通过这样,我们就可以简单的把java文件放置在src文件夹中,通过对该java文件的修改以及调试,便于学习拥有源码java文件、却没有打包成xxx-source的jar包。
另外呢,开发者也会因为粗心而犯下面的错误。
在 CATALINA_HOME/lib 以及 WEB-INF/lib 中放置了 不同版本的jar包,此时就会导致某些情况下报加载不到类的错误。
还有如果多个应用使用同一jar包文件,当放置了多份,就可能导致 多个应用间 出现类加载不到的错误。
【主要介绍,NIO线程模型】:Poller组件在非阻塞的模式下轮询多个客户端连接,不断检测,处理各种事件。例如检测各个连接是否可读,对于可读的客户端连接尝试进行读取和解析消息报文。
NioEndpoint 组件包含很多子组件:LimitLatch(连接数控制器)Acceptor(套接字接收器)Poller(轮询器)Poller池SocketProcessor(任务处理器)以及Executor(任务执行器)。
✘ LimitLatch(连接数控制器):负责对连接数的控制。初始化同步器的最大限制值,然后每接受一个套接字就将计数器变量+1,每关闭一个套接字,将计数器变量-1,如此一来,一旦技术变量值>最大限制值,则AQS机制将接受线程阻塞,而停止对套接字的接受。直到某些套接字处理完,关闭后重新唤起接受线程往下接受套接字。
Tomcat默认同时接受客户端连接数为200,但可以通过server.xml中的节点的maxConnections属性进行调节,Tomcat BIO模式下的LimitLatch的限制数与线程池的最大线程数密切相关。他们之间的比例1:1。
✘ Acceptor(套接字接收器):负责接收套接字连接并注册到通道连接里面。(接收请求)
✘ Poller(轮询器):负责轮询检查事件列表。
✘ Poller池:包含了若干个轮询组件。
✘ SocketProcessor(任务处理器):任务定义器,将socket扔进线程池前需要定义好任务。主要任务有3个任务:处理套接字并响应客户端,连接数计数器减1,关闭套接字。套接字的处理包括对底层套接字字节流的处理,HTTP协议请求报文的报文的解析(请求头,请求体,请求行等信息的解析),根据请求行解析得到的路径去寻找相应虚拟主机上的Web项目资源,根据处理好的结果组装好HTTP协议响应报文输出到客户端。
✘ Executor(任务执行器):负责处理套接字的线程池。
整体的流程图如下:
【1】Tomcat调优主要从四个方面考虑:1)、吞吐量。2)、Responsetime。 3)、Cpuload。 4)、MemoryUsage。
【2】参数调优:1)、Tomcat启动参数的优化:Tomcat 的启动参数位于tomcat的安装目录\bin目录下,如果你是Linux操作系统就是catalina.sh文件,如果你是Windows操作系统那么你需要改动的就是catalina.bat文件。
✔ Linux系统中catalina.sh文件中添加如下参数(重要参数随后说明):
export JAVA_OPTS="-server -Xms1400M -Xmx1400M -Xss512k -XX:+AggressiveOpts -XX:+UseBiasedLocking
-XX:PermSize=128M -XX:MaxPermSize=256M -XX:+DisableExplicitGC -XX:MaxTenuringThreshold=31
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled
-XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods
-XX:+UseCMSInitiatingOccupancyOnly -Djava.awt.headless=true "
✔ Windowns系统中catalina.bat文件中添加如下参数(重要参数随后说明):
set JAVA_OPTS=-server -Xms1400M -Xmx1400M -Xss512k -XX:+AggressiveOpts -XX:+UseBiasedLocking
-XX:PermSize=128M -XX:MaxPermSize=256M -XX:+DisableExplicitGC -XX:MaxTenuringThreshold=31
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled
-XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods
-XX:+UseCMSInitiatingOccupancyOnly -Djava.awt.headless=true
◀ -Server(重要):只要Tomcat是运行在生产环境中,这个参数必须添加。因为Tomcat默认是java-client模式运行,添加server后表示以真实的production的模式运行,将拥有更大、更高的并发处理能力,更快、更强的JVM垃圾回收机制,可以获得更多的负载和吞吐量等等。
◀ -Xms -Xmx:既JVM内存设置了,把Xms与Xmx两个值设成一样是最优的做法。(否则当内存=Xmx向Xms变化时,CPU高速运转触发垃圾回收机制,严重时会导致系统‘卡壳’,因此一开始我们就把这两个设成一样,使得Tomcat在启动时就为最大化参数充分利用系统的效率。)
※在设这个最大内存即Xmx值时请先打开一个命令行:能够正常显示JDK的版本信息,说明这个值能够用。
◀ -Xmn:设置年轻代大小为512m。整个堆大小=年轻代 + 老年代 + 持久代。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
◀ -Xss:是指设定每个线程的堆栈大小。这个就要依据程序,看一个线程大约需要占用多少内存,可能会有多少线程同时运行等。一般不易设置超过1M,要不然容易出现out ofmemory。
**【3】Tomcat容器内优化:**打开 tomcat安装目录 \conf\server.xml文件。其中如下参数的默认值远远不够我们使用,我们对其进行了更改,更改后的配置如下:
▶ URIEncoding=”UTF-8”:使得tomcat可以解析含有中文名的文件的url。
▶ minSpareThreads:最小备用线程数,tomcat启动时的初始化的线程数。
▶ maxSpareThreads:如果空闲状态的线程数多于设置的数目,则将这些线程中止,减少这个池中的线程总数。
▶ connectionTimeout:网络连接超时时间毫秒数。
▶ maxThreads:Tomcat使用线程来处理接收的每个请求。这个值表示Tomcat可创建的最大的线程数,即最大并发数。
▶ acceptCount:当线程数达到maxThreads后,后续请求会被放入一个等待队列,这个acceptCount是这个队列的大小,如果这个队列也满了,就直接refuse connection。
▶ maxProcessors与minProcessors:在 Java中线程是程序运行时的路径,是在一个程序中与其它控制线程无关的、能够独立运行的代码段。它们共享相同的地址空间。多线程帮助程序员写出CPU最大利用率的高效程序,使空闲时间保持最低,从而接受更多的请求。 通常Windows是1000个左右,Linux是2000个左右。
▶ useURIValidationHack:设成"false",可以减少它对一些url的不必要的检查从而减省开销。
▶ enableLookups:设置为"false",主要为了消除DNS查询对性能的影响我们可以关闭DNS查询,方式是修改server.xml文件中的enableLookups参数值
▶ disableUploadTimeout:允许Servlet容器,正在执行使用一个较长的连接超时值,以使Servlet有较长的时间来完成它的执行,默认值为false
▶ 给Tomcat配置gzip压缩(HTTP压缩)功能:HTTP 压缩可以大大提高浏览网站的速度,它的原理是,在客户端请求网页后,从服务器端将网页文件压缩,再下载到客户端,由客户端的浏览器负责解压缩并浏览。相对于普通的浏览过程HTML、CSS、Javascript、Text ,它可以节省40%左右的流量。更为重要的是,它可以对动态生成的,包括CGI、PHP、JSP、ASP、 Servlet、SHTML等输出的网页也能进行压缩,压缩效率惊人。
1)、compression="on" 打开压缩功能
2)、compressionMinSize="2048" 启用压缩的输出内容大小,这里面默认为2KB
3)、noCompressionUserAgents="gozilla, traviata" 对于以下的浏览器,不启用压缩
4)、compressableMimeType="text/html,text/xml" 压缩类型
▶ redirectPort: 如果我们走https协议的话,我们将会用到8443端口这个段的配置。