2011-06-13 187 views
3

我正在使用JBoss AS 4.2.3以及seam框架。我的CPU使用率隨着用戶數量的增加而增加,僅有80個用戶使用率達到99%。我們還使用Hibernate,EJB3和Apache與mod_jk進行負載平衡。JBoss CPU使用率問題

當我拿着線程轉儲所有可運行的線程正在做以下的跟蹤同一個活動:

at java.net.SocketInputStream.socketRead0(Native Method) 
at java.net.SocketInputStream.read(SocketInputStream.java:129) 
at org.apache.coyote.ajp.AjpProcessor.read(AjpProcessor.java:1012) 
at org.apache.coyote.ajp.AjpProcessor.readMessage(AjpProcessor.java:1091) 
at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:384) 
at org.apache.coyote.ajp.AjpProtocol$AjpConnectionHandler.process(AjpProtocol.java:366) 
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:446) 
at java.lang.Thread.run(Thread.java:662) 

我無法與堆棧跟蹤來解釋這一點。此外,我發現,即使用戶已註銷,CPU利用率仍會繼續與處於相同狀態的線程相同。

回答

1

這些線程試圖從Socket連接讀取。在這種情況下,他們正在等待下一個請求從Apache的mod_jk發送到服務器。這很正常,它們可能不是你CPU使用率的原因。

在這一點上,你真的需要去通過一個分析器來運行你的應用程序。

如果你無法在系統上運行一個分析器(例如它是一個生產盒),下一個最好的事情是開始每隔幾秒鐘進行一次堆棧轉儲,然後通過手工匹配線程ID。您需要查找正在運行代碼的線程,並且在轉儲之間似乎沒有更改。

這是一項非常乏味的任務,並不總是會得到清晰的結果,但是如果沒有探查器或某種儀器,您將無法找到所有CPU將要發生的位置。

+0

是否有可能我的請求太重以至於始終讀取它們。另外,我的apache和jboss實例位於相同的物理盒子中。 – Dwarakanath 2011-06-13 13:10:34

+0

如果你繼續採用堆棧轉儲,你會看到更多的活動,而不僅僅是'socketRead0' jboss至少會有其他的東西。最殘酷的事實是,首先需要關注應用程序中的線程,jboss和apache以及jboss的線程並不會真正增加事物授權方案中的巨大CPU開銷。 – 2011-06-13 13:21:54

+1

通常我會期待等待的線程處於狀態WAITING,然後是Tomcat(或JBoss)等待'org.apache.tomcat.util.net.JIoEndpoint $ Worker'。我曾見過其中一個AJP deamon線程在狀態爲RUNNABLE的socketRead0中「卡住」的情況,其中所有其他狀態都處於上述WAITING狀態。 – 2011-06-13 13:24:00

0

審查的Apache和JBoss之間的AJP的配置,如https://developer.jboss.org/wiki/OptimalModjk12Configuration

問題

JBoss應用的(Tomcat)的server.xml中AJP描述片段:

<Connector port="8009" address="${jboss.bind.address}" protocol="AJP/1.3" 
     emptySessionPath="true" enableLookups="false" redirectPort="8443" ></Connector> Apache's httpd.conf: 

<IfModule prefork.c> 
StartServers  8 
MinSpareServers 5 
MaxSpareServers 20 
ServerLimit  256 
MaxClients  256 
MaxRequestsPerChild 4000 
</IfModule> 

以上配置,在負載下,可能會導致mod_jk非常慢,並且不響應,導致http錯誤,並導致半連接的 連接。出現這些問題的原因可能是因爲沒有指定用於照顧孤立連接的連接超時 ,沒有在worker.properties中定義的 錯誤處理屬性,也沒有在Apache和Tomcat中設置 連接限制。

但是這麼多的線程可能來自另一個來源。如上所述here

的懸掛Socket.read(最常見的情況)是一種高 處理時間或遠程服務提供商的不健康狀態。 這意味着您需要立即與服務提供商 聯繫支持團隊,以確認他們的系統是否面臨某些 減速條件。

你的一個應用服務器的線程應該被釋放,一旦遠程 服務提供商的系統問題得以解決,但往往你會 需要重新啓動服務器實例(Java虛擬機),以清除所有 掛線程;特別是如果你缺乏適當的超時執行 。

其他較少見的原因包括:使增加經過時間

  • 巨大響應數據讀/消耗的插座的InputStream例如如非常大的XML數據。通過分析響應數據的大小可以很容易地證明這可以是
  • 網絡延遲導致從服務提供商到Java EE生產系統的數據傳輸所花費的時間增加。這可以 運行您的生產 服務器之間和服務提供商的一些網絡嗅探器,並確定任何重大的滯後/延遲 問題

無論是你的問題,要做的第一件事就是檢查你的超時被證明組態!

你可以做什麼?

你需要爲Jboss和Apache做一些配置。

的JBoss側

的server.xml主要關心的是設定爲ConnectionTimeout 它設置底層套接字的SO_TIMEOUT。因此,當 中的連接在012xxconnectionTimeout指定的時間內沒有請求時,則連接將中斷。這是必要的 ,因爲如果連接沒有被用於特定時間段 時間那麼它有可能在mod_jk結束時是半關閉的。

如果連接沒有關閉,將會出現線程膨脹 ,這會隨着時間的流逝而擊中Tomcat中的maxThreads計數,那麼Tomcat將不能接受任何新的連接。連接超時 600000(10分鐘)是一個很好的開始。可能存在 這種情況,其中連接沒有被足夠快地回收,在這種情況下, 可以將connectionTimeout降低到60000分鐘或10分鐘。

