dbcp基本配置和重連配置

轉(zhuǎn)載自http://agapple.iteye.com/blog/772507

  1. 引入dbcp (選擇1.4)
    Java代碼 收藏代碼
<dependency>  
    <groupId>com.alibaba.external</groupId>  
    <artifactId>jakarta.commons.dbcp</artifactId>  
    <version>1.4</version>  
</dependency>  
  1. dbcp的基本配置
    相關(guān)配置說明:
    initialSize :連接池啟動時創(chuàng)建的初始化連接數(shù)量(默認值為0)
    maxActive :連接池中可同時連接的最大的連接數(shù)(默認值為8,調(diào)整為20遭殉,高峰單機器在20并發(fā)左右叔遂,自己根據(jù)應用場景定)
    maxIdle:連接池中最大的空閑的連接數(shù)辨嗽,超過的空閑連接將被釋放担平,如果設置為負數(shù)表示不限制(默認為8個菊碟,maxIdle不能設置太小斤儿,因為假如在高負載的情況下裹虫,連接的打開時間比關(guān)閉的時間快飞盆,會引起連接池中idle的個數(shù) 上升超過maxIdle娄琉,而造成頻繁的連接銷毀和創(chuàng)建,類似于jvm參數(shù)中的Xmx設置)
    minIdle:連接池中最小的空閑的連接數(shù)吓歇,低于這個數(shù)量會被創(chuàng)建新的連接(默認為0孽水,調(diào)整為5,該參數(shù)越接近maxIdle城看,性能越好女气,因為連接的創(chuàng)建和銷毀,都是需要消耗資源的测柠;但是不能太大炼鞠,因為在機器很空閑的時候缘滥,也會創(chuàng)建低于minidle個數(shù)的連接,類似于jvm參數(shù)中的Xmn設置)
    maxWait :最大等待時間谒主,當沒有可用連接時朝扼,連接池等待連接釋放的最大時間,超過該時間限制會拋出異常霎肯,如果設置-1表示無限等待(默認為無限擎颖,調(diào)整為60000ms,避免因線程池不夠用姿现,而導致請求被無限制掛起)
    poolPreparedStatements:開啟池的prepared(默認是false肠仪,未調(diào)整,經(jīng)過測試备典,開啟后的性能沒有關(guān)閉的好异旧。)
    maxOpenPreparedStatements:開啟池的prepared 后的同時最大連接數(shù)(默認無限制,同上提佣,未配置)
    minEvictableIdleTimeMillis :連接池中連接吮蛹,在時間段內(nèi)一直空閑, 被逐出連接池的時間
    (默認為30分鐘拌屏,可以適當做調(diào)整潮针,需要和后端服務端的策略配置相關(guān))
    removeAbandonedTimeout :超過時間限制,回收沒有用(廢棄)的連接(默認為 300秒倚喂,調(diào)整為180)
    removeAbandoned :超過removeAbandonedTimeout時間后每篷,是否進 行沒用連接(廢棄)的回收(默認為false,調(diào)整為true)

removeAbandoned參數(shù)解釋:
如果開啟了removeAbandoned端圈,當getNumIdle() < 2) and (getNumActive() > getMaxActive() - 3)時被觸發(fā).
舉例當maxActive=20, 活動連接為18,空閑連接為1時可以觸發(fā)"removeAbandoned".但是活動連接只有在沒有被使用的時間超 過"removeAbandonedTimeout"時才被回收
logAbandoned: 標記當連接被回收時是否打印程序的stack traces日志(默認為false焦读,未調(diào)整)
一般會是幾種情況出現(xiàn)需要removeAbandoned: 
代碼未在finally釋放connection , 不過我們都用sqlmapClientTemplate,底層都有鏈接釋放的過程
遇到數(shù)據(jù)庫死鎖舱权。以前遇到過后端存儲過程做了鎖表操作矗晃,導致前臺集群中連接池全都被block住,后續(xù)的業(yè)務處理因為拿不到鏈接所有都處理失敗了宴倍。

一份優(yōu)化過的配置:
基本配置代碼 收藏代碼

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">   
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />  
    <property name="url" value="xxxx" />  
    <property name="username"><value>xxxx</value></property>  
        <property name="password"><value>xxxxx</value></property>  
        <property name="maxActive"><value>20</value></property>  
        <property name="initialSize"><value>1</value></property>  
        <property name="maxWait"><value>60000</value></property>  
        <property name="maxIdle"><value>20</value></property>  
        <property name="minIdle"><value>3</value></property>  
        <property name="removeAbandoned"><value>true</value></property>  
        <property name="removeAbandonedTimeout"><value>180</value></property>  
        <property name="connectionProperties"><value>clientEncoding=GBK</value></property>  
