1月2號XX省/市開始XX考試網(wǎng)上報(bào)名。今年是第一年開始采用網(wǎng)上報(bào)名的形式,預(yù)計(jì)在10天之內(nèi)XX省/市有大于14萬的學(xué)生需要在指定的網(wǎng)站中填寫完畢個(gè)人信息并且確認(rèn)。本來這個(gè)項(xiàng)目并不是我負(fù)責(zé)的,不過很無奈,正式報(bào)名剛開始系統(tǒng)就發(fā)生了比較嚴(yán)重的性能問題,因?yàn)槭虑榫o急只能取消自己的休假計(jì)劃,趕到現(xiàn)場調(diào)試系統(tǒng)。
到了之后,首先檢查了Tomcat的配置文件server.xml,原來一直以為肯定是配置服務(wù)器的同學(xué)沒有把Tomcat中默認(rèn)的允許訪問的最大數(shù)75給改掉,后來發(fā)現(xiàn)不是這個(gè)問題,在配置文件中設(shè)置Context的地方有一段非常的詭異:有一個(gè)Context的路徑是在%Tomcat%/webapps/ROOT中的一個(gè)目錄AAA,這樣的話如果當(dāng)一個(gè)用戶訪問URL: http://serverip:port/AAA 時(shí),系統(tǒng)是應(yīng)該使用ROOT/WEB-INF中類還是應(yīng)該使用ROOT/AAA/WEB-INF中的類?把服務(wù)器中兩個(gè)WEB-INF都下載下來,用JAD反編譯其中的部分類,發(fā)現(xiàn)并不一致。最后經(jīng)過分析,得出了TOMCAT在這種Context嵌套在ROOT Context中的情況,TOMCAT會使用ROOT目錄中的WEB-INF。
然后為程序加入了數(shù)據(jù)庫連接池配置,實(shí)踐證明了如果不采用TOMCAT的數(shù)據(jù)庫連接池技術(shù),那么在并發(fā)訪問數(shù)達(dá)到4000-5000的時(shí)候,Tomcat絕對支撐不到1分鐘的。采用TOMCAT的數(shù)據(jù)庫連接池技術(shù)后這時(shí)的TOMCAT能維持正常運(yùn)行30分鐘左右。數(shù)據(jù)庫連接池配置的方式如下:
修改tomcat配置文件server.xml,在context標(biāo)簽中加上
maxActive是最大激活連接數(shù),這里取值為1000,表示同時(shí)最多有1000個(gè)數(shù)據(jù)庫連接。maxIdle是最大的空閑連接數(shù),這里取值為20,表示即使沒有數(shù)據(jù)庫連接時(shí)依然可以保持20空閑的連接,而不被清除,隨時(shí)處于待命狀態(tài)。MaxWait是最大等待秒鐘數(shù),這里取值-1,表示無限等待,直到超時(shí)為止,也可取值9000,表示9秒后超時(shí)。
[待加入的XML片斷,竟然被系統(tǒng)過濾掉了,赫赫,留個(gè)站位符]
將Oracle的JDBC驅(qū)動classes12.jar拷貝到Tomcat安裝目錄的common/lib下。建立簡單的測試頁面test2.jsp:
到這里數(shù)據(jù)庫連接池配置基本完成了。但是如果半個(gè)小時(shí)服務(wù)器死掉一次的話,還是不能令人接受的。開始詳細(xì)檢查tomcat的輸出文件%Tomcat%/logs/catalina.out,在這個(gè)文件中記錄的是所有TOMCAT控制臺的輸出,一般在JAVA中的抱錯(cuò)信息都會在這里打印出來。自己分析后發(fā)現(xiàn)每次TOMCAT死掉之前,都是一堆java.net.SocketException: Too many open files這種錯(cuò)誤。這個(gè)錯(cuò)誤肯定不是程序的問題。
可能是因?yàn)槊坑幸粋€(gè)TCP的連接到Linux服務(wù)器的80端口,都有一次文件的傳輸過程,Tomcat服務(wù)器會打開一個(gè)文件(比如圖片文件),傳送給請求的客戶端瀏覽器,所以如果訪問Tomcat的人數(shù)過多,會突破linux系統(tǒng)默認(rèn)的1024個(gè)文件上限。
在/root/.bash_profile文件中加入:
ulimit -n 4096
可以在每次系統(tǒng)啟動時(shí)候自動執(zhí)行ulimit命令,把最大文件上傳個(gè)數(shù)調(diào)整到4096個(gè)。注意ulimit這個(gè)命令是針對于一個(gè)開打的終端的,比如你在一個(gè)終端上面運(yùn)行ulimit,但是影響到的只是你這個(gè)終端上運(yùn)行的命令和程序的打開的文件數(shù),其他的終端如果再打開,效果仍然是沒有運(yùn)行ulimit -n 4096之前的。大家可以實(shí)驗(yàn)一下。
這樣之后,服務(wù)器大概能維持2小時(shí)左右的正常運(yùn)行,使用TOP命令查看Java進(jìn)程占用的內(nèi)存后,發(fā)覺一個(gè)現(xiàn)象,就是內(nèi)存使用到256M之后,不會往上增長了(服務(wù)器有8G的內(nèi)存)。上網(wǎng)查了以后,知道了Tomcat默認(rèn)可以使用的是256M的內(nèi)存。由于在線人數(shù)過多,造成Tomcat默認(rèn)可以使用的256M的內(nèi)存不夠使用,所以修改Tomcat的啟動文件catalina.sh,在“echo “Using JAVA_HOME: $JAVA_HOME”” 后加入JAVA_OPTS=’-Xms256m -Xmx1024m’,256m表示初始化的時(shí)候給Tomcat初始內(nèi)存256M,1024m表示Tomcat最大可使用的內(nèi)存為1024M。
修改了這個(gè)之后,服務(wù)器比原先穩(wěn)定了許多了,可是又發(fā)現(xiàn)在有的時(shí)候,進(jìn)行用戶登錄的時(shí)候會報(bào)莫名其妙的數(shù)據(jù)庫連接錯(cuò)誤。終于在有一次使用ORACLE的客戶端程序GOLDEN連接Oracle時(shí),出現(xiàn)了ORA-00020:maximum number of process(150) exceeded 這樣一個(gè)錯(cuò)誤。這是由于數(shù)據(jù)庫服務(wù)器訪問的連接數(shù)過多,會出現(xiàn)ORA-00020:maximum number of process(150) exceeded的錯(cuò)誤。Oracle 9i中默認(rèn)的連接數(shù)為150,要修改這個(gè)配置文件,需要修改SPFILEORCL.ORA文件中的processes的值。(8.1.5中是init.ora文件,在9i中修改init.ora文件是無效的)這個(gè)文件由于是一個(gè)二進(jìn)制的文件,不能直接使用notepad此類的編輯器打開,否則會報(bào)錯(cuò)誤ORA-27101 Shared memory realm does not exist。使用UltraEdit或者EditPlus之類的可以編輯二進(jìn)制文件的編輯器打開此文件(直接編輯二進(jìn)制文件),然后在Windows服務(wù)中重新啟動Oracle服務(wù)器即可。
現(xiàn)在的狀況非常好,問題正在逐步的好轉(zhuǎn)之中,不過系統(tǒng)的性能還是非常的差,網(wǎng)頁的訪問速度很糟糕。到安裝Oracle的Win2003服務(wù)器上檢查了一下Oracle服務(wù)器,發(fā)現(xiàn)硬盤的占用率很高,基本一致是100% 使用的狀況。進(jìn)入Oracle中進(jìn)行分析,發(fā)現(xiàn)有兩條SQL語句非常占用系統(tǒng)的資源,是造成瓶頸的兩個(gè)SQL。
于是對于原先使用trim的SQL進(jìn)行優(yōu)化
由于trim命令會造成大量的硬盤讀寫(使用trim后造成索引無效),所以把所有使用trim命令的語句修改為使用rpad命令。
例如:
select sfzh from qjgkXSK where trim(sfzh)=:1
改為
select sfzh from qjgkXSK where sfzh=:rpad(1)
對于表結(jié)構(gòu)的建議:
表結(jié)構(gòu)中如果長度小于200的字段,建議使用char類型,而不是Varchar類型。
然后發(fā)現(xiàn)在生成一個(gè)唯一序列號的時(shí)候,程序中有一個(gè)鎖表的操作,造成一個(gè)最大的瓶頸。
原先的做法是先是鎖住一個(gè)表,然后取得最大值,最后把最大值加一,寫入數(shù)據(jù)庫中。
改進(jìn)后的做法是加入一個(gè)ORACLE的自增1的sequence(Oracle和MySQL、DB2等不同,它沒有主鍵auto-increasement這種功能)
做完這些時(shí)候,感到系統(tǒng)的問題都解決了,不過后來的情況還是幾個(gè)小時(shí)會死機(jī)一次,這次是報(bào)一個(gè)Java虛擬機(jī)的錯(cuò)誤,估計(jì)是因?yàn)橐婚_始別人裝的是1.5beta版的關(guān)系。
總結(jié)一下這次的優(yōu)化的經(jīng)驗(yàn):
1.要抓住事物的主要矛盾。其實(shí)一開始針對WEB服務(wù)器中的很多優(yōu)化都是次要矛盾,當(dāng)解決了最后的2個(gè)SQL語句的問題后,前面的很多問題都不會出現(xiàn)的,比如那個(gè)Linux 1024個(gè)默認(rèn)打開文件數(shù)的問題,最后發(fā)現(xiàn)如果系統(tǒng)數(shù)據(jù)庫訪問的速度足夠快,根本不會有那么多打開的文件數(shù)的,往往是大家用系統(tǒng)時(shí)很慢,所以造成了不斷用F5刷新,把Tomcat活活搞死。
2.在這種很重要的場合下改動程序或者配置一定要謹(jǐn)慎謹(jǐn)慎再謹(jǐn)慎。我在修改Oracle的配置文件的時(shí)候,一開始沒有備份,以后那是一個(gè)文本文件,我就是直接開打修改一個(gè)數(shù)字而已。但是雖然用notepad打開的時(shí)候顯示出來的是文本,但是這個(gè)文件在被notepad打開時(shí)一些二進(jìn)制的東西被破壞了,造成了Oracle服務(wù)器啟動不起來,那時(shí)候自己都要被嚇?biāo)懒?,還好有個(gè)同學(xué)的機(jī)器上也有Oracle9i,而且都是按照默認(rèn)配置的,直接打電話叫他把那個(gè)文件通過MSN發(fā)了過來。如果沒有類似的文件,或者服務(wù)器裝的比較怪異,那么就慘了,千古罪人的。后來我基本每做一個(gè)操作,都不圖快,而是隨時(shí)備份,做的比較穩(wěn)健了。
3.在改那個(gè)程序的時(shí)候不斷的有考生打電話來咨詢服務(wù)器的問題,那個(gè)時(shí)候壓力非常大,一定要頂住壓力,如果感覺吃不消了,不妨先休息下,然后效率可能會更加高。
4.事前一定要做好測試工作。
最后附上一些Linux中可能會在檢測性能時(shí)候用到的命令:
A.察看某個(gè)進(jìn)程打開的文件數(shù):
先用ps -aux找到pid,然后運(yùn)行l(wèi)sof -p %pid% | wc -l
B.察看80端口的連接數(shù)
netstat -nat|grep -i “80″|wc -l
聯(lián)系客服