在Tomcat中設置connectionTimeout時,mod_jk也應該設置爲 connect_timeout/prepost_timeout,它允許檢測到Tomcat連接已關閉並阻止重試請求。我們假設 服務器是單核心機器。如果它是四核,那麼我們 可以將該值推到800,並且更多取決於RAM和其他 機器規格。

<Connector port="8009" 
      address="${jboss.bind.address}" 
      emptySessionPath="true" 
      enableLookups="false" 
      redirectPort="8443" 
      protocol="AJP/1.3" 
      maxThreads="200" 
      connectionTimeout="600000"></Connector> 

阿帕奇側

worker.properties文件

見註釋行內。

worker.list=loadbalancer,status 

worker.template.port=8009 
worker.template.type=ajp13 
worker.template.lbfactor=1 
#ping_timeout was introduced in 1.2.27 
worker.template.ping_timeout=1000 
#ping_mode was introduced in 1.2.27, if not 
#using 1.2.27 please specify connect_timeout=10000 
#and prepost_timeout=10000 as an alternative 
worker.template.ping_mode=A 
worker.template.socket_timeout=10 
#It is not necessary to specify connection_pool_timeout if you are running the worker mpm 
worker.template.connection_pool_timeout=600 

#Referencing the template worker properties makes the workers.properties shorter and more concise 
worker.node1.reference=worker.template 
worker.node1.host=192.168.1.2 

worker.node2.reference=worker.template 
worker.node2.host=192.168.1.3 

worker.loadbalancer.type=lb 
worker.loadbalancer.balance_workers=node1,node2 
worker.loadbalancer.sticky_session=True 

worker.status.type=status 

在上述workers.properties的關鍵點是我們增加了限制 爲mod_jk的使得連接。使用基本配置時,套接字 超時默認爲無限。其他重要屬性是 ping_mode和ping_timeout,它們處理探測連接的錯誤和connection_pool_timeout,必須設置爲 當使用prefork mpm時,server.xml的connectionTimeout。當這兩個值相同時,連接在x 時間內處於非活動狀態後,mod_jk和Tomcat中的連接將同時關閉,並在 處關閉,從而阻止半關閉連接。

Apache配置

記下的AJP連接maxThreads應 在Apache的httpd.conf設置的MaxClients一致。 MaxClients需要在Apache的正確模塊中設置爲 。

這可以通過運行httpd -V確定:

# httpd -V 

Server version: Apache/2.2.3 
Server built: Sep 11 2006 09:43:05 
Server's Module Magic Number: 20051115:3 
Server loaded: APR 1.2.7, APR-Util 1.2.8 
Compiled using: APR 1.2.7, APR-Util 1.2.7 
Architecture: 32-bit 
Server MPM:  Prefork 
    threaded:  no 
    forked:  yes (variable process count) 
Server compiled with.... 
-D APACHE_MPM_DIR="server/mpm/prefork" 
-D APR_HAS_SENDFILE 
-D APR_HAS_MMAP 
-D APR_HAVE_IPV6 (IPv4-mapped addresses enabled) 
-D APR_USE_SYSVSEM_SERIALIZE 
-D APR_USE_PTHREAD_SERIALIZE 
-D SINGLE_LISTEN_UNSERIALIZED_ACCEPT 
-D APR_HAS_OTHER_CHILD 
-D AP_HAVE_RELIABLE_PIPED_LOGS 
-D DYNAMIC_MODULE_LIMIT=128 
-D HTTPD_ROOT="/etc/httpd" 
-D SUEXEC_BIN="/usr/sbin/suexec" 
-D DEFAULT_PIDLOG="logs/httpd.pid" 
-D DEFAULT_SCOREBOARD="logs/apache_runtime_status" 
-D DEFAULT_LOCKFILE="logs/accept.lock" 
-D DEFAULT_ERRORLOG="logs/error_log" 
-D AP_TYPES_CONFIG_FILE="conf/mime.types" 
-D SERVER_CONFIG_FILE="conf/httpd.conf" 

它告訴我的服務器MPM爲prefork的。這並不總是準確的,因此您還應該查看/ etc/sysconfig/httpd的輸出爲 ,看下面的行是否存在:HTTPD =/usr/sbin/httpd.worker。如果 它被註釋掉你正在運行prefork,否則如果沒有註釋 工人。

的httpd.conf:

<IfModule prefork.c> 
StartServers  8 
MinSpareServers 5 
MaxSpareServers 20 
MaxClients  200 
MaxRequestsPerChild 0 
</IfModule> 

或者Apache是​​否使用工人,這是

<IfModule worker.c> 
StartServers   2 
MaxClients   200 
MinSpareThreads  25 
MaxSpareThreads  75 
ThreadsPerChild  25 
MaxRequestsPerChild 0 
</IfModule> 

MaxRequestsPerChild值0,這是建議值使用的mod_jk 作爲時的mod_jk保持開放的持久連接。 上述配置中的關鍵值是MaxClients和MaxRequestsPerChild,其餘的值保留爲默認值。請注意,MaxRequestsPerChild 建議爲0,但該值可能需要大於0 ,具體取決於Apache是​​否也用於其他模塊,尤其是在 資源泄漏的情況下。

在鏈接中,您可以找到另一個配置來優化更多此場景。