Tomcat 8.0的併發優化 - 優化server.xml的配置

Tomcat併發量與其配置息息相關, 通常的機器幾百的併發量足矣, 若是設置過高可能引起各類問題, 內存、網絡等問題也能在高併發下暴露出來, 所以, 配置參數的設置很是重要.javascript

1 Tomcat的3種運行模式

1.1 BIO - 同步阻塞IO模式

BIO, 同步阻塞IO, 性能低, 沒有通過任何優化處理和支持.css

服務器實現模式爲一個鏈接一個線程, 即客戶端有鏈接請求時服務器端就須要啓動一個線程進行處理, 若是這個鏈接不作任何事情會形成沒必要要的線程開銷, 固然能夠經過 線程池 機制改善.html

適用場景: BIO方式適用於鏈接數比較小且固定的架構, 這種方式對服務器資源要求比較高, 有併發侷限, JDK1.4以前的惟一選擇.java

1.2 NIO - 同步非阻塞IO模式

是Java SE 1.4及後續版本提供的一種新的IO操做方式(即java.nio包及其子包). Java NIO是一個基於緩衝區、並能提供非阻塞IO操做的Java API, 所以NIO也被當作是non-blocking IO(非阻塞式IO)的縮寫, 它擁有比傳統BIO操做更好的併發性能.web

服務器實現模式爲一個請求一個線程, 即客戶端發送的鏈接請求都會註冊到多路複用器上, 多路複用器輪詢到鏈接有IO請求時才啓動一個線程進行處理.shell

適用場景: 適用於鏈接數較多且鏈接比較時間短(輕操做)的架構, 好比聊天服務器. 這種方式的併發性能侷限於應用中, 編程比較複雜.apache

目前Tomcat 8.x默認運行在NIO模式下.編程

1.3 APR - 可移植運行時模式

APR(Apache Portable Runtime, Apache可移植運行時), 是Apache HTTP服務器的一個支持庫, 它提供了一組映射到底層操做系統的API, 若是操做系統不支持特定功能, APR庫將提供仿真. 所以開發人員可使用APR使程序真正跨平臺移植.瀏覽器

此模式的安裝步驟比較繁瑣, 但卻從操做系統層面解決了異步IO的問題, 能大幅度提升應用性能.tomcat

APR的本質是使用 JNI 技術調用操做系統底層的IO接口, 因此須要提早安裝必要的依賴, 具體方式後續給出.

2 Tomcat的併發配置(配置Connector)

Tomcat的Connector是其接收HTTP請求的關鍵模塊, 能夠經過它來指定IO處理模式, 指定處理該Connector接收到的請求的線程數, 以及其餘經常使用的HTTP策略.

配置路徑: 在 ${TOMCAT_HOME}/conf/server.xml 文件的節點中進行配置.

2.1 使用線程池處理請求

使用線程池, 經過較少的線程資源來處理更多的請求, 從而提升Tomcat的請求處理能力.

前提: 要提早配置至少一個線程池來處理請求, 配置文件爲${TOMCAT_HOME}/conf/server.xml.

其中Executor與Connector同級, 多個Connector可使用同一個線程池來處理請求.

(1) 參考默認鏈接池配置:

<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4"/>

(2) 自定義線程池示例:

<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="200" minSpareThreads="10" maxIdleTime="600000" prestartminSpareThreads="true" maxQueueSize="100" /> 

(3) 線程池參數說明:

name: 線程池名稱.
namePrefix: 建立的每一個線程的名稱前綴, 單獨的線程名稱爲 namePrefix + threadNumber.
maxThreads: 線程池中最大併發線程數, 默認值爲200, 通常建議設置400~ 800 , 要根據服務器配置和業務需求而定.
minSpareThreads: 最小活躍線程數, 也就是核心線程數, 不會被銷燬, 會一直存在.
prestartminSpareThreads: 是否在啓動程序時就生成minSpareThreads個線程, 默認爲false, 即不啓動. 若不設置爲true, 則minSpareThreads的設置就不起做用了.
maxIdleTime: 線程最大空閒時間, 超過該時間後, 空閒線程會被銷燬, 默認值爲6000, 單位爲毫秒.
maxQueueSize: 最大的等待隊列數, 超過則拒絕請求. 默認值爲int類型的最大值(Integer.MAX_VALUE), 等同於無限大. 通常不做修改, 避免發生部分請求未能被處理的狀況.
threadPriority: 線程池中線程的優先級, 默認值爲5, 取值範圍: 1 ~ 10.
className:線程池的實現類, 未指定狀況下, 默認實現類爲 org.apache.catalina.core.StandardThreadExecutor. 要自定義線程池就須要實現 org.apache.catalina.Executor 接口.

