今天對之前寫的servlet程式做了個簡單的效能測試發現了一些問題,經過解決這些問題沒有再重現,有些問題自己確切知道原因,有的則不太確定。
1、設定檔讀取問題
項目中使用.properties作為設定檔,剛開始讀取方法如下,使用的是Properties:
public  class ConfigHelper {        private static Properties properties = new Properties();    /***     *      * @param propertyName:屬性的key     * @param defaultVal:預設值     * @return 返回設定檔名值,若找不到配置的key,返回預設值     * @throws IOException     */    public static String getPropertyByKey(String propertyName, String defaultVal) throws IOException {        String fileName = ("/config.properties");         InputStream  fin = null;        String value = null;        try {            fin = ConfigHelper.class.getResourceAsStream(fileName);            properties.load(fin);            value =  properties.get(propertyName).toString();                  } catch (FileNotFoundException e) {            return defaultVal;        } catch (IOException e) {            return defaultVal;        }        finally        {             fin.close();        }                return value;    }}
 在沒有壓力的情況下這種方法是沒問題的,但一旦有點並發發現這樣使用Properties是有問題的,壓力測試下出現的問題:
 
剛開始嘗試使用synchronized:
public static synchronized String getPropertyByKey(String propertyName, String defaultVal)
 當時問題並沒有解決,此處省去N個字,最後解決方案如下,聲明一個類SafeProperties繼承自Properties,該類為單例:
/*** 讀取Properties屬性檔案* @author jdzhan*/public class SafeProperties extends Properties {    /**     *      */    private static final long serialVersionUID = 1L;        private static SafeProperties instance;    public static SafeProperties getInstance(String path){        if (instance != null){            return instance;        }else {            makeInstance(path);            return instance;        }    }    private static synchronized void makeInstance(String path){        if (instance == null){            instance = new SafeProperties(path);        }    }    private SafeProperties(String path){        InputStream is = getClass().getResourceAsStream(path);        try {            load(is);        } catch (IOException ex) {            System.err.println("錯誤資訊:  讀取屬性檔案失敗!");            System.err.println("請確認 【"+ path +"】 檔案是否存在。");        }    }}
 然後在修改ConfigHelper如下:
public class ConfigHelper {    private static Properties properties = null;        static{        String fileName = ("/config.properties");        properties=SafeProperties.getInstance(fileName);    }    /***     *      * @param propertyName     *            :屬性的key     * @param defaultVal     *            :預設值     * @return 返回設定檔名值,若找不到配置的key,返回預設值     * @throws IOException     */    public static synchronized String getPropertyByKey(String propertyName, String defaultVal)            throws IOException {        InputStream fin = null;        String value = null;        try {            value = properties.get(propertyName).toString();        } catch (Exception e) {            LogHelper.writeLog("讀取設定檔出錯:"+ExceptionUtils.getFullStackTrace(e));            return defaultVal;        } finally {            if (fin != null) {                fin.close();            }        }        return value;    }}
 
2、Mysql:Communications link failure
在壓力測試下Mysql也報了一大堆問題,其中有一個問題如下:
這個問題我找到一個比較有參考意義的串連:
http://stackoverflow.com/questions/2121829/mysql-jdbc-communications-link-failure
但是我最後解決這個問題(可能根本沒解決)方法是將Mysql的max_connections從1000增加到10000。
 
3、Mysql:No operations allowed after statement closed.
這個問題折騰我時間最長,結果發現原來是自己代碼的問題,因為靜態變數的原因,細節不說了。最後得出結論是:這個問題“顧名思義”,一般是因為你後面使用了前面已經關閉的資料庫連接造成的。