軟件系統(tǒng)的穩(wěn)定性

軟件系統(tǒng)的穩(wěn)定性

軟件系統(tǒng)的穩(wěn)定性玛荞,主要決定于整體的系統(tǒng)架構(gòu)設(shè)計始腾,然而也不可忽略編程的細(xì)節(jié)州刽,正所謂“千里之堤,潰于蟻穴”浪箭,一旦考慮不周穗椅,看似無關(guān)緊要的代碼片段可能會帶來整體軟件系統(tǒng)的崩潰。這正是我閱讀Release It!的直接感受奶栖。究其原因匹表,一方面是程序員對代碼質(zhì)量的追求不夠,在項目進度的壓力下宣鄙,只考慮了功能實現(xiàn)袍镀,而不用過多的追求質(zhì)量屬性;第二則是對編程語言的正確編碼方式不夠了解冻晤,不知如何有效而正確的編碼苇羡;第三則是知識量的不足,在編程時沒有意識到實現(xiàn)會對哪些因素造成影響明也。

例如在Release It!一書中宣虾,給出了如下的Java代碼片段:

package com.example.cf.flightsearch; 
//... 
public class FlightSearch implements SessionBean {
    private MonitoredDataSource connectionPool;
    public List lookupByCity(. . .) throws SQLException, RemoteException { 
        Connection conn = null; 
        Statement stmt = null;
        try { 
            conn = connectionPool.getConnection(); 
            stmt = conn.createStatement();
             
            // Do the lookup logic
            // return a list of results
        } finally { 
            if (stmt != null) {
                stmt.close();
            }
            if (conn != null) { 
                conn.close();
            }
        }
    }
}

正是這一小段代碼惯裕,是造成Airline系統(tǒng)崩潰的罪魁禍?zhǔn)住3绦騿T充分地考慮了資源的釋放绣硝,但在這段代碼中他卻沒有對多個資源的釋放給予足夠的重視蜻势,而是以釋放單資源的做法去處理多資源。在finally語句塊中鹉胖,如果釋放Statement資源的操作失敗了握玛,就可能拋出異常,因為在finally中并沒有捕獲這種異常甫菠,就會導(dǎo)致后面的conn.close()語句沒有執(zhí)行挠铲,從而導(dǎo)致Connection資源未能及時釋放。最終導(dǎo)致連接池中存放了大量未能及時釋放的Connection資源寂诱,卻不能得到使用拂苹,直到連接池滿。當(dāng)后續(xù)請求lookupByCity()時痰洒,就會在調(diào)用connectionPool.getConnection()方法時被阻塞瓢棒。這些被阻塞的請求會越來越多,最后導(dǎo)致資源耗盡丘喻,整個系統(tǒng)崩潰脯宿。

Release It!的作者對Java中同步方法的使用也提出了警告。同步方法雖然可以較好地解決并發(fā)問題泉粉,在一定程度上可以避免出現(xiàn)資源搶占连霉、竟態(tài)條件和死鎖的情況。但它的一個副作用同步鎖可能導(dǎo)致線程阻塞嗡靡。這就要求同步方法的執(zhí)行時間不能太長跺撼。此外,Java的接口方法是不能標(biāo)記synchronized關(guān)鍵字叽躯。當(dāng)我們在調(diào)用封裝好的第三方API時财边,基于“面向接口設(shè)計”的原理肌括,可能調(diào)用者只知道公開的接口方法点骑,卻不知道實現(xiàn)類事實上將其實現(xiàn)為同步方法,這種未知性就可能存在隱患谍夭。

假設(shè)有這樣的一個接口:

public interface GlobalObjectCache {
    public Object get(String id);
}

如果接口方法get()的實現(xiàn)如下:

public synchronized Object get(String id){
    Object obj = items.get(id); 
    if(obj == null) {
        obj = create(id); 
        items.put(id, obj);
    } 
    return obj;
}
 
protected Object create(String id) {
    //...
}

