目錄javascript
在線上環境中,咱們常常會遇到相似的問題,就是tomcat 啓動比較慢,查看內存和cpu,io都是正常的,可是啓動很慢,有的時候長達幾分鐘,這究竟是什麼緣由致使的。php
tomcat的啓動須要產生session id,這個產生須要經過java.security.SecureRandom
生成隨機數來實現,隨機數算法使用的是」SHA1PRNG」,但這個算法依賴於操做系統的提供的隨機數據,在linux系統中,這個值又依賴於/dev/random 和/dev/urandomcss
/dev/random :阻塞型,讀取它就會產生隨機數據,但該數據取決於熵池噪聲,當熵池空了,對/dev/random 的讀操做也將會被阻塞。 /dev/urandom: 非阻塞的隨機數產生器,它會重複使用熵池中的數據以產生僞隨機數據。這表示對/dev/urandom的讀取操做不會產生阻塞,但其輸出的熵可能小於/dev/random的。它能夠做爲生成較低強度密碼的僞隨機數生成器,不建議用於生成高強度長期密碼。
咱們經過查看java.security 文件,(個人java版本是1.8.0_131) 發現依賴的是/dev/randomhtml
tomcat 啓動產生session id 最終依賴的是/dev/random ,/dev/random 又依賴於熵池,java
對於熵池,百度百科這樣寫到linux
Linux內核採用熵來描述數據的隨機性。熵(entropy)是描述系統混亂無序程度的物理量,一個系統的熵越大則說明該系統的有序性越差,即不肯定性越大。在信息學中,熵被用來表徵一個符號或系統的不肯定性,熵越大,代表系統所含有用信息量越少,不肯定度越大。計算機自己是可預測的系統,所以,用計算機算法不可能產生真正的隨機數。可是機器的環境中充滿了各類各樣的噪聲,如硬件設備發生中斷的時間,用戶點擊鼠標的時間間隔等是徹底隨機的,事先沒法預測。Linux內核實現的隨機數產生器正是利用系統中的這些隨機噪聲來產生高質量隨機數序列。內核維護了一個熵池用來收集來自設備驅動程序和其它來源的環境噪音。理論上,熵池中的數據是徹底隨機的,能夠實現產生真隨機數序列。爲跟蹤熵池中數據的隨機性,內核在將數據加入池的時候將估算數據的隨機性,這個過程稱做熵估算。熵估算值描述池中包含的隨機數位數,其值越大表示池中數據的隨機性越好。
那麼如何查看熵池 的大小,文件 /proc/sys/kernel/random/entropy_avail 保存着 熵池的大小。/proc/sys/kernel/random/poolsize 保存着熵池的最大容量,單位都是bit。c++
[root@haha cwd]# cat /proc/sys/kernel/random/entropy_avail 146
總結 tomcat 啓動慢的緣由是隨機數產生遭到阻塞,遭到阻塞的緣由是 熵池大小 。web
解決方法:算法
1. 更換產生隨機數的源,(也是tomcat的官方文檔的啓動比較慢的解決辦法) 2. 增大熵池 的值
1 . 更換產生隨機數的源apache
官方文檔連接
由於/dev/urandom 是非阻塞的隨機數產生器,因此咱們能夠從這邊獲取,可是生產的隨機數的隨機性比較低。咱們能夠在 咱們的tomcat啓動腳本(catalina.sh)裏面添加
JAVA_OPTS="$JAVA_OPTS -Djava.security.egd=file:/dev/./urandom"
或者是更改java的java.security 文件,將securerandom.source=file:/dev/random
securerandom.source=file:/dev/./urandom
注意一下,爲何咱們這裏使用的路徑是"/dev/./urandom",而不是 "/dev/urandom",是由於在java 8以前的版本設置了/dev/urandom ,可是實際仍是使用/dev/random,設置爲"/dev/./urandom"才能正常使用 "/dev/urandom" , 這個bug在java8版本已經修復了,若是你是java7版本的話,須要按照上面設置,java8的話能夠不用加 "./"。官方bug連接
2 .增大熵池 的值
要增大熵池 的值首先得你的cpu支持DRNG 特性, 如何查看咱們的服務器的是否支持DRNG特性?
cat /proc/cpuinfo | grep rdrand
若是不支持的話,那麼就只能經過上面的第一種方法來解決了
安裝rngd服務(關於rngd服務的介紹)
yum -y install rng-tools systemctl enable rngd systemctl start rngd
而後咱們進行查看咱們的熵池 的值,會發現變大了
cat /proc/sys/kernel/random/entropy_avail
而後咱們啓動tomcat 會發現啓動速度快不少。
有的時候,咱們tomcat啓動比較慢是由於它須要部署的web應用程序太多,可是其中有些應用程序是咱們不須要的,好比在webapps下的 doc 、example、ROOT 等等,咱們能夠將咱們不須要的webapps刪除,而後再進行發佈,這些不須要的web,不只會佔用咱們的資源,還有多是入侵者的入侵對象。若是咱們想並行啓動多個web應用程序,咱們能夠Host 的屬性 startStopThreads 值設置大於1 ,但這也取決於咱們的服務器是否是多核的。若是是多核的建議調大 startStopThreads 的值,但不超過內核數。
若是是項目比較大的話,咱們使用默認的參數去啓動的tomcat是頗有可能內存不足的,咱們須要設置JVM,將內存調整,JVM 的最大值和最小值建議是不要相差太大(最好一致.)
在啓動腳本catalina.sh加上:
JAVA_OPTS='-server -Xms1024m -Xmx1024m'
具體的內存大小,根據業務調整。
以上就是解決tomcat 啓動慢的問題和解決方案,可根據本身的項目狀況進行使用。後面也會有一篇tomcat 調優的文章,請你們點波關注哦。
### 2.1 使用arp 鏈接器
tomcat 可使用Apache Portable Runtime來提供更高的性能服務。Apache Portable Runtime是一個高度可移植的庫,是Apache HTTP Server 2.x的核心。APR有許多用途,包含高級的io功能(sendfile,epoll,Openssl),系統級別功能(產生隨機數,系統狀態)和進程處理(共享內存,NT管道,unix套接字),它可讓tomcat成爲通用的web服務器,讓java應用做爲一個完整的web服務器更加可行,而不是僅僅做爲後端的技術。
總結:從系統級別來解決異步io的問題,提高性能。
apr 鏈接器須要本身手動安裝,須要如下組件
2.1 yum安裝(建議)
注意apr安裝的版本
yum -y install openssl yum -y install apr yum -y install apr-util yum -y install tomcat-native
2.2 源碼安裝(yum和源碼安裝二選一)
apr源碼編譯 安裝流程:
https://www.cnblogs.com/zscc/p/9349908.html
安裝依賴並下載apr 包
下載地址 : http://archive.apache.org/dist/apr/
yum -y install make gcc gcc-c++ openssl-devel libtool cd /tmp && wget http://archive.apache.org/dist/apr/apr-1.6.5.tar.gz
解壓apr 包
tar -xzf apr-1.6.5.tar.gz && cd apr-1.6.5
預編譯,編譯,安裝
./configure --prefix=/usr/local/apr make make install
native 安裝
解壓native 包 (native 包在tomcat 安裝包裏面 bin下)
cd tomcat/bin && tar -xzf tomcat-native.tar.gz
預編譯,編譯,安裝
cd tomcat-native*/native && ./configure --with-apr=/usr/local/apr make make install
添加環境變量
vim + /etc/profile # 添加環境變量 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/apr/lib # 加載變量 source /etc/profile
2.3 配置apr 鏈接器
vim ./conf/server.xml # 將 Connector 屬性protocol 配置成 apr(org.apache.coyote.http11.Http11AprProtocol) <Connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol" connectionTimeout="20000" redirectPort="8443" />
默認鏈接器爲nio,共有三大鏈接器:
org.apache.coyote.http11.Http11NioProtocol
非阻塞nio鏈接器org.apache.coyote.http11.Http11Nio2Protocol
非阻塞nio2鏈接器org.apache.coyote.http11.Http11AprProtocol
APR鏈接器重啓tomcat
APR 測試·
tomcat,jvm使用默認配置進行測試,使用nio 鏈接器 共1000次請求100併發
在nio鏈接器時,我屢次嘗試使用150併發共1000請求去測試,發現一直成功不了,可是當我使用apr鏈接時,
100併發
150 併發
咱們能夠對比發現,在使用APR鏈接器在處理高併發請求的時候是有必定的優點的,可以提高web應用的處理請求能力。
屬性 | 描述 | 建議設置的值 |
---|---|---|
maxThreads | tomcat能建立來處理請求的最大線程數,默認值爲200 | 500 |
minProcessors | 啓動時建立的線程數(最小線程數) | |
acceptCount | 指定當全部可使用的處理請求的線程數都被使用時,能夠放到隊列中的請求數,,超過這個數的請求將拒絕鏈接 默認值爲100 | 500 |
compressibleMimeType | 該值用來指定哪些文件類型的文件能夠進行壓縮,默認值爲:text/html,text/xml,text/plain,text/css,text/javascript,application/javascript | |
compression | 開啓gzip 壓縮,能夠接受的值是 "off"(禁用壓縮),"on"(開啓壓縮),"force(強制壓縮)","1-9"(等效於開啓壓縮,而且設定壓縮等級),開啓了壓縮,也就意味着要佔用更多的cpu資源 | on |
keepAliveTimeout | 指connector兩個HTTP請求直接的等待時間,超過該時間沒有接收到第二個HTTP請求就關閉鏈接,默認是使用connectionTimeout 的值,單位爲毫秒 | 30000 |
processorCache | 進程緩衝器,默認值是maxThreads的值,使用好該值能夠提高併發請求。 | 500 |
以上設置只是參考,建議根據本身的業務進行設置,並測試。
有不少參數tomcat 默認就給我設置好了,好比URIEncoding,connectionTimeout,這些值都有默認值的,詳細見文章tomcat 配置文件server.xml 詳解 Connector Engine Host Context
屬性 | 描述 | 建議配置 |
---|---|---|
startStopThreads | 指Host用於啓動Context的線程數,默認值爲1,若是多核建議配置爲核心數-1 | 2 |
unpackWARs | 默認爲true,若是設置爲true 表示將web應用程序war包解壓,false表示直接從war文件運行。設置爲false對性能有必定的影響 | true |
若是咱們想並行啓動多個web應用程序,咱們能夠Host 的屬性 startStopThreads 值設置大於1 ,但這也取決於咱們的服務器是否是多核的。若是是多核的建議調大 startStopThreads 的值,但不超過內核數。
若是咱們使用的是自動發佈的形式,也就是替換war包的形式,在tomcat安裝文章中介紹了與jenkins 集成實現的,那麼容易出現的一個問題就是 上一次的線程沒有關閉掉,就啓動了新的版本,那麼上一個版本的線程還存在,也還在佔用着資源,這個問題的緣由有多是代碼的問題,咱們能夠嘗試直接使用 catalina.sh 腳本stop ,你會發現stop 掉後,該tomcat 的線程仍是存在的,那麼出現這種狀況很大一部分緣由就是 在java代碼中有非守護線程,也就是java代碼未將線程設置爲守護線程,致使了tomcat 進行stop 不掉該線程的緣由。那麼這種狀況有可能會致使兩個web應用(新老版本)都在使用,那這這個應用的定時任務可能就會執行兩次,就容易致使生產事故。
這種問題,一方面會佔用服務器資源。另一方面還會容易致使生產事故,咱們能夠用jstack 分析下未中止的線程,並和開發區解決這個線程關閉不掉的問題。
AJP協議在tomcat中的做用就是將該服務與其它HTTP服務器集成,咱們通常項目中,沒有用到該鏈接器,因此咱們能夠禁用該鏈接器
在前面啓動內存不足就談到了
JAVA_OPTS='-server -Xms1024m -Xmx1024m'
具體的JVM設置與調優見文章 JVM 調優-給你的java應用看看病
其餘的調優選項,若是你有多個connector 的話,那麼你還能夠經過 Executor 的屬性進行調優。