tomcat7關鍵配置和執行緒
1. tomcat 7的一些關鍵引數配置
配置檔案conf/server.xml
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
沒有指定Executor,則使用internal executor,使用的是jdk的執行緒池。本文討論internal executor。
maxThreads – 預設200,最大執行緒數,為執行緒池最大大小(ThreadPoolExecutor的maximumPoolSize)
maxConnections – 最大連線數,預設為maxThreads
acceptCount – 預設100,監聽socket的 backlog。
minSpareThreads – 預設min(10,maxThreads) ,等同於ThreadPoolExecutor的corePoolSize
maxKeepAliveRequests – 預設100,一條長連線服務的http請求最大數目(超過了關閉之),-1表示不受數目影響。
connectionTimeout – 預設60000ms,accept一個連線後,等URI的最長時間。
keepAliveTimeout – 預設為connectionTimeout,一個連線等待下一個http請求到來的最長時間(過期關閉該連線)
2. 主要執行緒
2.1 http監聽執行緒
程式碼為:JIoEndpoint$Acceptor.run\
執行緒名為:http-bio-監聽埠-Acceptor-0
關鍵邏輯
public void run() {
while (running) {
// 連線數到了maxConnections則等待,否則計數器加1
countUpOrAwaitConnection();
Socket socket = accept();
封裝socket為runnable物件(JIoEndpoint$SocketProcessor物件)提交給執行緒池;
}
}
注: 執行緒池使用的佇列為TaskQueue extends LinkedBlockingQueue,其過載了offer方法。所以執行緒池的行為與JDK裡的稍有不同:連線數小於minSpareThreads,來一個連線建個執行緒;minSpareThreads<=連線數<maxThreads
, 有空閒執行緒則新連線用空閒執行緒,無則建個執行緒; 連線數>=maxThreads,則新連線進入佇列。
分析: accept了maxConnections個連線後,1. 如果有新連線過來,則進入監聽套接字的backlog; 2.如果maxConnections>maxThreads,那麼maxConnections-maxThreads個連線進入執行緒池的佇列裡。
分析: nginx反向代理到tomcat時,出現過這麼個情況:nginx部分日誌顯示上游響應時間很長,但是tomcat access log顯示處理時間都很短,這是為什麼呢? 一個可能的原因是socket連線數滿了(並且每個長連線服務100個http後關閉,才處理新連線),新連線進入backlog,nginx的時間表現為backlog呆的時間+執行緒池佇列呆的時間+處理時間即accesslog裡的時間,而tomcat access日誌裡的時間為請求接收直到響應傳送完畢的時間。
conf/server.xml檔案裡,
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt"
pattern="%h %l %u %t "%r" %s %b %D" />
%D為毫秒,即為access log裡的時間
2.2 工作執行緒(執行緒池)
執行緒池在在AbstractEndpoint中建立。
AbstractEndpoint<Socket>
|
JIoEndpoint
工作執行緒程式碼:JIoEndpoint$SocketProcessor.run() \
執行緒名:http-bio-埠號-exec-
關鍵邏輯
public void run() {
try {
處理socket(一次http請求)
} finally {
不關閉socket(長連線),則封裝socket為runnable物件(JIoEndpoint$SocketProcessor物件)提交給執行緒池;
}
}
從單個執行緒來看:服務一個http請求後,將socket放到執行緒池,自己再去任務佇列裡取任務。 這種方式的好處是 連線數多於執行緒數時,所有連線都公平的輪詢得到處理;缺點是socket任務不斷的入隊出隊在頻率極高下也會是個瓶勁。
2.3 命令監聽執行緒
conf/server.xml檔案裡
<Server port="8005" shutdown="SHUTDOWN">
</Server>
接收shutdown 之類的命令