操作系統的中打開文件的最大句柄數受限所致,常常發生在很多個併發用戶訪問服務器的時候.因爲爲了執行每個用戶的應用服務器都要加載很多文件(new一個socket就需要一個文件句柄),這就會導致打開文件的句柄的缺乏.
解決:
儘量把類打成jar包,因爲一個jar包只消耗一個文件句柄,如果不打包,一個類就消耗一個文件句柄.
java的垃圾回收不能關閉網絡連接打開的文件句柄,如果沒有執行close()(例如:java.net.Socket.close())則文件句柄將一直存在,而不能被關閉.你也可以考慮設置socket的最大打開數來控制這個問題.
對操作系統做相關的設置,增加最大文件句柄數量。
Linux
在Linux內核2.4.x中需要修改源代碼,然後重新編譯內核才生效。編輯Linux內核源代碼中的 include/linux/fs.h文件,將
NR_FILE 由8192改爲65536,將NR_RESERVED_FILES 由10 改爲 128。編輯fs/inode.c
文件將MAX_INODE 由16384改爲262144。或者編輯 /etc/sysctl.conf 文件增加兩行 fs.file-max =
65536 和 fs.inode-max = 262144
。一般情況下,系統最大打開文件數比較合理的設置爲每4M物理內存256,比如256M.可以用lsof -p 看打開的文件句柄數.
Windows
最大文件句柄是16,384,你在任務管理器的性能這一項中可以看到當前打開的句柄數.
修改linux內核信息:
使用ulimit -n命令可以看到單個進程能夠打開的最大文件句柄數量(socket連接也算在裏面)。系統默認值1024。
vi /etc/security/limits.conf,加入如下內容:
* hard nofile 10240
vi /etc/profile,加入如下內容:
ulimit -n 10240
執行:
source /etc/profile
驗證:
ulimit -n
返回數值應該是10240
vi /etc/sysctl.conf
加入:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle=1
net.ipv4.tcp_fin_timeout = 30
說明:
net.ipv4.tcp_syncookies = 1 表示開啓SYN Cookies。當出現SYN等待隊列溢出時,啓用cookies來處理,可防範少量SYN攻擊,默認爲0,表示關閉;
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 修改系統默認的 TIMEOUT 時間
shmmax - 共享內存段的最大字節數,建議設大點,甚至可以大過物理內存的字節數
shmmin - 共享內存段的最小尺寸.
shmmni - 共享內存段的最大數目.
shmseg - 每個進程可分配的最大共享內存段數目.
shmall - 最大的併發共享內存段數目,比SGA還要大.
semmns - 信號燈的最大數量,跟ORACLE的PROCESS數有關.
semmsl - 每個信號燈集合中最多的信號燈數目.
設置Linux內核參數
配置 Linux 內核參數(2種方法),修改後不用重啓動更新: /sbin/sysctl -p
第一種:打開/etc/sysctl.conf
kernel.shmmax = 536870912
kernel.shmall = 2097152
kernel.shmmax = 2147483648 2G
kernel.shmmni = 4096
kernel.sem = 250 32000 100 128
fs.file-max = 65536
net.ipv4.ip_local_port_range = 1024 65000
net.core.rmem_default=262144
net.core.wmem_default=262144
net.core.rmem_max=262144
net.core.wmem_max=262144
第二種:打開終端
cat >> /etc/sysctl.conf
kernel.shmall = 2097152
*
kernel.shmmni = 4096
kernel.sem = 250 32000 100 128
fs.file-max =
net.ipv4.ip_local_port_range = 1024 65000
net.core.rmem_default=262144
net.core.wmem_default=262144
net.core.rmem_max=262144
net.core.wmem_max=262144
EOF
這裏,對每個參數值做個簡要的解釋和說明。
(1)shmmax:該參數定義了共享內存段的最大尺寸(以字節爲單位)。缺省爲32M,對於oracle來說,該缺省值太低了,通常將其設置爲2G。
(2)shmmni:這個內核參數用於設置系統範圍內共享內存段的最大數量。該參數的默認值是 4096 。通常不需要更改。
(3)shmall:該參數表示系統一次可以使用的共享內存總量(以頁爲單位)。缺省值就是2097152,通常不需要修改。
(4)sem:該參數表示設置的信號量。
(5)file-max:該參數表示文件句柄的最大數量。文件句柄設置表示在linux系統中可以打開的文件數量。
修改好內核以後,執行下面的命令使新的配置生效。
[root @linux1 /root]# /sbin/sysctl -p
以 root 用戶身份運行以下命令來驗證您的設置:
/sbin/sysctl -a | grep shm
/sbin/sysctl -a | grep sem
/sbin/sysctl -a | grep file-max
/sbin/sysctl -a | grep ip_local_port_range
例如:
# /sbin/sysctl -a | grep shm
kernel.shmmni = 4096
kernel.shmall = 2097152
kernel.shmmax = 2147483648
kernel.shm-use-bigpages = 0
# /sbin/sysctl -a | grep sem
kernel.sem = 250 32000 100 128
# /sbin/sysctl -a | grep file-max
fs.file-max = 65536
# /sbin/sysctl -a | grep ip_local_port_range
net.ipv4.ip_local_port_range = 1024 65000
如果系統的參數設置的比上述參數值小,則編輯 /etc/sysctl.conf 文件,添加或更改這些參數。完成後,運行以下命令激活更改:
/sbin/sysctl -p
查看進程句柄數量:
如何知道當前進程打開了多少個文件句柄呢?下面一段小腳本可以幫你查看:lsof -n |awk '{print $2}'|sort|uniq -c |sort -nr|more
在系統訪問高峯時間以root用戶執行上面的腳本,可能出現的結果如下:# lsof -n|awk '{print
$2}'|sort|uniq -c |sort -nr|more 131 24204 57 24244 57 24231
56 24264
其中第一行是打開的文件句柄數量,第二行是進程號。得到進程號後,我們可以通過ps命令得到進程的詳細內容。ps -aef|grep 24204
mysql 24204 24162 99 16:15 ? 00:24:25 /usr/sbin/mysqld
哦,原來是mysql進程打開最多文件句柄數量。但是他目前只打開了131個文件句柄數量,遠遠底於系統默認值1024。
用以下語句看了一下服務器的TCP狀態:
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
返回結果如下:
ESTABLISHED 1423
FIN_WAIT1 1
FIN_WAIT2 262
SYN_SENT 1
TIME_WAIT 962
apache2.x優化──提高併發量
引用:http://tech.ccidnet.com/art/737/20030527/47607_1.html
指定MPM的方法
下面以Red Hat Linux 9爲平臺,說明在Apache 2.0中如何指定MPM (Apache採用2.0.45)。先解壓縮源代碼包httpd-2.0.45.tar.gz,生成httpd-2.0.45目錄(Apache 1.3源代碼包的命名規則是apache_1.3.NN.tar.gz,而2.0版則是httpd-2.0.NN.tar.gz,其中NN是次版本號)。
進入httpd-2.0.45目錄,運行以下代碼:
$ ./configure --help|grep mpm |
顯示如下:
--with-mpm=MPM |
上述操作用來選擇要使用的進程模型,即哪種MPM模塊。Beos、 mpmt_os2分別是BeOS和OS/2上缺省的MPM,perchild主要設計目的是以不同的用戶和組的身份來運行不同的子進程。這在運行多個需要 CGI的虛擬主機時特別有用,會比1.3版中的SuExec機制做得更好。leader和threadpool都是基於worker的變體,還處於實驗性 階段,某些情況下並不會按照預期設想的那樣工作,所以Apache官方也並不推薦使用。因此,我們主要闡述prefork和worker這兩種和性能關係 最大的產品級MPM ( 有關其它的MPM詳細說明,請參見Apache官方文檔:http://httpd.apache.org/docs-2.0/mod/)。
prefork的工作原理及配置
如果不用“--with-mpm”顯式指定某種MPM,prefork就是 Unix平臺上缺省的MPM。它所採用的預派生子進程方式也是Apache 1.3中採用的模式。prefork本身並沒有使用到線程,2.0版使用它是爲了與1.3版保持兼容性;另一方面,prefork用單獨的子進程來處理不 同的請求,進程之間是彼此獨立的,這也使其成爲最穩定的MPM之一。
若使用prefork,在make編譯和make install安裝後,使用“httpd -l”來確定當前使用的MPM,應該會看到prefork.c(如果看到worker.c說明使用的是worker MPM,依此類推)。再查看缺省生成的httpd.conf配置文件,裏面包含如下配置段:
<IfModule prefork.c> |
prefork的工作原理是,控制進程在最初建立“StartServers” 個子進程後,爲了滿足MinSpareServers設置的需要創建一個進程,等待一秒鐘,繼續創建兩個,再等待一秒鐘,繼續創建四個……如此按指數級增 加創建的進程數,最多達到每秒32個,直到滿足MinSpareServers設置的值爲止。這就是預派生(prefork)的由來。這種模式可以不必在 請求到來時再產生新的進程,從而減小了系統開銷以增加性能。
MaxSpareServers設置了最大的空閒進程數,如果空閒進程數大於 這個值,Apache會自動kill掉一些多餘進程。這個值不要設得過大,但如果設的值比MinSpareServers小,Apache會自動把其調整 爲MinSpareServers+1。如果站點負載較大,可考慮同時加大MinSpareServers和MaxSpareServers。
MaxRequestsPerChild設置的是每個子進程可處理的請求數。 每個子進程在處理了“MaxRequestsPerChild”個請求後將自動銷燬。0意味着無限,即子進程永不銷燬。雖然缺省設爲0可以使每個子進程處 理更多的請求,但如果設成非零值也有兩點重要的好處:
◆ 可防止意外的內存泄漏;
◆ 在服務器負載下降的時侯會自動減少子進程數。
因此,可根據服務器的負載來調整這個值。筆者認爲10000左右比較合適。
MaxClients是這些指令中最爲重要的一個,設定的是Apache可以同 時處理的請求,是對Apache性能影響最大的參數。其缺省值150是遠遠不夠的,如果請求總數已達到這個值(可通過ps -ef|grep http|wc -l來確認),那麼後面的請求就要排隊,直到某個已處理請求完畢。這就是系統資源還剩下很多而HTTP訪問卻很慢的主要原因。系統管理員可以根據硬件配置 和負載情況來動態調整這個值。雖然理論上這個值越大,可以處理的請求就越多,但Apache默認的限制不能大於256。如果把這個值設爲大於256,那麼 Apache將無法起動。事實上,256對於負載稍重的站點也是不夠的。在Apache 1.3中,這是個硬限制。如果要加大這個值,必須在“configure”前手工修改的源代碼樹下的src/include/httpd.h中查找 256,就會發現“#define HARD_SERVER_LIMIT 256”這行。把256改爲要增大的值(如4000),然後重新編譯Apache即可。在Apache 2.0中新加入了ServerLimit指令,使得無須重編譯Apache就可以加大MaxClients。下面是筆者的prefork配置段:
<IfModule prefork.c> |
上述配置中,ServerLimit的最大值是20000,對於大多數站點已經足夠。如果一定要再加大這個數值,對位於源代碼樹下server/mpm/prefork/prefork.c中以下兩行做相應修改即可:
#define DEFAULT_SERVER_LIMIT 256 |
worker的工作原理及配置
相對於prefork,worker是2.0 版中全新的支持多線程和多進程混合模型的MPM。由於使用線程來處理,所以可以處理相對海量的請求,而系統資源的開銷要小於基於進程的服務器。但是, worker也使用了多進程,每個進程又生成多個線程,以獲得基於進程服務器的穩定性。這種MPM的工作方式將是Apache 2.0的發展趨勢。
在configure -with-mpm=worker後,進行make編譯、make install安裝。在缺省生成的httpd.conf中有以下配置段:
<IfModule worker.c> |
worker的工作原理是,由主控制進程生成“StartServers”個子 進程,每個子進程中包含固定的ThreadsPerChild線程數,各個線程獨立地處理請求。同樣,爲了不在請求到來時再生成線程, MinSpareThreads和MaxSpareThreads設置了最少和最多的空閒線程數;而MaxClients設置了所有子進程中的線程總數。 如果現有子進程中的線程總數不能滿足負載,控制進程將派生新的子進程。
MinSpareThreads和MaxSpareThreads的最大缺省值分別是75和250。這兩個參數對Apache的性能影響並不大,可以按照實際情況相應調節。
ThreadsPerChild是worker MPM中與性能相關最密切的指令。ThreadsPerChild的最大缺省值是64,如果負載較大,64也是不夠的。這時要顯式使用 ThreadLimit指令,它的最大缺省值是20000。上述兩個值位於源碼樹server/mpm/worker/worker.c中的以下兩行:
#define DEFAULT_THREAD_LIMIT 64 |
這兩行對應着ThreadsPerChild和ThreadLimit的限制數。最好在configure之前就把64改成所希望的值。注意,不要把這兩個值設得太高,超過系統的處理能力,從而因Apache不起動使系統很不穩定。
Worker模式下所能同時處理的請求總數是由子進程總數乘以 ThreadsPerChild值決定的,應該大於等於MaxClients。如果負載很大,現有的子進程數不能滿足時,控制進程會派生新的子進程。默認 最大的子進程總數是16,加大時也需要顯式聲明ServerLimit(最大值是20000)。這兩個值位於源碼樹 server/mpm/worker/worker.c中的以下兩行:
#define DEFAULT_SERVER_LIMIT 16 |
需要注意的是,如果顯式聲明瞭ServerLimit,那麼它乘以 ThreadsPerChild的值必須大於等於MaxClients,而且MaxClients必須是ThreadsPerChild的整數倍,否則 Apache將會自動調節到一個相應值(可能是個非期望值)。下面是筆者的worker配置段:
<IfModule worker.c> |
通過上面的敘述,可以瞭解到Apache 2.0中prefork和worker這兩個重要MPM的工作原理,並可根據實際情況來配置Apache相關的核心參數,以獲得最大的性能和穩定
修改tomcat6.0的併發數:
- <Connector port="80" protocol="HTTP/1.1"
- maxHttpHeaderSize="8192"
- maxThreads="1000" minSpareThreads="75" maxSpareThreads="300"
- enableLookups="false" redirectPort="8443" acceptCount="200"
- connectionTimeout="50000" disableUploadTimeout="true"/>
主要修改了maxThreads、acceptCount。
2、 增加tomcat啓動初始內存設置;catalina.sh – 增加了參數內存設置
增加設置
- JAVA_OPTS="-server -Xms2048M -Xmx2048M -Xss128k -XX:+AggressiveOpts -XX:+UseParallelGC -XX:+UseBiasedLocking"
JAVA_OPTS="-server -Xms2048M -Xmx2048M -Xss128k -XX:+AggressiveOpts -XX:+UseParallelGC -XX:+UseBiasedLocking"
增加了JVM初始分配的內存
資料:
堆內存分配
JVM初始分配的內存由-Xms指定,默認是物理內存的1/64;JVM最大分配的內存由-Xmx指定,默認是物理內存的1/4。默認空餘堆內存 小於40%時,JVM就會增大堆直到-Xmx的最大限制;空餘堆內存大於70%時,JVM會減少堆直到-Xms的最小限制。因此服務器一般設置-Xms、 -Xmx相等以避免在每次GC 後調整堆的大小。
非堆內存分配
JVM使用-XX:PermSize設置非堆內存初始值,默認是物理內存的1/64;由XX:MaxPermSize設置最大非堆內存的大小,默認是物理內存的1/4。
JVM內存限制(最大值)
首先JVM內存限制於實際的最大物理內存(廢話!呵呵),假設物理內存無限大的話,JVM內存的最大值跟操作系統有很大的關係。簡單的說就32位 處理器雖然可控內存空間有4GB,但是具體的操作系統會給一個限制,這個限制一般是2GB-3GB(一般來說Windows系統下爲1.5G-2G, Linux系統下爲2G-3G),而64bit以上的處理器就不會有限制了。
3、 響應處理的servlet在系統啓動時進行初始化,修改servlet load-on-strartup數值,可設0、1、2、3,值小的先初始化;