2.2 在Connector中使用線程池

Connector是Tomcat接收請求的入口, 每一個Connector都有本身專屬的監聽端口.

<Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />

(1) Connector的參數說明:

redirectPort="8443" # 基於SSL的端口, 在須要基於安全通道的場合, 好比當客戶端的請求協議是HTTPS時, 將該請求轉發到此端口.

minSpareThreads="25" # Tomcat鏈接器的最小空閒Socket線程數, 默認值爲25. 若是當前沒有空閒線程, 且沒有超過maxThreads, 將一次性建立的空閒線程數量. Tomcat初始化時建立的線程數量也是此值.

maxSpareThreads="75" # 最大空閒線程數, 一旦建立的線程超過此值, Tomcat就會關閉再也不須要的Socket線程, 默認值爲50. 線程數能夠大體用 "同時在線用戶數、用戶每秒操做次數、系統平均操做時間" 來計算.

keepAliveTimeout="6000" # 下次請求到來以前, Tomcat保持該鏈接6000ms.

maxKeepAliveRequests="10" # 該鏈接最大支持的請求數, 超過該請求數的鏈接也將被關閉(此時就會返回一個Connection: close頭給客戶端). 1表示禁用長鏈接, -1表示不限制鏈接個數, 默認爲100, 通常設置在100~200之間.

acceptorThreadCount="1" # 用於接收鏈接的線程的數量, 默認值是1. 通常若是服務器是多核CPU時, 須要改配置爲 2.

enableLookups="false" # 是否支持反查域名(即DNS解析), 默認爲true. 爲提升處理能力, 應設置爲false.

disableUploadTimeout="true" # 上傳時是否啓用超時機制, 若爲true, 則禁用上傳超時.

connectionTimeout="20000" # 網絡鏈接超時時間, 默認值爲20000ms, 設置爲0表示永不超時 —— 存在隱患. 一般可設置爲30000ms.

URIEncoding="UTF-8" # 指定Tomcat容器的URL編碼格式.

maxHttpHeaderSize="8192" # HTTP請求頭信息的最大程度, 超過此長度的部分不予處理. 通常設置爲8K便可.

maxPostSize="10485760" # 指定POST請求的內容大小, 單位爲Byte, 默認大小爲2097152(2MB), 10485760爲10M. 若是要禁用限制, 可設置爲-1.

compression="on" # 打開傳輸時壓縮功能.

compressionMinSize="10240" # 啓用壓縮的輸出內容大小, 默認爲2048, 即2KB.

noCompressionUserAgents="gozilla, traviata" # 設置不啓用壓縮的瀏覽器

compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain" # 壓縮的資源類型

(2) 補充說明:

① Tomcat 的壓縮是在客戶端請求服務器對應資源後, 從服務器端將資源文件壓縮, 再輸出到客戶端, 由客戶端的瀏覽器負責解壓縮並瀏覽. 相對於普通的瀏覽過程(如瀏覽HTML、CSS、Javascript和Text), 它能夠節省40%左右的流量. 更爲重要的是, 它也能夠對動態生成的網頁(包括CGI、PHP、JSP、ASP、Servlet、SHTML等)進行壓縮.

② 須要注意的是, 壓縮會增長Tomcat的負擔, 最好採用 Nginx + Tomcat 或 Apache + Tomcat 方式, 將壓縮交由 Nginx / Apache 去完成. 在server.xml的節點配置(還沒有驗證使用):

  • <Service name="Catalina" /> --- 處理全部直接由Tomcat服務器接收的web客戶請求.
  • <Service name="Apache" /> --- 處理全部由Apahce服務器轉發過來的Web客戶請求.
  • <Service name="Nginx" /> --- 處理全部由Nginx服務器轉發過來的Web客戶端請求.