這段代碼很簡單黑滴,當(dāng)調(diào)用者試圖根據(jù)id獲得目標(biāo)對象時,首先會在Cache中尋找紧索,如果有就直接返回袁辈;否則通過create()方法獲得目標(biāo)對象,然后再將它存儲到Cache中珠漂。create()方法是該類定義的一個非final方法晚缩,它執(zhí)行了DB的查詢功能∥膊玻現(xiàn)在,假設(shè)使用該類的用戶對它進行了擴展荞彼,例如定義RemoteAvailabilityCache類派生該類冈敛,并重寫create()方法,將原來的本地調(diào)用改為遠(yuǎn)程調(diào)用鸣皂。問題出現(xiàn)了抓谴。由于采用create()方法是遠(yuǎn)程調(diào)用,當(dāng)服務(wù)端比較繁忙時寞缝,發(fā)出的遠(yuǎn)程調(diào)用請求可能會被阻塞癌压。由于get()方法是同步方法,在方法體內(nèi)荆陆,每次只能有一個線程訪問它滩届,直到方法執(zhí)行完畢釋放鎖。現(xiàn)在create()方法被阻塞被啼,就會導(dǎo)致其他試圖調(diào)用RemoteAvailabilityCache對象的get()方法的線程隨之而被阻塞丐吓。進而可能導(dǎo)致系統(tǒng)崩潰。

當(dāng)然趟据,我們可以認(rèn)為這種擴展本身是不合理的券犁。但從設(shè)計的角度來看,它并沒有違背Liskove替換原則汹碱。從接口的角度看粘衬,它的行為也沒有發(fā)生任何改變,僅僅是實現(xiàn)發(fā)生了變化咳促。如果不是同步方法稚新,則一個調(diào)用線程的阻塞并不會影響到其他調(diào)用線程,問題就可以避免了跪腹。當(dāng)然褂删,這里的同步方法本身是合理的,因為只有采取同步的方式才能保證對Cache的讀取是支持并發(fā)的冲茸。書中給出這個例子屯阀,無非是要說明同步方法潛在的危險,提示我們在編寫代碼時轴术,需要考慮周全难衰。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市逗栽,隨后出現(xiàn)的幾起案子盖袭,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鳄虱,死亡現(xiàn)場離奇詭異弟塞,居然都是意外死亡,警方通過查閱死者的電腦和手機拙已,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門宣肚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人悠栓,你說我怎么就攤上這事霉涨。” “怎么了惭适?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵笙瑟,是天一觀的道長。 經(jīng)常有香客問我癞志,道長往枷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任凄杯,我火速辦了婚禮错洁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘戒突。我一直安慰自己屯碴,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布膊存。 她就那樣靜靜地躺著导而,像睡著了一般。 火紅的嫁衣襯著肌膚如雪隔崎。 梳的紋絲不亂的頭發(fā)上今艺,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天,我揣著相機與錄音爵卒,去河邊找鬼虚缎。 笑死,一個胖子當(dāng)著我的面吹牛钓株,可吹牛的內(nèi)容都是我干的实牡。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼享幽,長吁一口氣:“原來是場噩夢啊……” “哼铲掐!你這毒婦竟也來了拾弃?” 一聲冷哼從身側(cè)響起值桩,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎豪椿,沒想到半個月后奔坟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體携栋,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年咳秉,在試婚紗的時候發(fā)現(xiàn)自己被綠了婉支。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡澜建,死狀恐怖向挖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情炕舵,我是刑警寧澤何之,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站咽筋,受9級特大地震影響溶推,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜奸攻,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一蒜危、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧睹耐,春花似錦辐赞、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至捎迫,卻和暖如春晃酒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背窄绒。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工贝次, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人彰导。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓蛔翅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親位谋。 傳聞我的和親對象是個殘疾皇子山析,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法掏父,內(nèi)部類的語法笋轨,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,632評論 18 399
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,139評論 25 707
  • 一個朋友A向我吐槽說爵政,她因為吃了路邊的燒烤被一個同事赤裸裸的鄙視了仅讽。A生性活潑可愛,不拘小節(jié)钾挟,當(dāng)然洁灵,也是...
    木棉花zhi閱讀 255評論 0 3
  • 01. “快,快點掺出,別磨蹭……” 午夜徽千,四周一片寂靜無聲,兩個裝著侍衛(wèi)服的小兵抬著個麻布袋汤锨,匆匆向著樹林深處走去罐栈。...
    絨絨姜閱讀 922評論 0 5