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