2.2 使用NIO模式處理請求

(1) 默認配置 - BlockingIO模型:

<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />

(2) 關於NIO的說明:

  • 每一個Web客戶端請求對服務器端來講就是一個單獨的線程, 客戶端請求數量增多, 服務器端的處理線程數量也將增長, 對CPU而言, 將會在線程切換上消耗更多的時間. 而NIO則是使用單線程(單個CPU)或只使用少許的多線程(多CPU)來接受Socket, 而由線程池來處理堵塞在 Pipe 或 Queue 中的請求. 這樣的話, 只要OS能夠接受TCP鏈接, Web服務器就能夠處理該請求 -- 大大提升了Web服務器的伸縮性.
  • Tomcat 8 下使用 NIO2, 即 org.apache.coyote.http11.Http11Nio2Protocol 更優.
  • Tomcat 六、7 下使用 NIO, 即 org.apache.coyote.http11.Http11NioProtocol 更優.

(3) NIO模型配置:

<Connector executor="tomcatThreadPool" port="8080" protocol="org.apache.coyote.http11.Http11Nio2Protocol" connectionTimeout="20000" redirectPort="8443" maxPostSize="10485760" acceptorThreadCount="2" />

(4) 參數說明:

executor="..."  # 鏈接器使用的線程池名稱. 
port="..."      # 鏈接端口, URL中指定此端口進行訪問.  
protocol="..."  # 鏈接器使用的請求處理模式.  
redirectPort="8443"   # 基於SSL的端口, 在須要基於安全通道的場合, 好比當客戶端的請求協議是HTTPS時, 將該請求轉發到此8443端口.

2.3 使用APR模式處理請求

能夠簡單地將APR模式理解爲,Tomcat將以JNI的形式調用Apache HTTP服務器的核心動態連接庫, 進行文件讀取或網絡傳輸操做, 從而大大地提升Tomcat對靜態文件的處理性能.

APR是Tomcat上運行高併發應用的首選模式, 同時若是使用HTTPS方式傳輸, 也能夠提高SSL的處理性能.

前面已經提到, APR模式會調用操做系統底層的IO接口, 因此須要安裝必要的依賴.

(1) 安裝OpenSSL:

安裝命令以下:

yum -y install openssl-devel

(2) 安裝APR組件:

  • 第一步: 下載apr與apr-util安裝包:
    下載地址: http://apr.apache.org/download.cgi. 這裏下載apr-1.6.3.tar.gzapr-util-1.6.1.tar.gz, 而後將安裝包上傳至服務器, 這裏上傳至 /usr/local 目錄下.

  • 第二步: 安裝apr:

    cd /usr/local
    tar -zxf apr-1.6.3.tar.gz
    cd apr-1.6.3
    # 配置安裝路徑 ./configure --prefix=/usr/local/apr # 編譯安裝 make make install
  • 第三步: 安裝apr-util:

    cd /usr/local
    tar -zxf apr-util-1.6.1.tar.gz
    cd apr-util-1.6.1
    # 配置安裝路徑 ./configure --prefix=/usr/local/apr-util--with-apr=/usr/local/apr # 編譯安裝 make make install

    錯誤提示:

    可能出現gcc依賴沒有安裝的錯誤, 可經過 yum install gcc 命令安裝.

    若是make過程當中出錯, 解決錯誤後從新安裝前須要執行清理: make clean, 而後再次嘗試make及make install過程.

    若是拋出 xml/apr_xml.c:35:19: error: expat.h: No such file or directory, 說明缺乏了expat庫, 可執行下屬命令安裝: yum install expat-devel.

  • 第四步: 配置環境變量:

    上面安裝完後設置下環境變量:
    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/apr/lib

    或者, 將/usr/local/apr/lib包路徑添加到/etc/ld.so.conf文件中:
    echo "/usr/local/apr/lib" >> /etc/ld.so.conf

(3) 安裝tomcat-native組件:

