性能優化(Tomcat優化)

工做原理

WEB應用服務器javascript

netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'css

返回結果通常以下:
LAST_ACK 5 (正在等待處理的請求數)
SYN_RECV 30
ESTABLISHED 1597 (正常數據傳輸狀態)
FIN_WAIT1 51
FIN_WAIT2 504
TIME_WAIT 1057 (處理完畢,等待超時結束的請求數)html

其餘參數說明:
CLOSED:無鏈接是活動的或正在進行
LISTEN:服務器在等待進入呼叫
SYN_RECV:一個鏈接請求已經到達,等待確認
SYN_SENT:應用已經開始,打開一個鏈接
ESTABLISHED:正常數據傳輸狀態
FIN_WAIT1:應用說它已經完成
FIN_WAIT2:另外一邊已贊成釋放
ITMED_WAIT:等待全部分組死掉
CLOSING:兩邊同時嘗試關閉
TIME_WAIT:另外一邊已初始化一個釋放
LAST_ACK:等待全部分組死掉java

Tomcat內部結構linux

server:指的是整個應用的上下文,也是最頂層的容器,tomcat中全部的東西都在這個server裏邊。
service:指的是一個服務,主要的功能是把connector組件和engine組織起來,使得經過connector組件與整個容器通信的應用可使用engine提供的服
務。
engine:服務引擎,這個能夠理解爲一個真正的服務器,內部提供了多個虛擬主機對外服務。
host:虛擬主機,每個虛擬主機至關於一臺服務器,而且內部能夠部署多個應用,每一個虛擬主機能夠綁定一個域名,並指定多個別名。
context:應用上下文,每個webapp都有一個單獨的context,也能夠理解爲每個context表明一個webapp。
connector:鏈接器組件,能夠配置多個鏈接器支持多種協議,如http,APJ等。nginx

性能的定義及表現web

頂級組件:位於配置層次的頂級,而且彼此間有着嚴格的對應關係。Server
服務類組件:位於Server的下一級。Service
鏈接器組件:鏈接客戶端(能夠是瀏覽器或Web服務器)請求至Servlet容器。http,https,ajp
容器類組件:包含一組其它組件。Engine,Host,Context
被嵌套的組件:位於一個容器當中,但不能包含其它組件。valve,loger,realm,loder,manager,…
集羣類組件: listen,cluster,…redis

Tomcat常見組件:數據庫

服務器(server):Tomcat的一個實例,一般一個JVM只能包含一個Tomcat實例;所以,一臺物理服務器上能夠在啓動多個JVM的狀況下在每個JVM中啓動一個Tomcat實例,每一個實例分屬於一個獨立的管理端口。這是一個頂級組件。
服務(service):一個服務組件一般包含一個引擎和與此引擎相關聯的一個或多個鏈接器。給服務命名能夠方便管理員在日誌文件中識別不一樣服務產生的日誌。一個server能夠包含多個service組件,但一般情下只爲一個service指派一個server。鏈接器類組件:
鏈接器(connectors):負責鏈接客戶端(能夠是瀏覽器或Web服務器)請求至Servlet容器內的Web應用程序,一般指的是接收客戶發來請求的位置及服務器端分配的端口。默認端口一般是HTTP協議的8080,管理員也能夠根據本身的須要改變此端口。還能夠支持HTTPS ,默認HTTPS端口爲8443。同時也支持AJP,即(A)一個引擎能夠配置多個鏈接器,但這些鏈接器必須使用不一樣的端口。默認的鏈接器是基於HTTP/1.1的Coyote。同時,Tomcat也支持AJPJServ和JK2鏈接器。apache