</bean>  
  1. dbcp的鏈接validate配置
    dbcp是采用了commons-pool做為其連接池管理张症,testOnBorrow,testOnReturn, testWhileIdle是pool是提供的幾種校驗機制,通過外部鉤子的方式回調(diào)dbcp的相關(guān)數(shù)據(jù)庫鏈接(validationQuery)校驗
    dbcp相關(guān)外部鉤子類:PoolableConnectionFactory,繼承于common-pool PoolableObjectFactory
    dbcp通過GenericObjectPool這一入口鸵贬,進行連接池的borrow,return處理
    testOnBorrow : 顧明思義俗他,就是在進行borrowObject進行處理時,對拿到的connection進行validateObject校驗
    testOnReturn : 顧明思義阔逼,就是在進行returnObject對返回的connection進行validateObject校驗拯辙,個人覺得對數(shù)據(jù)庫連接池的管理意義不大
    testWhileIdle : 關(guān)注的重點,GenericObjectPool中針對pool管理,起了一個Evict的TimerTask定時線程進行控制(可通過設置參數(shù)timeBetweenEvictionRunsMillis>0),定時對線程池中的鏈接進行validateObject校驗涯保,對無效的鏈接進行關(guān)閉后诉濒,會調(diào)用ensureMinIdle,適當建立鏈接保證最小的minIdle連接數(shù)夕春。
    timeBetweenEvictionRunsMillis,設置的Evict線程的時間未荒,單位ms,大于0才會開啟evict檢查線程
    validateQuery及志, 代表檢查的sql
    validateQueryTimeout片排, 代表在執(zhí)行檢查時,通過statement設置速侈,statement.setQueryTimeout(validationQueryTimeout)
    numTestsPerEvictionRun率寡,代表每次檢查鏈接的數(shù)量,建議設置和maxActive一樣大倚搬,這樣每次可以有效檢查所有的鏈接.

Validate配置代碼 收藏代碼

<property name="testWhileIdle"><value>true</value></property> <!-- 打開檢查,用異步線程evict進行檢查 -->  
    <property name="testOnBorrow"><value>false</value></property>  
    <property name="testOnReturn"><value>false</value></property>  
    <property name="validationQuery"><value>select sysdate from dual</value></property>  
    <property name="validationQueryTimeout"><value>1</value></property>  
    <property name="timeBetweenEvictionRunsMillis"><value>30000</value></property>  
    <property name="numTestsPerEvictionRun"><value>20</value></property>  

相關(guān)配置需求:

目前網(wǎng)站的應用大部分的瓶頸還是在I/O這一塊冶共,大部分的I/O還是在數(shù)據(jù)庫的這一層面上,每一個請求可能會調(diào)用10來次SQL查詢每界,如果不走事務捅僵,一個請求會重復獲取鏈接,如果每次獲取鏈接都進行validateObject眨层,性能開銷不是很能接受庙楚,可以假定一次SQL操作消毫0.5~1ms(一般走了網(wǎng)絡請求基本就這數(shù))
網(wǎng)站異常數(shù)據(jù)庫重啟,網(wǎng)絡異常斷開的頻率是非常低的趴樱,一般也就在數(shù)據(jù)庫升級馒闷,演習維護時才會進行,而且一般也是選在晚上叁征,訪問量相對比較低的請求纳账,而且一般會有人員值班關(guān)注,所以異步的validateObject是可以接受航揉,但一個前提需要確保能保證在一個合理的時間段內(nèi)塞祈,數(shù)據(jù)庫能完成自動重聯(lián)金刁。

從代碼層面簡單介紹下dbcp的validate實現(xiàn):

  1. common-pools提供的PoolableObjectFactory帅涂,針對pool池的管理操作接口

Java代碼 收藏代碼

public interface PoolableObjectFactory {  
  
  Object makeObject() throws Exception;  
  
  void destroyObject(Object obj) throws Exception;  
  
  boolean validateObject(Object obj);  
  
  void activateObject(Object obj) throws Exception;  
  
  void passivateObject(Object obj) throws Exception;  
}  
  1. dbcp實現(xiàn)的pool從池管理操作

