zoukankan      html  css  js  c++  java
  • Tomcat 性能优化

    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

    使用较为广泛

  • 相关阅读:
    巴菲特最推崇的10本书
    如何锻炼剑术基本功
    Ubuntu 20.04 LTS, CUDA 11.2.0, NVIDIA 455 and libcudnn 8.0.4
    缘起性空
    Mac 每次都要执行source ~/.bash_profile 配置的环境变量才生效
    Calcite分析 -- Register
    go超时控制有4种写法,你知道吗?
    npm install node-sass报错处理
    IDEA + maven热部署及自动编译不生效问题
    1-STM32+CH395Q(以太网)远程升级篇(自建物联网平台)-STM32通过ch395使用http下载程序文件,升级程序(单片机程序轮训检查更新)
  • 原文地址:https://www.cnblogs.com/2567xl/p/12682347.html
Copyright © 2011-2022 走看看