容器類組件:
引擎(Engine):引擎通是指處理請求的Servlet引擎組件,即Catalina Servlet引擎,它檢查每個請求的HTTP首部信息以辨別此請求應該發往哪一個host或context,並將請求處理後的結果返回的相應的客戶端。嚴格意義上來講,容器沒必要非得經過引擎來實現,它也能夠是隻是一個容器。若是Tomcat被配置成爲獨立服務器,默認引擎就是已經定義好的引擎。而若是Tomcat被配置爲Apache Web服務器的提供Servlet功能的後端,默認引擎將被忽略,由於Web服務器自身就能肯定將用戶請求發往何處。一個引擎能夠包含多個host組件。
主機(Host):主機組件相似於Apache中的虛擬主機,但在Tomcat中只支持基於FQDN的「虛擬主機」。一個引擎至少要包含一個主機組件。
上下文(Context):Context組件是最內層次的組件,它表示Web應用程序自己。配置一個Context最主要的是指定Web應用程序的根目錄,以便Servlet容器可以將用戶請求發往正確的位置。Context組件也可包含自定義的錯誤頁,以實如今用戶訪問發生錯誤時提供友好的提示信息。被嵌套類(nested)組件:這類組件一般包含於容器類組件中以提供具備管理功能的服務,它們不能包含其它組件,但有些卻能夠由不一樣層次的容器各自配置。
閥門(Valve):用來攔截請求並在將其轉至目標以前進行某種處理操做,相似於Servlet規範中定義的過濾器。Valve能夠定義在任何容器類的組件中。Valve常被用來記錄客戶端請求、客戶端IP地址和服務器等信息,這種處理技術一般被稱做請求轉儲(request dumping)。請求轉儲valve記錄請求客戶端請求數據包中的HTTP首部信息和cookie信息文件中,響應轉儲valve則記錄響應數據包首部信息和cookie信息至文件中。
日誌記錄器(Logger):用於記錄組件內部的狀態信息,可被用於除Context以外的任何容器中。日誌記錄的功能可被繼承,所以,一個引擎級別的Logger將會記錄引擎內部全部組件相關的信息,除非某內部組件定義了本身的Logger組件。
領域(Realm):用於用戶的認證和受權;在配置一個應用程序時,管理員能夠爲每一個資源或資源組定義角色及權限,而這些訪問控制功能的生效須要經過Realm來實現。Realm的認證能夠基於文本文件、數據庫表、LDAP服務等來實現。Realm的效用會遍佈整個引擎或頂級容器,所以,一個容器內的全部應用程序將共享用戶資源。同時,Realm能夠被其所在組件的子組件繼承,也能夠被子組件中定義的Realm所覆蓋。

優化思路

全局優化思考

非阻塞、傳輸

網絡優化

一、非阻塞,Tomcat8已經取消BIO
四種請求鏈接模型
HTTP/1.1
org.apache.coyote.http11.Http11Protocol 阻塞模式的鏈接協議
org.apache.coyote.http11.Http11NioProtocol 非阻塞模式的鏈接協議
org.apache.coyote.http11.Http11Nio2Protocol 非阻塞模式的鏈接協議
org.apache.coyote.http11.Http11AprProtocol – 本地鏈接協議
二、啓用壓縮,消耗CPU,減少網絡傳輸大小
compression="on"
disableUploadTimeout="true"
compressionMinSize="2048"
compressableMimeType="text/html,text/xml,text/plain,text/css,text/javascript,a
pplication/javascript"
URIEncoding="utf-8

併發優化

鏈接數:maxConnections(排隊數量)
處理線程:maxThreads(操做系統容許多少線程,線程多大會引發切換效能)
等候隊列:acceptCount

底層優化

JVM優化:固定堆內存,多線程併發收集,對象預留新生代,大對象進入老年代,啓用內聯
多實例:多個tomcat實例在一臺機上
操做系統優化:網絡參數,線程數,關閉IPV6,最大文件數
Linux服務器每進程不容許超過1000個線程,聽說六、700線程服務器切換線程就慢下來
查詢命令:ps -eLf | grep java | wc –l
Linux線程棧大小是8M,ulimit –s設置

主體優化

示例

tomcat.conf配置

JAVA_OPTS=「-server –Xmx2048M –Xms2048M –Xmn768m -
XX:TargetSurvivorRatio=90 -XX:PetenureSizeThreshold=1000000 -
XX:MaxTenuringThreshold=30 –XX:+UseParallelGC
–XX:+UseConcMarkSweepGC –XX:ParallelGCThreads=2」

server.conf配置

