你是如何讓老闆相信你的程序?

就如Google總監說的,我還沒見過沒有bug的程序。

即使如此,你還是可以做得更好:採用預估、預演、持續改善的方式,可以讓你對你程序更有信心。

比如首先從產品經理那裏得知系統將來的在線人數、最大事務併發量以及使用環境等,並將之換算爲系統參數。接着嘗試編寫測試去模擬它,以驗證程序是否能勝任。最後如果程序發生錯誤,想辦法改善架構或程序。

預估

一個好的產品經理總是可以告訴你需要的信息,比如系統的規模、可能的在線人數、事務併發量等,你也可以從客戶那裏獲得這些信息。你需要做的就是應用一些數學,將之轉換爲你測試程序的依據。

比如我有一個公路測速的項目,從用戶那獲得這樣的信息:

  1. 即將有100個測速點,每個測速點都會有一個測速器。
  2. 測速器最快0.7s完成拍攝圖片和測速工作,並即時上傳圖片。
  3. 要完成的功能就是開發一個Web服務(圖片服務器,環境不支持ftp)來接受所有點的圖片上傳
  4. 每張圖片300k;

這個web服務沒有任何業務,需要考慮的就是能否支持100個點同時上傳圖片?關鍵考慮的有帶寬、CPU以及硬盤。所以我們可以這樣預估:帶寬 = 100 * 300k * 2(大約值,單張圖片上傳的時間,單位爲秒) *sqrt(2)/(1024*0.7)=100M;硬盤容量=測速點的每日車流量*300k*100*天數,而CPU很少情況下需要在這裏考慮。

這一步很重要,而接下來的事情就簡單多了。

預演

編寫模擬程序,這個程序應該是多併發的。

使用java的併發工具包可以輕鬆實現,比如使用Executors.newFixedThreadPool(併發線程數)創建一個限定線程數的共享池,然後使用CountDownLatch類實現併發

ExecutorService executor = Executors.newFixedThreadPool(c);

。。。

private void concurrency() throws Exception{

log.debug("....................... start test ...................");

long sTime = System.currentTimeMillis();

final CountDownLatch ready = new CountDownLatch(c);

final CountDownLatch start = new CountDownLatch(1);

final CountDownLatch done = new CountDownLatch(c);

final AtomicInteger success = new AtomicInteger(0);

for (int i = 0; i < c; i++) {

executor.execute(new Runnable() {

public void run() {

ready.countDown();

try {

start.await();

boolean result = upload();

if(result) {

success.incrementAndGet();

}

} catch (Exception e1) {

} finally {

done.countDown();

}

}

});

}

ready.await();

start.countDown();

done.await();

long eTime = System.currentTimeMillis();

log.info("....................... time for spend is " + (eTime - sTime)/1000 + " ...................");

if(success.get()!= c) {

log.warn("....................... count for files uploaded successly is " + success.get() + " .but it expect to be " + c);

} else {

log.info("....................... all the file have upload successly! ...................");

}

sCount += success.get();

fCount += c - success.get();

Thread.sleep(1000);

}

代碼中的concurrency()函數支持併發調用uoload()方法c次,並記錄上傳失敗或者成功的次數。

持續改善

如果需要改善你的程序,首先你得知道它發生了什麼問題,着意味着你想要一些工具。

比如,上述程序中的代碼ExecutorService executor = Executors.newFixedThreadPool(c);之前被放在concurrency()方法的開頭,我使用while(true)循環中調用了該方法,期望它能一直正常運行1天一夜,但是它才10分鐘就發生錯誤了,結果截圖如下

clip_image002

我一直調試了這個程序幾個小時,一直沒有發現問題,後來打開jconsole工具(這是一個java自帶的監控工具),然後得到這樣的圖標。

clip_image002[6]

我發現了問題:我的程序在持續的創建線程。

但是我代碼的意圖是創建一個設定線程數的共享池,這樣即使我循環無法次,它也只會創建和我設定的值一樣多的線程。我一開始就考慮了要避免浪費。

直到這裏,我又從頭仔細閱讀了代碼,我終於知道自己犯了很愚蠢的錯誤--就是那句代碼,它實現的是每次調用都創建一個線程池,所以線程數線性增加的。我將那句代碼被移出方法意外,問題就解決了。

除了線程數,通過工具你還可以看到程序使用的內存、CPU,創建的實例等等。你可以根據這些圖表來決定如何改善你的架構和程序。這個在下節在介紹。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章