tomcat-native組件能夠看做是Tomcat與APR交互的中間環節.

  • 第一步: 下載並解壓native安裝包:

    前往 ${TOMCAT_HOME}/bin 目錄下找到tomcat-native.tar.gz, 也可前往官網(http://tomcat.apache.org/download-native.cgi)下載其餘版本, 推薦使用Tomcat自帶的版本, 兼容性有更大保證.

    解壓tomcat-native組件並安裝, 或上傳本身下載的native組件至服務器後, 再執行下述過程:

    cd /usr/local/tomcat/bin/
     tar -zxf tomcat-native.tar.gz
     cd tomcat-native-1.2.14-src/native/

    注意: 1.1.x版本中的目錄是tomcat-native-1.1.x-src/jni/native.

  • 第二步: 安裝組件:

    # 配置安裝參數, 其中java-home可以使用默認環境變量中的配置 ./configure --with-apr=/usr/local/apr --with-ssl=yes make make install

(4) Tomcat整合APR:

  • 第一步: 修改啓動腳本catalina.sh:
    ${TOMCAT_HOME}/bin/catalina.sh 文件的 cygwin=false 前(110行左右)加入下述啓動參數:

    JAVA_OPTS="$JAVA_OPTS -Djava.library.path=/usr/local/apr/lib"
  • 第二步: 修改容器配置文件server.xml:

    查看 ${TOMCAT_HOME}/conf/server.xml 文件, 確保以下監聽器沒有被註釋掉:

    <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  • 修改Connector選項:

    <Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol" maxThreads="150" SSLEnabled="true" > </Connector>

(5) 驗證配置是否成功:

啓動Tomcat, 在 ${TOMCAT_HOME}/logs/catalina.out 文件中查看日誌信息:

  • 若是出現下述內容, 說明APR組件安裝不成功:

    Sep 14, 2018 19:11:20 PM org.apache.catalina.core.AprLifecycleListener init 
    INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path:...
  • 若是出現下述內容, 說明APR組件安裝成功:

    Sep 14, 2018 19:19:47 PM org.apache.catalina.core.AprLifecycleListener init
    INFO: Loaded APR based Apache Tomcat Native library 1.1.27 using APR version 1.6.3.
    Sep 14, 2018 19:19:47 PM org.apache.catalina.core.AprLifecycleListener init
    INFO: APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true].
    Sep 14, 2018 19:19:47 PM org.apache.catalina.core.AprLifecycleListener initializeSSL
    INFO: OpenSSL successfully initialized (OpenSSL 1.0.1e-fips 11 Feb 2013)
    Sep 14, 2018 19:19:47 PM org.apache.coyote.AbstractProtocol init
    INFO: Initializing ProtocolHandler ["http-apr-8080"]
    Sep 14, 2018 19:19:47 PM org.apache.coyote.AbstractProtocol init
    INFO: Initializing ProtocolHandler ["ajp-apr-8009"]
  • Tomcat經過APR模式成功啓動:

    Sep 14, 2018 19:19:56 PM org.apache.coyote.AbstractProtocol start
    INFO: Starting ProtocolHandler ["http-apr-8986"]
    Sep 14, 2018 19:19:56 PM org.apache.coyote.AbstractProtocol start
    INFO: Starting ProtocolHandler ["ajp-apr-8915"]
    Sep 14, 2018 19:19:56 PM org.apache.catalina.startup.Catalina start
    INFO: Server startup in 9421 ms

3 配置AJP鏈接器

AJP(Apache JServer Protocol)是爲 Tomcat 與 HTTP 服務器之間通訊而定製的協議, 能提供較高的通訊速度和效率.

與案例說明: AJP v13 協議是面向包的, Web服務器和Servlet容器經過TCP鏈接來交互, 爲了節省 建立Socket的昂貴代價, Web服務器會嘗試維護一個永久的TCP鏈接到Servlet容器, 並在多個請求與響應週期過程內重用該TCP鏈接.

若是使用Apache架構, 就要用AJP鏈接器, 當Apache接收到動態網頁請求時, 經過在配置中指定的端口號將請求發送給在此端口號上監聽的AJP鏈接器組件.

若是不使用Tomcat + Apache, 而是用其餘架構, 如Tomcat + Nginx, 就須要註銷掉該鏈接器.

<!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->
相關文章
相關標籤/搜索