這里貼了一個相關(guān)validate代碼,具體類可見:PoolableConnectionFactory.validateConnection()

Java代碼 收藏代碼

public class PoolableConnectionFactory implements PoolableObjectFactory {  
public boolean validateObject(Object obj) { //驗證validateObject  
        if(obj instanceof Connection) {  
            try {  
                validateConnection((Connection) obj);  
                return true;  
            } catch(Exception e) {  
                return false;  
            }  
        } else {  
            return false;  
        }  
    }  
public void validateConnection(Connection conn) throws SQLException {  
        String query = _validationQuery;  
        if(conn.isClosed()) {  
            throw new SQLException("validateConnection: connection closed");  
        }  
        if(null != query) {  
            Statement stmt = null;  
            ResultSet rset = null;  
            try {  
                stmt = conn.createStatement();  
                if (_validationQueryTimeout > 0) {  
                    stmt.setQueryTimeout(_validationQueryTimeout);  
                }  
                rset = stmt.executeQuery(query);  
                if(!rset.next()) {  
                    throw new SQLException("validationQuery didn't return a row");  
                }  
            } finally {  
                if (rset != null) {  
                    try {  
                        rset.close();  
                    } catch(Exception t) {  
                        // ignored  
                    }  
                }  
                if (stmt != null) {  
                    try {  
                        stmt.close();  
                    } catch(Exception t) {  
                        // ignored  
                    }  
                }  
            }  
        }  
    }  
}  
  1. pool池的evict調(diào)用代碼:GenericObjectPool (apache commons pool version 1.5.4)
    Java代碼 收藏代碼
protected synchronized void startEvictor(long delay) { //啟動Evictor為TimerTask  
        if(null != _evictor) {  
            EvictionTimer.cancel(_evictor);  
            _evictor = null;  
        }  
        if(delay > 0) {  
            _evictor = new Evictor();  
            EvictionTimer.schedule(_evictor, delay, delay);  
        }  
    }  
  