<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="500" 
//最大併發數,默認設置 200,通常建議在 500 ~ 800,根據硬件設施和業務來判斷
minSpareThreads="100" //Tomcat 初始化時建立的線程數,默認設置 25
prestartminSpareThreads = "true"//在 Tomcat 初始化的時候就初始化 minSpareThreads 的參數值,
若是不等於 true,minSpareThreads 的值就無效
maxQueueSize = "100"//最大的等待隊列數,超過則拒絕請求 />
<Connector executor="tomcatThreadPool" port="8080"
protocol="org.apache.coyote.http11.Http11Nio2Protocol" 
//Tomcat 8 設置 nio2 更好,Tomcat 六、7設置nio更好:org.apache.coyote.http11.Http11NioProtocol
connectionTimeout="20000"
minSpareThreads="100" maxSpareThreads="1000"最大處理鏈接數線程  
minProcessors="100「同時處理請求的最小數
maxProcessors=「1000」 同時處理請求的最大數
maxConnections="1000" redirectPort="8443"
enableLookups="false" //禁用DNS查詢
acceptCount="100" 
//指定當全部可使用的處理請求的線程數都被使用時,能夠放處處理隊列中的請求數,超過這個數的請求將不予處理,默認設置 100
maxPostSize="10485760" //以 FORM URL 參數方式的 POST 提交方式,限制提交最大的大小,默認是2097152(2兆),它使用的單位是字節。10485760 爲 10M。若是要禁用限制,則能夠設置爲 -1。
compression="on" disableUploadTimeout="true" compressionMinSize="2048"
acceptorThreadCount="2" //用於接收鏈接的線程的數量,默認值是1。通常這個指須要改動的時候是由於該服務器是一個多核CPU,若是是多核 CPU 通常配置爲 2.
compressableMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/javascript" URIEncoding="utf-8"  keepAliveTimeout ="0"
/>

server.conf

關閉shutdown端口:<Server port="-1" shutdown="SHUTDOWN">
關閉ajp鏈接:註釋<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
取消訪問日誌Valve閥門:

<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="%h %l %u %t &quot;%r&quot; %s %b" />

ulimit優化 

linux  默認值 open files  和 max user processes  爲 1024

#ulimit -n
1024
#ulimit –u
1024

問題描述: 說明 server 只容許同時打開 1024 個文件,處理1024 個用戶進程
使用ulimit -a 能夠查看當前系統的全部限制值,使用ulimit -n 能夠查看當前的最大打開文件數。
新裝的linux 默認只有1024 ,看成負載較大的服務器時,很容易遇到error: too many open files 。
解決方法:
使用 ulimit –n 65535 可即時修改,但重啓後就無效了。有以下三種修改方式:
 在/etc/security/limits.conf 最後增長:
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535    

內核優化

net.ipv4.tcp_syncookies = 1 開啓SYN Cookies。當出現SYN等待隊列溢出時,啓用cookies來處理,可防範少許SYN攻擊;
net.ipv4.tcp_tw_reuse = 1 開啓重用。容許將TIME-WAIT sockets從新用於新的TCP鏈接,默認爲0
net.ipv4.tcp_tw_recycle = 1 開啓TCP鏈接中TIME-WAIT sockets的快速回收,默認爲0,表示關閉。
net.ipv4.tcp_fin_timeout = 30 若是套接字由本端要求關閉,它決定了它保持在FIN-WAIT-2狀態的時間。
net.ipv4.tcp_keepalive_time = 1200 當keepalive起用的時候,TCP發送keepalive消息的頻度。缺省是2小時
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3 probe 3次(每次30秒)不成功,內核才完全放棄。
tcp_keepalive_time = 7200 seconds (2 hours)
tcp_keepalive_probes = 9
tcp_keepalive_intvl = 75 seconds
net.ipv4.ip_local_port_range = 1024 65000 
用於向外鏈接的端口範圍。缺省狀況下很小:32768到61000,改成1024到65000。
net.ipv4.tcp_max_syn_backlog = 8192 
SYN隊列的長度,默認爲1024,加大隊列長度爲8192,能夠容納更多等待鏈接的網絡鏈接數。
net.ipv4.netdev_max_backlog = 1000 表示進入包的最大設備隊列,默認300,改大
net.core.tcp_max_tw_buckets = 5000 
系統同時保持TIME_WAIT套接字的最大數量,若是超過這個數字,TIME_WAIT套接字將馬上被清除並打印警告信息。默認爲180000,改成 5000。
另外能夠參考優化內核配置:
/proc/sys/net/core/wmem_max 最大socket寫buffer,可參考的優化值:873200
/proc/sys/net/core/rmem_max 最大socket讀buffer,可參考的優化值:873200
/proc/sys/net/ipv4/tcp_wmem TCP寫buffer,可參考的優化值: 8192 436600 873200
/proc/sys/net/ipv4/tcp_rmem TCP讀buffer,可參考的優化值: 32768 436600 873200
/proc/sys/net/ipv4/tcp_mem
一樣有3個值,意思是:配置單位爲頁,不是字節
net.ipv4.tcp_mem[0]:低於此值,TCP沒有內存壓力. 786432
net.ipv4.tcp_mem[1]:在此值下,進入內存壓力階段. 1048576
net.ipv4.tcp_mem[2]:高於此值,TCP拒絕分配socket. 1572864
/proc/sys/net/core/somaxconn 256
listen()的默認參數,掛起請求的最大數量.默認是128.對繁忙的服務器,增長該值有助於網絡性能.
/proc/sys/net/core/optmem_max socket buffer的最大初始化值,默認10K.
/proc/sys/net/ipv4/tcp_retries2 TCP失敗重傳次數,默認值15.減小到5,以儘早釋放內核資源.
net.core.somaxconn = 32768 
socket監聽(listen)的backlog上限,是socket的監聽隊列。好比nginx 定義NGX_LISTEN_BACKLOG默認到511

