讀古今文學網 > 編寫高質量代碼:改善Java程序的151個建議 > 建議138:性能是個大「咕咚」 >

建議138:性能是個大「咕咚」

有一部動畫片叫《咕咚來了》,其大致劇情是:三隻小兔在湖邊玩耍,忽然湖中傳來「咕咚」一聲,這奇怪的聲音把小兔們嚇了一大跳。小兔們剛想去看個究竟,又聽到「咕咚」一聲,這可把小兔們嚇壞了,「快跑,咕咚來了,快逃呀!」小兔們轉身就跑。

狐狸正同小鳥跳舞,與跑來的兔子碰了個滿懷。狐狸一聽「咕咚來了!」也緊張起來,跟著就跑。它們又驚醒了睡覺的小熊和樹上的小猴,小熊和小猴也不問青紅皂白,跟著它們跑起來,於是一路上跟著跑的動物越來越多,大象、河馬、老虎、野豬……

岸上這陣騷亂,讓湖中的青蛙感到十分驚訝,它攔住了這群嚇蒙了的夥伴們,問出了什麼事,大家七嘴八舌地形容「咕咚」是個多麼可怕的怪物。青蛙問:「誰見到了?」大家互相推諉,誰也沒有親眼看見,於是決定回去看看明白。

回到湖邊,又聽見「咕咚」一聲,仔細一看,原來是木瓜掉進水裡發出的聲音,眾動物不禁大笑起來。

這寓言故事好笑嗎?很好笑,但是要是發生在我們自己身上就不那麼好笑了,比如說,某些Javaer一直在質疑Java系統的性能,於是我們自己也跟著懷疑Java的性能——這就是發生在我們身邊的真實「咕咚」,Java系統的性能問題本就是子虛烏有的事情,是我們自己嚇唬自己,其實,我們可以從四個方面分析該問題:

(1)沒有慢的系統,只有不滿足業務的系統

不管是使用C開發還是Java開發的項目,最終都會有一個產品誕生,或服務於大眾(如網站),或服務於企業(企業級應用),誰來決定一個系統的快慢呢?不是計算機,它只會使用毫秒、納秒去記錄時間但不會做判斷,它可以計算出一個交易執行了多長時間,但它不能決定這個時間是長還是短,那誰去判斷呢?是人,準確地說是使用者,即使是開發人員自己根據日誌記錄的時間來判斷系統是慢了還是快了,那也還是以使用者的身份來判斷的,對一個系統毫無瞭解的人員是無法判斷出一個系統的快慢的。

例如一個做統計的業務人員去看計費系統,即使響應需要N秒的時間,統計人員也會覺得非常快了,那是因為統計系統的結果經常是按照小時、天來計算的。再比如即時通信系統,有1秒內的延遲是可以接受的(發送者發出消息到接受者接收消息的時間間隔為1秒),但是語音通信系統若有1秒的延遲就是不可接受的了;發送郵件N分鐘後才收到,這是可以容忍的,但是對於同城銀行內轉賬來說,這個時間就是不可容忍的,必須在秒級完成。不同的系統所要求的性能不同,因此只要一個系統達到業務要求就可以認為它足夠快,我們不要期望跨系統間的性能對比,這是毫無意義的。

如果有使用者告訴你,「這個系統太慢了」,也就是在間接地提醒您:系統沒有滿足業務需求,尚待繼續努力。

(2)沒有慢的系統,只有架構不良的系統

在做系統架構設計時,架構師有沒有考慮並行計算?有沒有考慮雲計算技術?有沒有負載均衡?……這些都是解決我們性能問題的良方,只要架構設計得當,效率就不是問題。

即使是架構初期沒有考慮擴展性,那我們也有一些手段可解決性能問題。比如有一個批處理系統,系統建設時的目標是:5小時內生成2000萬條業務數據,可到第3年的時候,公司發生了大規模的變化(整合了其他同類公司),需要處理的數據更多了,在5小時內需要生成8000萬業務。於是就得考慮架構的擴展了。有一個很簡單的處理方案,即應用服務器水平擴展,增加業務數據源的縱向切割能力,均分數據壓力,這樣就可以很輕鬆地實現大數量的生成。

再比如,一個新聞網站,剛開始上線時訪問的人員不多,響應都是在毫秒級別的,隨著訪問量的激增,響應時間呈階梯型增加,資深會員流失率翻倍跳躍,如何解決該問題呢?解決方案有兩個:一是增加IP層的負載均衡,或者硬件設備,或者軟件架構,把訪問者分配到多個不同的應用服務器上,降低單台應用服務器的性能壓力;二是增強系統的處理能力,增大吞吐量,比如提升數據源的響應能力,劃分數據的熱度(如把數據劃分為Hot、Warm、Cold等區域,分配不同的硬件資源和服務等級),很多時候這兩個方案配合起來使用,會很快解決性能問題。

(3)沒有慢的系統,只有懶惰的技術人員

這裡的技術人員涉及面很大,可以是開發人員,也可以是維護人員,甚至是應用軟件的顧問人員(如數據庫顧問、App Server的顧問)等。一個系統出現問題,或者是投產前後立刻出現的性能問題,或者是運行中突發的性能問題,或者是逐漸增長的數據(用戶或業務數據)導致的性能問題,只要我們肯用心查找,並且擁有適當的資源(如源碼和支持資源),一般都是可以解決的。最可怕的是我們的技術人員對性能問題漠不關心,對時間效率不夠敏感,導致使用者怨聲載道,三人成虎,最終致使此系統成為一個「慢得無法使用的系統」。

這也要求我們在開發初期就適當考慮一下性能問題,但不要把性能排為頭號任務,它不是,它只是我們的一個關注點而已。

(4)沒有慢的系統,只有不願意投入的系統

這裡的投入指的是資源,包括軟硬件資源、人員資源及資金資源等,這不是項目組能夠單獨解決的問題,但是它會嚴重影響系統的性能。曾經遇到一個運行超過8年的分析系統,從1年前開始只要是高峰期它的速度就會慢下來,分析下來,發現是因為並發用戶超過了許可的數量,造成系統阻塞,性能緩慢,唯一解決的法就是購買更多的許可數量,但是8年了,一個系統的生命期還能有多少呢?——所以最後採用了自由放任的辦法,讓其自行走到壽命的終結點,然後建立新的分析系統。

當然,我們也會碰到查不出原因的性能問題,這不可否認,畢竟現在的系統越做越大,源代碼動輒就十萬、百萬級別,讓一個人或一個小團隊將其徹頭徹尾地查清楚也不現實,而且性能問題涉及面非常廣,如操作系統、數據庫、網絡、存儲等,要想對這些技術都非常熟悉也很困難,但查不出問題並不代表我們解決不了,是的,這與治療癌症相似,我們現在的科學還不知道它的發病機理,不知道為什麼會產生癌細胞,但我們知道割除病變部位能夠避免癌細胞擴散,性能問題也一樣:我們可能不知道問題產生的原因,但我們可以有N種手段來解決它。能夠解決的問題還算是問題嗎?

而且,性能只是衡量系統的一個輔助指標,而不是主指標,如果您與業務人員交流,說「我們可以把系統的響應時間提升到0.001秒內,但前提是不實現您提出的需求」,您猜業務人員會同意嗎?——不把我們這些「火星人」攆出門外已經算是客氣的了!

注意 對現代化的系統建設來說,性能就是一個大「咕咚」——看清它的本質吧。