for (int i=0,m=getNumTests();i<m;i++) {  
            final ObjectTimestampPair pair;  
           .......  
            boolean removeObject = false;  
            // 空閑鏈接處理  
            final long idleTimeMilis = System.currentTimeMillis() - pair.tstamp;  
            if ((getMinEvictableIdleTimeMillis() > 0) &&  
                    (idleTimeMilis > getMinEvictableIdleTimeMillis())) {  
                removeObject = true;  
            } else if ((getSoftMinEvictableIdleTimeMillis() > 0) &&  
                    (idleTimeMilis > getSoftMinEvictableIdleTimeMillis()) &&  
                    ((getNumIdle() + 1)> getMinIdle())) {   
                removeObject = true;  
            }  
            //  testWhileIdle sql 檢查處理  
            if(getTestWhileIdle() && !removeObject) {  
                boolean active = false;  
                try {  
                    _factory.activateObject(pair.value);  
                    active = true;  
                } catch(Exception e) {  
                    removeObject=true;  
                }  
                if(active) {  
                    if(!_factory.validateObject(pair.value)) {   
                        removeObject=true;  
                    } else {  
                        try {  
                            _factory.passivateObject(pair.value);  
                        } catch(Exception e) {  
                            removeObject=true;  
                        }  
                    }  
                }  
            }  
            // 真正關(guān)閉  
            if (removeObject) {  
                try {  
                    _factory.destroyObject(pair.value);  
                } catch(Exception e) {  
                    // ignored  
                }  
            }  

注意: 目前dbcp的pool的實現(xiàn)是使用了公用的apache common pools進行擴展處理尤蛮,所以和原生的連接池處理媳友,代碼看上去有點別扭,感覺自動重連這塊異常處理不怎么好产捞,我也就只重點關(guān)注了這部分代碼而已

  1. dbcp的鏈接自動重鏈相關(guān)測試
    相關(guān)場景:
    數(shù)據(jù)庫意外重啟后醇锚,原先的數(shù)據(jù)庫連接池能自動廢棄老的無用的鏈接,建立新的數(shù)據(jù)庫鏈接
    網(wǎng)絡異常中斷后,原先的建立的tcp鏈接焊唬,應該能進行自動切換
    測試需求1步驟
    建立一testCase代碼
    配置mysql數(shù)據(jù)庫
    循環(huán)執(zhí)行在SQL查詢過程
    異常重啟mysql數(shù)據(jù)庫
    測試需求2步驟
    建立一testCase代碼
    配置mysql數(shù)據(jù)庫
    循環(huán)執(zhí)行在SQL查詢過程
    通過iptables禁用網(wǎng)絡鏈接
    /sbin/iptables -A INPUT -s 10.16.2.69 -j REJECT
    /sbin/iptables -A FORWARD -p tcp -s 10.16.2.69 --dport 3306 -m state --state NEW,ESTABLISHED -j DROP
    1. iptables -F 清空規(guī)則恋昼,恢復鏈接通道。

測試需求問題記錄

分別測試了兩種配置赶促,有validateObject的配置和沒有validateObject的相關(guān)配置液肌。

  1. 沒有validate配置
    問題一: 異常重啟mysql數(shù)據(jù)庫后,居然也可以自動恢復鏈接鸥滨,sql查詢正常
    跟蹤了一下代碼嗦哆,發(fā)現(xiàn)這么一個問題:
    在數(shù)據(jù)庫關(guān)閉的時候,client中pool通過borrowObject獲取一個異常鏈接返回給client
    client在使用具體的異常鏈接進行sql調(diào)用出錯了婿滓,拋了異常
    在finally老速,調(diào)用connection.close(),本意是應該調(diào)用pool通過returnObject返回到的池中凸主,但在跟蹤代碼時橘券,未見調(diào)用GenericObjectPool的returnObject
    繼續(xù)查,發(fā)現(xiàn)在dbcp在中PoolingDataSource(實現(xiàn)DataSource接口)調(diào)用PoolableConnection(dbcp pool相關(guān)的delegate操作)進行相應關(guān)閉時秕铛,會檢查_conn.isClosed()约郁,針對DataSource如果isClosed返回為true的則不調(diào)用returnObject,直接丟棄了鏈接
    解釋:
    正因為在獲取異常鏈接后但两,因為做了_conn.isClosed()判斷鬓梅,所以異常鏈接并沒有返回到連接池中,所以到數(shù)據(jù)庫重啟恢復后谨湘,每次都是調(diào)用pool重新構(gòu)造一個新的connection绽快,所以后面就正常了
    _conn.isClosed()是否保險,從jdk的api描述中: A connection is closed if the method close has been called on it or if certain fatal errors have occurred. 里面提供兩種情況紧阔,一種就是被調(diào)用了closed方法坊罢,另一種就是出現(xiàn)一些異常也說的比較含糊。
    問題二:validateObject調(diào)用時擅耽,dbcp設置的validationQueryTimeout居然沒效果
    看了mysql statement代碼實現(xiàn)活孩,找到了答案。
    mysql com.mysql.jdbc.statemen 部分代碼

timeout時間處理:
Java代碼 收藏代碼
timeoutTask = new CancelTask();
//通過TimerTask啟動一定時任務
Connection.getCancelTimer().schedule(timeoutTask, this.timeoutInMillis);

對應的CancelTask的代碼:

Java代碼 收藏代碼

class CancelTask extends TimerTask {  
  
        long connectionId = 0;  
  
        CancelTask() throws SQLException {  
            connectionId = connection.getIO().getThreadId();  
        }  
  
        public void run() {  
  
            Thread cancelThread = new Thread() {  
  
                public void run() {  
                    Connection cancelConn = null;  
                    java.sql.Statement cancelStmt = null;  
  
                    try {  
                        cancelConn = connection.duplicate();  
                        cancelStmt = cancelConn.createStatement();  
                                                // 簡單暴力乖仇,再發(fā)起一條KILL SQL憾儒,關(guān)閉先前的sql thread id  
                        cancelStmt.execute("KILL QUERY " + connectionId);  
                        wasCancelled = true;  
                    } catch (SQLException sqlEx) {  
                        throw new RuntimeException(sqlEx.toString());  
                    } finally {  
                        if (cancelStmt != null) {  
                            try {  
                                cancelStmt.close();  
                            } catch (SQLException sqlEx) {  
                                throw new RuntimeException(sqlEx.toString());  
                            }  
                        }  
  
                        if (cancelConn != null) {  
                            try {  
                                cancelConn.close();  
                            } catch (SQLException sqlEx) {  
                                throw new RuntimeException(sqlEx.toString());  
                            }  
                        }  
                    }  
                }  
            };  
  
            cancelThread.start();  
        }  
    }  

原因總結(jié)一句話: queryTimeout的實現(xiàn)是通過底層數(shù)據(jù)庫提供的機制,比如KILL QUERY pid. 如果此時的網(wǎng)絡不通乃沙,出現(xiàn)阻塞現(xiàn)象起趾,對應的kill命令也發(fā)不出去,所以timeout設置的超時沒效果警儒。
4.最后

最后還是決定配置testWhileIdle掃描训裆,主要考慮:
pool池中的鏈接如果未被使用,可以通過testWhileIdle進行鏈接檢查,避免在使用時后總要失敗那么一次边琉,可以及時預防
配合連接池的minEvictableIdleTimeMillis(空閑鏈接)属百,removeAbandoned(未釋放的鏈接),可以更好的去避免因為一些異常情況引起的問題变姨,防范于未然诸老。比如使用一些分布式數(shù)據(jù)庫的中間件,會有空閑鏈接關(guān)閉的動作钳恕,動態(tài)伸縮連接池别伏,這時候需要能及時的發(fā)現(xiàn),避免請求失敗忧额。
testOnBorrow個人不太建議使用厘肮,存在性能問題,試想一下連接一般會在什么情況出問題睦番,網(wǎng)絡或者服務端異常終端空閑鏈接类茂,網(wǎng)絡中斷你testOnBorrow檢查發(fā)現(xiàn)不對再取一個鏈接還是不對,針對空閑鏈接處理異常關(guān)閉托嚣,可以從好業(yè)務端的重試策略進行考慮巩检,同時配置客戶端的空閑鏈接超時時間,maxIdle,minIdle等示启。


新加的內(nèi)容:
5.dbcp密碼加密處理

以前使用jboss的jndi數(shù)據(jù)源的方式兢哭,是通過配置oracle-ds.xml,可以設置<security-domain>EncryptDBPassword</security-domain>夫嗓,引用jboss login-config.xml配置的加密配置迟螺。

Java代碼 收藏代碼

<application-policy name="EncryptDBPassword">  
        <authentication>  
            <login-module code="org.jboss.resource.security.SecureIdentityLoginModule" flag="required">  
                <module-option name="username">${username}</module-option>  
                <module-option name="password">${password_encrypt}</module-option>  
                <module-option name="managedConnectionFactoryName">jboss.jca:service=LocalTxCM,name=${jndiName}</module-option>  
            </login-module>  
        </authentication>  
    </application-policy>  

為了能達到同樣的效果,切換為spring dbcp配置時舍咖,也有類似密碼加密的功能矩父,運行期進行密碼decode,最后進行數(shù)據(jù)鏈接。

實現(xiàn)方式很簡單排霉,分析jboss的對應SecureIdentityLoginModule的實現(xiàn)窍株,無非就是走了Blowfish加密算法,自己拷貝實現(xiàn)一份攻柠。

Java代碼 收藏代碼

private static String encode(String secret) throws NoSuchPaddingException, NoSuchAlgorithmException,  
                                               InvalidKeyException, BadPaddingException, IllegalBlockSizeException {  
        byte[] kbytes = "jaas is the way".getBytes();  
        SecretKeySpec key = new SecretKeySpec(kbytes, "Blowfish");  
  
        Cipher cipher = Cipher.getInstance("Blowfish");  
        cipher.init(Cipher.ENCRYPT_MODE, key);  
        byte[] encoding = cipher.doFinal(secret.getBytes());  
        BigInteger n = new BigInteger(encoding);  
        return n.toString(16);  
    }  
  
    private static char[] decode(String secret) throws NoSuchPaddingException, NoSuchAlgorithmException,  
                                               InvalidKeyException, BadPaddingException, IllegalBlockSizeException {  
        byte[] kbytes = "jaas is the way".getBytes();  
        SecretKeySpec key = new SecretKeySpec(kbytes, "Blowfish");  
  
        BigInteger n = new BigInteger(secret, 16);  
        byte[] encoding = n.toByteArray();  
  
        Cipher cipher = Cipher.getInstance("Blowfish");  
        cipher.init(Cipher.DECRYPT_MODE, key);  
        byte[] decode = cipher.doFinal(encoding);  
        return new String(decode).toCharArray();  
    }  

最后的配置替換為:

Xml代碼 收藏代碼

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">   
......  
        <property name="password"><!-- 注意多了一層轉(zhuǎn)化球订,將密碼串調(diào)用decode解密為最初的數(shù)據(jù)庫密碼 -->  
            <bean class="com.xxxxx.EncryptDBPasswordFactory">  
                <property name="password" value="${xxxx.password.encrypted}" />  
            </bean>  
        </property>  
........  
</bean>  

新加的內(nèi)容:
6.數(shù)據(jù)庫重連機制

常見的問題:

  1. 數(shù)據(jù)庫意外重啟后,原先的數(shù)據(jù)庫連接池能自動廢棄老的無用的鏈接辙诞,建立新的數(shù)據(jù)庫鏈接
  2. 網(wǎng)絡異常中斷后辙售,原先的建立的tcp鏈接轻抱,應該能進行自動切換飞涂。比如網(wǎng)站演習中的交換機重啟會導致網(wǎng)絡瞬斷
  3. 分布式數(shù)據(jù)庫中間件,比如amoeba會定時的將空閑鏈接異常關(guān)閉,客戶端會出現(xiàn)半開的空閑鏈接较店。

大致的解決思路:

  1. sql心跳檢查
    主動式 ,即我前面提到的sql validate相關(guān)配置
  2. 請求探雷
    犧牲小我士八,完成大我的精神。 拿鏈接嘗試一下梁呈,發(fā)現(xiàn)處理失敗丟棄鏈接婚度,探雷的請求總會失敗幾個,就是前面遇到的問題一官卡,dbcp已經(jīng)支持該功能蝗茁,不需要額外置。
  3. 設置合理的超時時間寻咒,
    解決半開鏈接. 一般數(shù)據(jù)庫mysql,oracle都有一定的鏈接空閑斷開的機制哮翘,而且當你使用一些分布式中間件(軟件一類的),空閑鏈接控制會更加嚴格毛秘,這時候設置合理的超時時間可以有效避免半開鏈接饭寺。
    一般超時時間,dbcp主要是minEvictableIdleTimeMillis(空閑鏈接) , removeAbandonedTimeout(鏈接泄漏)叫挟〖璩祝可以見前面的參數(shù)解釋。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末抹恳,一起剝皮案震驚了整個濱河市员凝,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌奋献,老刑警劉巖绊序,帶你破解...
    沈念sama閱讀 222,627評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異秽荞,居然都是意外死亡骤公,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評論 3 399
  • 文/潘曉璐 我一進店門扬跋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來阶捆,“玉大人,你說我怎么就攤上這事钦听∪魇裕” “怎么了?”我有些...
    開封第一講書人閱讀 169,346評論 0 362
  • 文/不壞的土叔 我叫張陵朴上,是天一觀的道長垒棋。 經(jīng)常有香客問我,道長痪宰,這世上最難降的妖魔是什么叼架? 我笑而不...
    開封第一講書人閱讀 60,097評論 1 300
  • 正文 為了忘掉前任畔裕,我火速辦了婚禮,結(jié)果婚禮上乖订,老公的妹妹穿的比我還像新娘扮饶。我一直安慰自己,他們只是感情好乍构,可當我...
    茶點故事閱讀 69,100評論 6 398
  • 文/花漫 我一把揭開白布甜无。 她就那樣靜靜地躺著,像睡著了一般哥遮。 火紅的嫁衣襯著肌膚如雪岂丘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,696評論 1 312
  • 那天眠饮,我揣著相機與錄音元潘,去河邊找鬼。 笑死君仆,一個胖子當著我的面吹牛翩概,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播返咱,決...
    沈念sama閱讀 41,165評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼钥庇,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了咖摹?” 一聲冷哼從身側(cè)響起评姨,我...
    開封第一講書人閱讀 40,108評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎萤晴,沒想到半個月后吐句,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,646評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡店读,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,709評論 3 342
  • 正文 我和宋清朗相戀三年嗦枢,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屯断。...
    茶點故事閱讀 40,861評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡文虏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出殖演,到底是詐尸還是另有隱情氧秘,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布趴久,位于F島的核電站丸相,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏彼棍。R本人自食惡果不足惜灭忠,卻給世界環(huán)境...
    茶點故事閱讀 42,196評論 3 336
  • 文/蒙蒙 一膳算、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧更舞,春花似錦、人聲如沸坎吻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瘦真。三九已至刊头,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間诸尽,已是汗流浹背原杂。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留您机,地道東北人穿肄。 一個月前我還...
    沈念sama閱讀 49,287評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像际看,于是被迫代替她去往敵國和親咸产。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,860評論 2 361

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