nginx優化

1. worker_processes 8;    nginx 進程數,建議按照cpu 數目來指定,通常爲它的倍數 (如,2個四核的cpu計爲8)。
2. worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
爲每一個進程分配cpu,上例中將8 個進程分配到8 個cpu,固然能夠寫多個,或者將一個進程分配到多個cpu。
3. worker_rlimit_nofile 65535;
這個指令是指當一個nginx 進程打開的最多文件描述符數目,理論值應該是最多打開文件數(ulimit -n)與nginx 進程數相除,可是nginx 分配請求並非那麼均勻,因此最好與ulimit -n 的值保持一致。

查看linux系統文件描述符的方法:
[root@web001 ~]# sysctl -a | grep fs.file
fs.file-max = 789972
fs.file-nr = 510 0 789972

4. use epoll; 使用epoll 的I/O 模型
5. worker_connections 65535;
每一個進程容許的最多鏈接數, 理論上每臺nginx 服務器的最大鏈接數爲worker_processes*worker_connections。
6. keepalive_timeout 60;keepalive 超時時間。
7. client_header_buffer_size 4k;
客戶端請求頭部的緩衝區大小,這個能夠根據你的系統分頁大小來設置,通常一個請求頭的大小不會超過1k,不過因爲通常系統分頁都要大於1k,因此這裏設置爲分頁大小。

分頁大小能夠用命令getconf PAGESIZE 取得。
[root@web001 ~]# getconf PAGESIZE
4096
但也有client_header_buffer_size超過4k的狀況,可是client_header_buffer_size該值必須設置爲 「 系統分頁大小 」 的整倍數。

8. open_file_cache max=65535 inactive=60s;
這個將爲打開文件指定緩存,默認是沒有啓用的,max 指定緩存數量,建議和打開文件數一致,inactive 是指通過多長時間文件沒被請求後刪除緩存。
9. open_file_cache_valid 80s;這個是指多長時間檢查一次緩存的有效信息。
10. open_file_cache_min_uses 1;open_file_cache 
指令中的inactive 參數時間內文件的最少使用次數,若是超過這個數字,文件描述符一直是在緩存中打開的,如上例,若是有一個文件在inactive 時間內一次沒被使用,它將被移除。

 

集羣優化

當線程數達到250以上,考慮羣集部署
集羣部署須要考慮的兩個問題
Tomcat部署,session共享
Tomcat<4時,可用tomcat內部的集羣session共享
不然採用redis方式集羣

 

Redis session共享

1.tomcat  server.xml配置

<Valve className="tomcat.request.session.redis.RequestSessionHandlerValve"/>
<Manager className="tomcat.request.session.redis.RequestSessionManager"/>

2.jar包
TomcatRedisSessionManager-1.1 .jar
Jredis-2.8.0.jar
Commons-logging-1.2.jar
Commons-pool2-2.4.1.ja

3.安裝redis和配置

redis-data-cache.properties,放在conf.d目錄
redis.hosts=127.0.0.1:6379
redis.cluster.enabled=false
#- redis database (default 0)
#redis.database=0
#- redis connection timeout (default 2000)
#redis.timeout=2000

 

Ab測試

吞吐率(Requests per second):總請求數 / 處理完成這些請求數所花費的時間
併發鏈接數(The number of concurrent users,Concurrency Level):一個用戶可能同時會產生多個會話,也即鏈接數
用戶平均請求等待時間(Time per request):處理完成全部請求數所花費的時間/ (總請求數 / 併發用戶數)服務器平均請求等待時間(Time per request: across all concurrent requests)
計 算 公 式 : 處 理 完 成 所 有 請 求 數 所 花 費 的 時 間 / 總 請 求 數

命令:

ab –n 1000 –c 100 url/
若是隻用到一個Cookie,那麼只需鍵入命令:
ab -n 100 -C key=value http://test.com/
若是須要多個Cookie,就直接設Header:
ab -n 100 -H 「Cookie: Key1=Value1; Key2=Value2」 http://test.com/

 

Jmeter測試

相關文章
相關標籤/搜索