TCP 线程池
在 tomcat 服务中每一个用户请求都是一个线程,所以可以使用线程池来提高性能、
线程池是什么?
线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后创建线程后自动启动这些任务,线程池线程都是后台线程。每个线程都使用默认的堆栈大小。
它由线程池管理器,工作线程,任务接口,任务队列组成。
在什么情况下使用线程池?
单个任务处理的时间短
将需处理的任务的数量大
有什么好处?
减少在创建和销毁线程上所花的时间以及系统资源的开销
如不使用线程池,有可能造成系统创建大量线程而导致消耗完系统内存以及"过度切换"
开启并使用
[root@tomcat ~]# vim /usr/local/tomcat8/conf/server.xml
57 <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
58 maxThreads="500" minSpareThreads="100" prestartminSpareThreads="true"/>
更改完重启服务效果
参数说明
maxThreads(最大线程数) | 默认值是 200(可适当调整)如果配置了一个 Executor,则该属性的任何值集将被正确记录,但是它将被显示为 -1 |
minSpareThreads(最小活跃线程数) | 默认是 25(调整活跃线程数的时候必须开启下面的参数) |
prestartminSpareThreads(是否在启动时就生成 minSpareThreads 个线程) | 默认是 false,改为 true 则开启 |
MaxQueueSize(最大的等待队列数,超过则请求拒绝) | 基本是无上限,假如你超过最大线程数,就可以给你设置 100 的等待队列数 |
Tomcat 连接器
Connector 是 Tomcat 接收请求的入口,每个 Connector 有自己专属的监听端口
Connector 有两种:HTTP Connector 和 AJP Connector
通用属性(高亮是重点)
属性 | 描述 |
allowTrace | 一个布尔值,可用于启用或禁用 TRACE HTTP 方法。如果未指定,则此属性设置为 false、 |
asyncTimeout | 异步请求的默认超时(以毫秒为单位)。如果未指定,则此属性设置为 10000(10秒)。 |
enableLookups | 设置为 true,如果你想调用 request-getRemoteHost(),以便返回远程客户的实际主机名执行 DNS 查找。设置为 false 跳过 DNS 查找并以字符串形式返回 IP 地址(从而提高性能)。默认情况下,DNS 查找被禁用。 |
maxHeaderCount |
容器允许的请求中的最大标头数,将拒绝包含多于指定限制的标头的请求。值小于 0 表示没有限制。如果未指定,则使用默认值 100。 |
maxParameterCount |
容器将自动解析的参数和值对的最大数量(GET 加 POST)。超出此限制的参数和值对将被忽略。值小于 0 表示没有限制。如果未指定,则使用默认值 10000。请注意,FailedRequestFilter 过滤器可用于拒绝达到限制的请求。 |
maxPostSize |
POST 的最大大小(以字节为单位)将由容器 FORM URL 参数解析处理。可以通过将此属性设置为小于或等于 0 的值来禁用该限制。如果未指定,则此属性设置为 2097152(2兆字节)。 比如你向 tomcat 提交文件的时候大于 2 兆是不能提交的。 |
maxSavePostSize | 在 FORM 或 CLIENT-CERT 身份验证期间,容器将保存/缓冲的 POST 的最大字节数(以字节为单位)。对于这两种类型的身份验证,POST 将在用户通过身份验证之前保存/缓冲。对于 CLIENT-CERT 身份验证,POST 会在 SSL 握手期间进行缓冲,并在处理请求时清空缓冲区。对于 FORM 身份验证,保存 POST,同时将用户重定向到登录表单并保留,直到用户成功进行身份验证或与身份验证请求关联的会话到期为止。可以通过将此属性设置为 -1 来禁用该限制。将该属性设置为零将禁用在身份验证期间保存 POST 数据。如果没有指定, |
parseBodyMethods | 以逗号分隔的 HTTP 方法列表,对于请求主体,将针对与 POST 相同的请求参数进行解析。这在希望支持 PUT 请求的 POST 样式语义的 RESTful 应用程序中很有用。请注意,除了 POST 导致 Tomcat 以违反 servlet 规范意图的方式运行之外的任何设置。这里根据 HTTP 规范明确禁止 HTTP 方法 TRACE。默认是 POST。 |
port | 此连接器将在其上创建服务器套接字并等待传入连接的 TCP 端口号。您的操作系统将只允许一个服务器应用程序侦听特定 IP 地址上的特定端口号。如果使用特殊值 0 (零),则 Tomcat 将随机选择一个空闲端口用于此连接器。这通常仅适用于嵌入式和测试应用程序。 |
protocol |
设置协议以处理传入流量。默认值是 HTTP/1.1 使用自动切换机制来选择阻塞的基于 java 的连接器或基于 APR/native 的连接器。如果 PATH(Windows)或 LD_LIBRARY_PATH(在大多数 unix 系统上)环境变量包含 Tomcat 本机库,则将使用 APR/本机连接器。如果找不到本机库,将使用阻塞的基于 java 的连接器。请注意,APR/本机连接器对 HTTPS 的设置与 java 连接器不同。 要使用显式协议而不是依赖于上述自动切换机制,可以使用以下值: org.apache.coyote.http11.Http11Protocol- 阻止 java 连接器 org.apache.coyote.http11.Http11NioProtocol- 非阻塞 java 连接器 org.apache.coyote.http11.Http11AprProtocol- APR/本机连接器 |
proxyName |
如果在代理配置中使用此连接器,请配置此属性以指定要为其调用返回的服务器名称 request.getServerName()。 |
proxyPort |
如果在代理配置中使用此连接器,请配置此属性以指定要为其调用返回的服务器端口 request.getServerPort()。 |
redirectPort | 如果此连接器支持非 SSL 请求,并且收到匹配<security-constraint>需要 SSL 传输的请求,则 Catalina 将自动将请求重定向到此处指定的端口号。 |
scheme | 将此属性设置为您希望通过调用返回的协议的名称 request.getScheme()。例如,您可以 https 为 SSL 连接器将此属性设置为 ""。默认为 "http"。 |
secure | 将此属性设置为 true 如果您希望调用 request.isSecure() 返回 true 了此连接器接收到的请求。您希望在 SSL 连接器后从 SSL 加速器接收数据的非 SSL 连接器(如加密卡,SSL 设备甚至 Web 服务器)上使用此连接器。默认值为 false。 |
URIEncoding |
这指定在 %xx 解决 URL 之后用于解码 URI 字节的字符编码。如果未指定,将使用 ISO-8859-1. 解决乱码的 |
useBodyEncodingForURI |
这指定了 contentType 中指定的编码是否应该用于 URI 查询参数,而不是使用 URIEncoding。此设置用于与 Tomcat 4.1x 兼容,其中在 contentType 中指定的编码或使用 Request.setCharacterEncoding 方法显式设置的编码也用于 URL 中的参数。默认值为 false。 |
useIPVHosts | 将此属性设置 true 为使 Tomcat 使用收到请求的 IP 地址来确定要将请求发送到的主机。默认值为 false。 |
xpoweredBy | 将此属性设置 true 为使 Tomcat 使用规范中建议的标头来宣传对 Servlet 规范的支持。默认值为 false。 |
标准实施
除了上面列出的常见 Connector 属性之外,标准 HTTP 连接器 (BIO,NIO 和 APR/native)都支持以下属性。
属性 | 描述 |
acceptCount | 当所有可能的请求处理线程都在使用时,传入连接请求的最大队列长度。队列已满时收到的任何请求都将被拒绝。默认值为 100。 |
acceptorThreadCount | 用于接受连接的线程数。在多 CPU 机器上增加此值,尽管您真的不需要超过 2。此外,对于大量非保持连接的连接,您可能还希望增加此值。默认值是 1。 |
acceptorThreadPriority | 接受者线程的优先级。用于接受新连接的线程。默认值为 5(java.lang.Thread.NORM_PRIORITY 常量的值)。 |
address | 对于具有多个 IP 地址的服务器,此属性指定将用于侦听指定端口的地址。默认情况下,此端口将用于与服务器关联的所有 IP 地址。 |
bindOnlnit | 控制连接器使用的套接字何时绑定。默认情况下,它在连接器启动时绑定,在销毁连接器时解除绑定。如果设置为 false,则套接字将在连接器启动时绑定,并在停止时解除绑定。 |
compressableMimeType | 该值是以逗号分隔的 MIME 类型列表,可以使用 HTTP 压缩。默认值为 text/html,text/xml,text/plain。 |
compression |
所述连接器可在试图节省服务器的带宽使用 HTTP/1.1 GZIP 压缩。参数的可接受值是 “off” (禁用压缩),“on” (允许压缩,导致文本数据被压缩),“force” (在所有情况下强制压缩)或数字整数值(这是等效于 “on”,但指定压缩输出之前的最小数据量 )。如果内容长度未知且压缩设置为 "on" 或更具攻击性,则输出也将被压缩。如果未指定,则将此属性设置为 "off"。 注意:在使用压缩(节省带宽)和使用 sendfile 功能(节省 CPU 周期)之间需要权衡。如果连接器支持 sendfile 功能,例如 NIO 连接器,则使用 sendfile 将优先于压缩。症状是静态文件大于 48 kb 将被解压缩。您可以通过设置 useSendfile 连接器的属性来关闭 sendfile ,如下所述,或者更改默认 或 web 应用程序中 DefaultServlet 配置中的 sendfile 使用率阈值。conf/web.xml |
compressionMinSize | 如果压缩设置为 "on",则此属性可用于指定压缩输出之前的最小数据量。如果未指定,则此属性默认为 "2048" |
connectionLinger | 此连接器使用的套接字在关闭时将停留的秒数。默认值是 -1 禁用套接字延迟。 |
connectionTimeout | 接受连接后,此连接器将等待呈现请求 URI 行的毫秒数。使用值 -1 表示没有(即无限)超时。默认值为 60000(即60秒),但请注意 Tomcat 附带的标准 server.xml 将其设置为 20000(即20秒)。除非将 disableUploadTimeout 设置为 false,否则在读取请求正文(如果有)时也将使用超时。 |
connectionUploadTimeout | 指定在数据上载过程中使用的超时(以毫秒为单位)。这仅在 disableUploadTimeout 设置为时生效 false。 |
disableUploadTimeout | 此标志允许 servlet 容器在数据上载期间使用不同的,通常更长的连接超时。如果未指定,则将此属性设置为 true 禁用此较长超时。 |
executor | 对 Executor 元素中的名称的引用。如果设置了此属性,并且存在指定的执行程序,则连接器将使用执行程序,并且将忽略所有其他线程属性。请注意,如果为未为连接器指定共享执行程序,则连接器将使用专用的内部执行程序来提供线程池。 |
禁用 Tomcat AJP 连接器
AJP(Apache JServer Protocol)
AJPV13 协议是面向包的。WEB 服务器 和 servlet 容器通过 TCP 链接 来交互;为节省 SOCKET 创建的昂贵代价,WEB 服务器会尝试维护一个永久 TCP 链接到 servlet 容器,并且在多个请求和响应周期过程会重用链接。
我们一般是使用 Nginx + Tomcat 的架构,所以用不着 AJP 协议,所以把 AJP 连接器禁用。
vim /usr/local/tomcat8/conf/server.xml
<!--
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
-->
/usr/local/tomcat8/bin/shutdown.sh
/usr/local/tomcat8/bin/startup.sh
netstat -lnpt | grep 8009
Tomcat 热部署与热加载
项目开发过程中,经常要改动 tomcat 的 JSP 文件,但是又不想重新启动服务,因为服务器重新启动服务需要花费很长时间,但又想直接获得 debug 结果。
有两种方式:热部署和热加载
热加载:在 server.xml -> context 属性中 设置 reloadable="true"
<Context docBase="/web/crushlinux" path="" reloadable="true" />
热部署:在 server.xml -> context 属性中 设置 autoDeploy="true"
<Context docBase="/web/crushlinux" path="" autoDeploy="true" />
两者区别:
热加载:服务器会监听 class 文件改变,包括 web-inf/class,wen-inf/lib,web-inf/web.xml 等文件,若发生更改,则局部进行加载,不清空 session,不释放内存。开发中用的多,但是要考虑内存溢出的情况。
热部署:整个项目重新部署,包括你重新打上 .war 文件。会清空 session,释放内存。项目打包的时候用的多。
Tomcat JVM 参数优化
JVM 参数的优化
适当调整 tomcat 的运行 jvm 参数可以提升整体性能
JVM 内存模型
1、Java 栈
Java 栈与每一个线程关联的,jvm 在创建每个线程的时候,会分配一定的栈空间给线程使用,它主要用来存储线程执行过程中的局部变量和方法的返回值,以及方法调用上下文,栈空间随着线程的终止而释放。
2、Java 堆
Java 中堆是由所有的线程共享的一块内存区域,堆用来保存各种 java 对象,比如数组,线程对象等。
Java 堆的分区
Young 新生代
新生成的对象都是放在新生代的。新生代的目标就是尽可能快速的回收掉那些生命周期短的对象。
新生代分为三个区:一个 Eden 区,两个 Survivor 区(一般情况)。大部分对象是在 Eden 区中生成,某一个时刻只有其中一个是被使用的,当 Eden 区满了,GC 就会将存活的对象移到空闲的 survivor 区间中,根据 jvm 的策略。在经过几次垃圾收集后,仍然存活于 survivor 的对象将被移动到 old generation 区间。(新生成的对象都在新生代,java 的 GC 会进行垃圾回收你这个对象,但是它发现你这个内存对象还在应用,根据几次的垃圾回收,仍然还有些对象没有被回收的话就给他放到老年代里,放到老年代里不一定不会被 GC 回收)。
Old Generation 老年代
Old generation 区主要保存生命周期长的对象,一般是一些老的对象,当一些对象在 Young 复制转移到一定次数以后,内存对象就会被转移到 Old Generation 区,一般如果系统中用了 application 级别的缓存,缓存中的对象往往会被转移到这一区间,放到老年代里不一定不会被 GC 回收。
Perm 永久代
Perm 主要保存 class,method,filed 对象,并不会被 GC 回收。
Virtual 区:
最大内存和初始内存的差值,就是 virtual 区,新生代,老年代,永久代上都有虚拟区(virtual)
设置区的大小
Jvm 提供了相应的参数来对内存大小进行配置,jvm 中堆被分为了 3 个大的区间,同时 jvm 也提供了一些选项对 young,Oid generation 的大小进行控制。
Total heap
-Xms:指定了 jvm 初始启动以后初始化内存
-Xmx:指定 jvm 堆的最大内存,在 jvm 启动以后,会分配 -Xmx 参数指定大小的内存给 JVM,但是不一定全都使用,jvm 会根据 -Xms 参数来调节真正用于 jvm 的内存。
Xmx-Xms=virtual 大小(之差就是三个 virtual 空间大小)
常用参数
file.encoding | 默认文件编码 |
-Xmx1024m | 设置 JVM 最大可用内存为 1024 MB |
-Xms1024m | 设置 JVM 最小可用内存为 1024 MB,此值可以设置与 -Xmx 相同,以避免每次垃圾回收完成后 JVM 重新分配内存 |
-XX:NewSize | 设置新生代 |
XX:MaxNewSize | 设置最大的新生代大小 |
-XX:PermSize | 设置永久代大小 |
-XX:MaxPermSize | 设置最大永久代大小 |
-XX:NewRatio=4 | 设置新生代(包括 Eden 和 两个 Survivor 区)与终身代的比值(除去永久代)。设置为4,则新生代与 终身代所占比值为 1:4,新生代占整个堆栈的 1/5。 |
-XX:MaxTenuringThreshold=0 | 设置垃圾最大年龄,默认为 15,如果设置为 0 的话,则新生代对象不经过 Survivor 区,直接进去老年代,对于老年代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则新生代对象会在 Survivor 区进行多次复制,这样可以增加对象在新生代的存活时间,增加在新生代即被回收的概论。 |
-XX:+DisableExplicitGC | 这个将会忽略手动调用 GC 的代码使得 System.gc() 的调用就会变成一个空调用,完全不会触发任何 GC。 |
在 tomcat 中设置 JVM 参数
Tomcat 性能取决于内存大小
上策:优化代码
该项需要开发经验足够丰富,对开发人员要求较高。
中策:jvm 优化机制 垃圾回收机制 把不需要的内存回收
优化 jvm-- 优化垃圾回收策略
优化 catalina.sh 配置文件。在 catalina.sh 配置文件中添加以下代码:
# tomcat 分配 1G 内存模板
vim /usr/local/tomcat8/bin/catalina.sh
JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1024m -Xmx1024m -XX:NewSize=512m -XX:MaxNewSize=512m -XX:PermSize=512m -XX:MaxPermSize=512m"
重启服务
/usr/local/tomcat8/bin/shutdown.sh
/usr/local/tomcat8/bin/startup.sh
下策:加足够大的内存
该项的资金投入较大
下下策:每天 0 点定时重启 tomcat
使用较为广泛