測試在進行一次性能測試的時候發現併發300個請求時出現了下麵的異常: HTTP Status 500 - Handler processing failed; nested exception is java.lang.OutOfMemoryError: unable to create new n ...
測試在進行一次性能測試的時候發現併發300個請求時出現了下麵的異常:
HTTP Status 500 - Handler processing failed; nested exception is java.lang.OutOfMemoryError: unable to create new native thread
看到這個異常有點發慌,畢竟併發程式寫的少,突然來這麼一個確實有點找不著背。但不管怎麼樣還是先搜索一下是啥原因吧。
這個錯誤是因為無法再創建新線程導致的,原因可能是沒有更多的空間用於創建線程,還有一個公式用來計算:
(MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads
這其中各個參數的意思是:
MaxProcessMemory:進程最大定址空間。
JVMMMEMORY:jvm的記憶體空間(堆+永久區)-Xmx大小 (應該是實際分配大小)
ReservedOsMemory:操作系統預留記憶體
ThreadStackSize:-Xss大小
於是我查看一下liunx系統的參數情況:
[root@RHEL63temp ~]# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 63628
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 1024
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
其中的max user processes只有1024個,心想著這事情可能問題不在於創建的限制,而是為什麼要創建這麼多線程?畢竟只有300個併發,tomcat最多也就300個線程用於處理請求吧?
於是想了想程式代碼的問題,還是要從代碼上去查找原因。於是臨時開始研究了一下JVisualVM這個監控工具,在伺服器上做了做配置,反正網上有教程。因為我使用的是Tomcat,所以直接就監控Tomcat吧,在catalina.sh中增加一些參數:
JAVA_OPTS="-server -Xmx384m -Xms128m -XX:PermSize=128M -XX:MaxPermSize=256m"
-Dcom.sun.management.jmxremote.port=9998
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-Djava.rmi.server.hostname=192.168.49.199"
這樣就可以使用JVisualVM通過JMX方式監控了。連接上後再進行測試問題原因找到了。
線程產生這麼大主要是兩塊:
1、tomcat的本身需要支持併發的線程
2、smack產生的大量線程,而且連續壓測會發現smack的線程出現不釋放的情況
這裡的關鍵是smack的使用,因為系統實現了一個功能就是通過網頁發起ajax請求,然後在服務端模擬即時通過用戶發送消息。因為併發300個請求,導致每個請求都要創建smack的連接,而smack是用於客戶端開發的庫,啟動後會創建3個左右的線程用於連接和處理伺服器的通訊。這就導致同時會產生300*3的線程,所以併發時會所線程創建數用滿。
既然問題原因找到了,所以這裡的問題可能還是smack的使用問題,畢竟smack是個客戶端庫,不太適合於這種服務端的場景。
解決方法是使用其他方式代替smack發消息,這樣只需要創建少量的線程就可以滿足要求,而且處理速度大大提升。
註:此文章為原創,歡迎轉載,請在文章頁面明顯位置給出此文鏈接! 若您覺得這篇文章還不錯請點擊下右下角的推薦,非常感謝! http://www.cnblogs.com/5207