“沒有最優,只有平衡”。因此在配置與調優之前,我總喜歡先介紹理論基礎。
Apusic AS V5.1的線程池只是個池服務,池中沒有具體的線程,池中管理的線程是與業務相關的服務啟動后并加入的。線程池只負責管理池中線程的數量和生命周期,從而簡化了Apusic應用服務器的池管理框架。驗證線程池的方法有以下幾種:
1. 在Windows下啟動Apusic V5.1的mydomain域,里面不帶任何自啟動線程的應用,在命令行窗口下按Ctrl+Break結果見附一(各人機器可能有所不同),發現系統沒有任何與線程池相關的線程啟動。打開IE訪問一個HTML頁面,再Ctrl+Break結果見附二,發現多了兩個線程:Running HTTPHandler-1(HTTP服務線程)和Idle MuxHandler-1(多路復用服務線程),Mux空閑是因為多路復用的分配工作已經完成,而HTTP忙是因為HTTP服務剛結束,KeepAlive仍然保持著??梢娋€程池啟動時是空的,當有服務時才生成線程加入到池中,池主要負責線程的數量和生命周期。這樣的設定可以避免受到攻擊時無限制地創建線程而導致系統宕機;或者合理使用機器的性能,平衡分配不同線程池中的線程數量。
2. 在apusic.conf文件中自定義一個線程池Test,然后可以在自己的代碼中使用Apusic AS提供的池管理技術,當然如果沒有使用這個池系統也仍然可以正常運行,因為這只是個池服務,只是沒有線程加入到池中而已。
<SERVICE
??? CLASS="com.apusic.util.ThreadPoolService"
??? NAME="Apusic:service=ThreadPool,name=Test"
??? >
??? <ATTRIBUTE NAME="MaxThreads" VALUE="150"/>
??? <ATTRIBUTE NAME="Priority" VALUE="5"/>
??? <ATTRIBUTE NAME="ServicePriority" VALUE="H"/>
??? <ATTRIBUTE NAME="IdleTimeout" VALUE="300"/>
??? <ATTRIBUTE NAME="MaxSpareThreads" VALUE="30"/>
??? <ATTRIBUTE NAME="MinSpareThreads" VALUE="5"/>
??? <ATTRIBUTE NAME="MaxQueueSize" VALUE="500"/>
</SERVICE>
3. 只提供default池,其他池都注釋掉,系統依然能夠正常運行,也是因為池與服務之間不是緊耦合,沒有的相關的池,所有的線程統一使用default池,如果有自己的池就通過自定義池處理。
注意:如果有了自定義池,池中線程數達到最大值后,系統不會使用defalut池來處理的,從而充分保證相應服務池的控制。
例如:定義了HTTPHandler池,當HTTPHandler線程達到最大值后,其他只能在Queue中排隊,如果Queue也滿了,則其他請求將會被拒絕。
Apusic AS自己使用了五種池:
default:Apusic AS系統默認的線程池
MuxHandler:多路復用的線程池,主要是將請求向不同的服務,如:HTTP、JMS、ORB等服務上分配
HTTPHandler:HTTP服務的線程池
JMSHandler:JMS服務的線程池
ORBHandler:ORB服務的線程池
了解了線程池的基本概念,就可以知道在線程池配置中default池最為重要,其他池可以根據需要增加或者注釋,所有線程池的配置參數都是相同的,具體的配置參數解釋如下:
MaxThreads:線程池中能夠運行的最大線程數,也就是提供服務的線程數,-1代表無限制
MinSpareThreads,MaxSpareThreads:線程池中最?。畲罂臻e的線程數,當線程數符合這個區間時無論空閑多久都不會被銷毀
IdelTimeout:空閑線程超時的時間,超時后會如果運行的線程總數大于MaxSpareThreads則被銷毀
Priority(1~10):受Java線程優先級管理
ServicePriority:服務啟動的優先級,五種(H > A > N > B > L)
MaxQueueSize:當所有線程都忙時,為無法獲得線程的請求提供隊列進行排隊,Size代表隊列長度,隊列滿時請求被拋棄
Apusic AS的線程池優化:
● 一般的WEB應用部署在Apusic上時,不會用到JMS和ORB服務,因此可以將這兩個池注釋掉,減少資源消耗。
● 如果應用現階段使用人數不多,但是伴隨著發展應用人數會不斷增長,可以將MinSpareThreads調整為符合現階段情況的值,將MaxSpareThreads調整為符合將來的值,這樣系統無須再變動就可以有效支持很長一段時間;
● 如果應用一段時間內訪問量變化不大,但是系統偶爾會遇到高峰訪問,那么可以設置MinSpareThreads=MaxSpareThreads;
● MaxThreads的值依據CPU數量來定,參考值50×CPU核數,具體值還需要根據應用執行過程中對CPU的壓力決定。
● 關于Apusic AS V5.1服務的配置,下篇文章會單獨介紹。
附一、
Full thread dump Java HotSpot(TM) Client VM (1.5.0_14-b03 mixed mode, sharing):
"AutoDeployer" prio=6 tid=0x030f2970 nid=0x9e0 in Object.wait() [0x03cef000..0x03cefc6c]
??????? at java.lang.Object.wait(Native Method)
??????? - waiting on <0x23460458> (a com.apusic.deploy.runtime.AutoDeployer)
??????? at com.apusic.deploy.runtime.AutoDeployer.run(Unknown Source)
??????? - locked <0x23460458> (a com.apusic.deploy.runtime.AutoDeployer)
??????? at java.lang.Thread.run(Thread.java:595)
"Thread-4" prio=6 tid=0x031ca7f0 nid=0x21c in Object.wait() [0x0349f000..0x0349fd6c]
??????? at java.lang.Object.wait(Native Method)
??????? - waiting on <0x2321c188> (a com.sun.corba.se.impl.javax.rmi.CORBA.KeepAlive)
??????? at java.lang.Object.wait(Object.java:474)
??????? at com.sun.corba.se.impl.javax.rmi.CORBA.KeepAlive.run(Util.java:736)
??????? - locked <0x2321c188> (a com.sun.corba.se.impl.javax.rmi.CORBA.KeepAlive)
"HTTPSessionSwapper" prio=6 tid=0x031d8168 nid=0xb98 in Object.wait() [0x0345f000..0x0345fa6c]
??????? at java.lang.Object.wait(Native Method)
??????? - waiting on <0x2318ba58> (a java.lang.Object)
??????? at com.apusic.web.session.SessionManager$HouseKeeper.run(Unknown Source)
??????? - locked <0x2318ba58> (a java.lang.Object)
"HttpLogger" prio=2 tid=0x031be630 nid=0xfe8 in Object.wait() [0x0341f000..0x0341f9ec]
??????? at java.lang.Object.wait(Native Method)
??????? - waiting on <0x2317d2b8> (a com.apusic.web.http.HttpLogger)
??????? at java.lang.Object.wait(Object.java:474)
??????? at com.apusic.web.http.HttpLogger.getNextRecord(Unknown Source)
??????? - locked <0x2317d2b8> (a com.apusic.web.http.HttpLogger)
??????? at com.apusic.web.http.HttpLogger.run(Unknown Source)
"MuxListener" prio=6 tid=0x031a8be8 nid=0x7dc runnable [0x033df000..0x033dfaec]
??????? at java.net.PlainSocketImpl.socketAccept(Native Method)
??????? at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:384)
??????? - locked <0x23177890> (a java.net.SocksSocketImpl)
??????? at java.net.ServerSocket.implAccept(ServerSocket.java:450)
??????? at java.net.ServerSocket.accept(ServerSocket.java:421)
??????? at com.apusic.net.BlockingListenerThread.run(Unknown Source)
"Timer-0" prio=6 tid=0x031c3b08 nid=0xc98 in Object.wait() [0x0339f000..0x0339fb6c]
??????? at java.lang.Object.wait(Native Method)
??????? - waiting on <0x23133120> (a java.util.TaskQueue)
??????? at java.util.TimerThread.mainLoop(Timer.java:509)
??????? - locked <0x23133120> (a java.util.TaskQueue)
??????? at java.util.TimerThread.run(Timer.java:462)
"LogManager" prio=2 tid=0x02e2c680 nid=0xb20 waiting on condition [0x0335f000..0x0335fbec]
??????? at sun.misc.Unsafe.park(Native Method)
??????? at java.util.concurrent.locks.LockSupport.park(LockSupport.java:118)
??????? at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:
841)
??????? at com.apusic.util.concurrent.LinkedBlockingQueue.take(Unknown Source)
??????? at com.apusic.logging.manager.ServerLogManager$PushThread.dequeue(Unknown Source)
??????? at com.apusic.logging.manager.ServerLogManager$PushThread.run(Unknown Source)
"Low Memory Detector" daemon prio=6 tid=0x00a83bf0 nid=0xa6c runnable [0x00000000..0x00000000]
"CompilerThread0" daemon prio=10 tid=0x00a537b8 nid=0xdc4 waiting on condition [0x00000000..0x02c2f6cc]
"Signal Dispatcher" daemon prio=10 tid=0x00a95a58 nid=0xeb0 waiting on condition [0x00000000..0x00000000]
"Finalizer" daemon prio=8 tid=0x00a50870 nid=0xbd0 in Object.wait() [0x02baf000..0x02bafa6c]
??????? at java.lang.Object.wait(Native Method)
??????? - waiting on <0x230d25c8> (a java.lang.ref.ReferenceQueue$Lock)
??????? at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:120)
??????? - locked <0x230d25c8> (a java.lang.ref.ReferenceQueue$Lock)
??????? at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:136)
??????? at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)
"Reference Handler" daemon prio=10 tid=0x00a4f3e8 nid=0xf94 in Object.wait() [0x02b6f000..0x02b6faec]
??????? at java.lang.Object.wait(Native Method)
??????? - waiting on <0x230d2650> (a java.lang.ref.Reference$Lock)
??????? at java.lang.Object.wait(Object.java:474)
??????? at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
??????? - locked <0x230d2650> (a java.lang.ref.Reference$Lock)
"main" prio=6 tid=0x00038c00 nid=0x718 in Object.wait() [0x0007f000..0x0007fc3c]
??????? at java.lang.Object.wait(Native Method)
??????? - waiting on <0x230e0ed8> (a com.apusic.server.J2EEServer)
??????? at java.lang.Object.wait(Object.java:474)
??????? at com.apusic.server.J2EEServer.startup(Unknown Source)
??????? - locked <0x230e0ed8> (a com.apusic.server.J2EEServer)
??????? at com.apusic.server.Main.main(Unknown Source)
"VM Thread" prio=10 tid=0x00a80190 nid=0x490 runnable
"VM Periodic Task Thread" prio=10 tid=0x00a8e780 nid=0xcec waiting on condition
附二、
Full thread dump Java HotSpot(TM) Client VM (1.5.0_14-b03 mixed mode, sharing):
"Running HTTPHandler-1" prio=6 tid=0x02febe58 nid=0xbd8 runnable [0x03d6f000..0x03d6fb6c]
??????? at java.net.SocketInputStream.socketRead0(Native Method)
??????? at java.net.SocketInputStream.read(SocketInputStream.java:129)
??????? at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
??????? at java.io.BufferedInputStream.read1(BufferedInputStream.java:256)
??????? at java.io.BufferedInputStream.read(BufferedInputStream.java:313)
??????? - locked <0x234dd378> (a java.io.BufferedInputStream)
??????? at com.apusic.web.http.tcp.TCP_BIOProtocol.readLine(Unknown Source)
??????? at com.apusic.web.http.tcp.TCP_BIOProtocol.readRequestLine(Unknown Source)
??????? at com.apusic.web.http.tcp.TCP_BIOProtocol.read(Unknown Source)
??????? at com.apusic.web.http.tcp.TCP_BIOConnection.getNextRequest(Unknown Source)
??????? at com.apusic.web.http.ConnectionHandler.processConnection(Unknown Source)
??????? at com.apusic.web.http.ConnectionHandler.run(Unknown Source)
??????? at com.apusic.util.ThreadPoolImpl$WorkerThread.run(Unknown Source)
"Idle MuxHandler-1" prio=6 tid=0x02cc0d90 nid=0x54c in Object.wait() [0x03d2f000..0x03d2fbec]
??????? at java.lang.Object.wait(Native Method)
??????? - waiting on <0x23147df0> (a java.lang.Object)
??????? at com.apusic.util.ThreadPoolImpl.getWork(Unknown Source)
??????? - locked <0x23147df0> (a java.lang.Object)
??????? at com.apusic.util.ThreadPoolImpl$WorkerThread.run(Unknown Source)
"AutoDeployer" prio=6 tid=0x03146980 nid=0x7bc in Object.wait() [0x03cef000..0x03cefc6c]
??????? at java.lang.Object.wait(Native Method)
??????? - waiting on <0x2344f8c0> (a com.apusic.deploy.runtime.AutoDeployer)
??????? at com.apusic.deploy.runtime.AutoDeployer.run(Unknown Source)
??????? - locked <0x2344f8c0> (a com.apusic.deploy.runtime.AutoDeployer)
??????? at java.lang.Thread.run(Thread.java:595)
"Thread-4" prio=6 tid=0x031e3868 nid=0xdc8 in Object.wait() [0x0349f000..0x0349fd6c]
??????? at java.lang.Object.wait(Native Method)
??????? - waiting on <0x2321c188> (a com.sun.corba.se.impl.javax.rmi.CORBA.KeepAlive)
??????? at java.lang.Object.wait(Object.java:474)
??????? at com.sun.corba.se.impl.javax.rmi.CORBA.KeepAlive.run(Util.java:736)
??????? - locked <0x2321c188> (a com.sun.corba.se.impl.javax.rmi.CORBA.KeepAlive)
"HTTPSessionSwapper" prio=6 tid=0x031c1948 nid=0x9f4 in Object.wait() [0x0345f000..0x0345fa6c]
??????? at java.lang.Object.wait(Native Method)
??????? - waiting on <0x2318ba58> (a java.lang.Object)
??????? at com.apusic.web.session.SessionManager$HouseKeeper.run(Unknown Source)
??????? - locked <0x2318ba58> (a java.lang.Object)
"HttpLogger" prio=2 tid=0x031b8830 nid=0xb2c in Object.wait() [0x0341f000..0x0341f9ec]
??????? at java.lang.Object.wait(Native Method)
??????? - waiting on <0x2317d2b8> (a com.apusic.web.http.HttpLogger)
??????? at java.lang.Object.wait(Object.java:474)
??????? at com.apusic.web.http.HttpLogger.getNextRecord(Unknown Source)
??????? - locked <0x2317d2b8> (a com.apusic.web.http.HttpLogger)
??????? at com.apusic.web.http.HttpLogger.run(Unknown Source)
"MuxListener" prio=6 tid=0x02e654a8 nid=0xa28 runnable [0x033df000..0x033dfaec]
??????? at java.net.PlainSocketImpl.socketAccept(Native Method)
??????? at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:384)
??????? - locked <0x23177890> (a java.net.SocksSocketImpl)
??????? at java.net.ServerSocket.implAccept(ServerSocket.java:450)
??????? at java.net.ServerSocket.accept(ServerSocket.java:421)
??????? at com.apusic.net.BlockingListenerThread.run(Unknown Source)
"Timer-0" prio=6 tid=0x02e65c08 nid=0xdf0 in Object.wait() [0x0339f000..0x0339fb6c]
??????? at java.lang.Object.wait(Native Method)
??????? - waiting on <0x23133120> (a java.util.TaskQueue)
??????? at java.util.TimerThread.mainLoop(Timer.java:509)
??????? - locked <0x23133120> (a java.util.TaskQueue)
??????? at java.util.TimerThread.run(Timer.java:462)
"LogManager" prio=2 tid=0x02e2d488 nid=0xbfc waiting on condition [0x0335f000..0x0335fbec]
??????? at sun.misc.Unsafe.park(Native Method)
??????? at java.util.concurrent.locks.LockSupport.park(LockSupport.java:118)
??????? at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1
841)
??????? at com.apusic.util.concurrent.LinkedBlockingQueue.take(Unknown Source)
??????? at com.apusic.logging.manager.ServerLogManager$PushThread.dequeue(Unknown Source)
??????? at com.apusic.logging.manager.ServerLogManager$PushThread.run(Unknown Source)
"Low Memory Detector" daemon prio=6 tid=0x00a83c78 nid=0xc5c runnable [0x00000000..0x00000000]
"CompilerThread0" daemon prio=10 tid=0x00a53910 nid=0x780 waiting on condition [0x00000000..0x02c2f6cc]
"Signal Dispatcher" daemon prio=10 tid=0x00a95ae8 nid=0xc8c waiting on condition [0x00000000..0x00000000]
"Finalizer" daemon prio=8 tid=0x00a50870 nid=0xd10 in Object.wait() [0x02baf000..0x02bafa6c]
??????? at java.lang.Object.wait(Native Method)
??????? - waiting on <0x230d25c8> (a java.lang.ref.ReferenceQueue$Lock)
??????? at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:120)
??????? - locked <0x230d25c8> (a java.lang.ref.ReferenceQueue$Lock)
??????? at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:136)
??????? at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)
"Reference Handler" daemon prio=10 tid=0x00a4f3e8 nid=0x1d0 in Object.wait() [0x02b6f000..0x02b6faec]
??????? at java.lang.Object.wait(Native Method)
??????? - waiting on <0x230d2650> (a java.lang.ref.Reference$Lock)
??????? at java.lang.Object.wait(Object.java:474)
??????? at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
??????? - locked <0x230d2650> (a java.lang.ref.Reference$Lock)
"main" prio=6 tid=0x00038c00 nid=0x7fc in Object.wait() [0x0007f000..0x0007fc3c]
??????? at java.lang.Object.wait(Native Method)
??????? - waiting on <0x230e0ed8> (a com.apusic.server.J2EEServer)
??????? at java.lang.Object.wait(Object.java:474)
??????? at com.apusic.server.J2EEServer.startup(Unknown Source)
??????? - locked <0x230e0ed8> (a com.apusic.server.J2EEServer)
??????? at com.apusic.server.Main.main(Unknown Source)
"VM Thread" prio=10 tid=0x00a80190 nid=0xab4 runnable
"VM Periodic Task Thread" prio=10 tid=0x00a8e808 nid=0x684 waiting on condition
參考:
http://infocenter.apusic.com/help/index.jsp?topic=/com.apusic.studio.doc.server/output/eclipse/threadpool.html