com.alibaba.externaljakarta.commons.dbcp1.42.dbcp的基本配置相關(guān)配置說明:initialSize:連接池啟動時創(chuàng)建的初始化連接數(shù)量(默認值為" />

欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

dbcp基本配置和重連配置

系統(tǒng) 1841 0

最近在看一些dbcp的相關(guān)內(nèi)容,順便做一下記錄,免得自己給忘記了。

1. 引入dbcp (選擇1.4)

    <dependency>
	<groupId>com.alibaba.external</groupId>
	<artifactId>jakarta.commons.dbcp</artifactId>
	<version>1.4</version>
</dependency>
  

?

2. dbcp的基本配置

相關(guān)配置說明:

?

  1. initialSize :連接池啟動時創(chuàng)建的初始化連接數(shù)量(默認值為0)
  2. maxActive :連接池中可同時連接的最大的連接數(shù)(默認值為8,調(diào)整為20,高峰單機器在20并發(fā)左右,自己根據(jù)應(yīng)用場景定)
  3. maxIdle:連接池中最大的空閑的連接數(shù),超過的空閑連接將被釋放,如果設(shè)置為負數(shù)表示不限制(默認為8個,maxIdle不能設(shè)置太小,因為假如在高負載的情況下,連接的打開時間比關(guān)閉的時間快,會引起連接池中idle的個數(shù) 上升超過maxIdle,而造成頻繁的連接銷毀和創(chuàng)建,類似于jvm參數(shù)中的Xmx設(shè)置)
  4. minIdle:連接池中最小的空閑的連接數(shù),低于這個數(shù)量會被創(chuàng)建新的連接(默認為0,調(diào)整為5,該參數(shù)越接近maxIdle,性能越好,因為連接的創(chuàng)建和銷毀,都是需要消耗資源的;但是不能太大,因為在機器很空閑的時候,也會創(chuàng)建低于minidle個數(shù)的連接,類似于jvm參數(shù)中的Xmn設(shè)置)
  5. maxWait ?:最大等待時間,當沒有可用連接時,連接池等待連接釋放的最大時間,超過該時間限制會拋出異常,如果設(shè)置-1表示無限等待(默認為無限,調(diào)整為60000ms,避免因線程池不夠用,而導(dǎo)致請求被無限制掛起)
  6. poolPreparedStatements:開啟池的prepared(默認是false,未調(diào)整,經(jīng)過測試,開啟后的性能沒有關(guān)閉的好。)
  7. maxOpenPreparedStatements:開啟池的prepared 后的同時最大連接數(shù)(默認無限制,同上,未配置)
  8. minEvictableIdleTimeMillis ?:連接池中連接,在時間段內(nèi)一直空閑, 被逐出連接池的時間
  9. (默認為30分鐘,可以適當做調(diào)整,需要和后端服務(wù)端的策略配置相關(guān))
  10. removeAbandonedTimeout ?:超過時間限制,回收沒有用(廢棄)的連接(默認為 300秒,調(diào)整為180)
  11. removeAbandoned ?:超過removeAbandonedTimeout時間后,是否進 行沒用連接(廢棄)的回收(默認為false,調(diào)整為true)

removeAbandoned參數(shù)解釋:
  1. 如果開啟了removeAbandoned,當getNumIdle() < 2) and (getNumActive() > getMaxActive() - 3)時被觸發(fā).
  2. 舉例當maxActive=20, 活動連接為18,空閑連接為1時可以觸發(fā)"removeAbandoned".但是活動連接只有在沒有被使用的時間超 過"removeAbandonedTimeout"時才被回收
  3. logAbandoned: 標記當連接被回收時是否打印程序的stack traces日志(默認為false,未調(diào)整)

一般會是幾種情況出現(xiàn)需要 removeAbandoned : 
  1. 代碼未在 finally 釋放 connection ,  不過我們都用 sqlmapClientTemplate ,底層都有鏈接釋放的過程
  2. 遇到數(shù)據(jù)庫死鎖 。以前遇到過后端存儲過程做了鎖表操作,導(dǎo)致前臺集群中連接池全都被 block 住,后續(xù)的業(yè)務(wù)處理因為拿不到鏈接所有都處理失敗了。

一份優(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>
            
?
?

2. dbcp的鏈接validate配置
  1. dbcp是采用了commons-pool做為其連接池管理,testOnBorrow,testOnReturn, testWhileIdle是pool是提供的幾種校驗機制,通過外部鉤子的方式回調(diào)dbcp的相關(guān)數(shù)據(jù)庫鏈接(validationQuery)校驗
  2. dbcp相關(guān)外部鉤子類:PoolableConnectionFactory,繼承于common-pool PoolableObjectFactory
  3. dbcp通過GenericObjectPool這一入口,進行連接池的borrow,return處理
  4. testOnBorrow : 顧明思義,就是在進行borrowObject進行處理時,對拿到的connection進行validateObject校驗
  5. testOnReturn : 顧明思義,就是在進行returnObject對返回的connection進行validateObject校驗,個人覺得對數(shù)據(jù)庫連接池的管理意義不大
  6. testWhileIdle : 關(guān)注的重點,GenericObjectPool中針對pool管理,起了一個Evict的TimerTask定時線程進行控制(可通過設(shè)置參數(shù)timeBetweenEvictionRunsMillis>0),定時對線程池中的鏈接進行validateObject校驗,對無效的鏈接進行關(guān)閉后,會調(diào)用ensureMinIdle,適當建立鏈接保證最小的minIdle連接數(shù)。
  7. timeBetweenEvictionRunsMillis,設(shè)置的Evict線程的時間,單位ms,大于0才會開啟evict檢查線程
  8. validateQuery, 代表檢查的sql
  9. validateQueryTimeout, 代表在執(zhí)行檢查時,通過statement設(shè)置,statement.setQueryTimeout(validationQueryTimeout)
  10. numTestsPerEvictionRun,代表每次檢查鏈接的數(shù)量,建議設(shè)置和maxActive一樣大,這樣每次可以有效檢查所有的鏈接.

        <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)配置需求:

?

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

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

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

?

    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;
}
  

?

?

2. dbcp實現(xiàn)的pool從池管理操作

?

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

?

    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
                    }
                }
            }
        }
    }

....

}
  

?

3. pool池的evict調(diào)用代碼:GenericObjectPool (apache commons pool version 1.5.4)

    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)注了這部分代碼而已? ?.


?

3. dbcp的鏈接自動重鏈相關(guān)測試

相關(guān)場景:

  1. 數(shù)據(jù)庫意外重啟后,原先的數(shù)據(jù)庫連接池能自動廢棄老的無用的鏈接,建立新的數(shù)據(jù)庫鏈接
  2. 網(wǎng)絡(luò)異常中斷后,原先的建立的tcp鏈接,應(yīng)該能進行自動切換

測試需求1步驟

  1. 建立一testCase代碼
  2. 配置mysql數(shù)據(jù)庫
  3. 循環(huán)執(zhí)行在SQL查詢過程
  4. 異常重啟mysql數(shù)據(jù)庫

測試需求2步驟

  1. 建立一testCase代碼
  2. 配置mysql數(shù)據(jù)庫
  3. 循環(huán)執(zhí)行在SQL查詢過程
  4. 通過iptables禁用網(wǎng)絡(luò)鏈接

/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

???? 5. iptables -F 清空規(guī)則,恢復(fù)鏈接通道。

?

測試需求問題記錄

?

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

1. 沒有validate配置
問題一: 異常重啟mysql數(shù)據(jù)庫后,居然也可以自動恢復(fù)鏈接,sql查詢正常
跟蹤了一下代碼,發(fā)現(xiàn)這么一個問題:

  1. 在數(shù)據(jù)庫關(guān)閉的時候,client中pool通過borrowObject獲取一個異常鏈接返回給client
  2. client在使用具體的異常鏈接進行sql調(diào)用出錯了,拋了異常
  3. 在finally,調(diào)用connection.close(),本意是應(yīng)該調(diào)用pool通過returnObject返回到的池中,但在跟蹤代碼時,未見調(diào)用GenericObjectPool的returnObject
  4. 繼續(xù)查,發(fā)現(xiàn)在dbcp在中PoolingDataSource(實現(xiàn)DataSource接口)調(diào)用PoolableConnection(dbcp pool相關(guān)的delegate操作)進行相應(yīng)關(guān)閉時,會檢查_conn.isClosed(),針對DataSource如果isClosed返回為true的則不調(diào)用returnObject,直接丟棄了鏈接??

解釋:

  • 正因為在獲取異常鏈接后,因為做了_conn.isClosed()判斷,所以異常鏈接并沒有返回到連接池中,所以到數(shù)據(jù)庫重啟恢復(fù)后,每次都是調(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設(shè)置的validationQueryTimeout居然沒效果

看了mysql statement代碼實現(xiàn),找到了答案。?

mysql com.mysql.jdbc.statemen 部分代碼

?

timeout時間處理:

    timeoutTask = new CancelTask();
//通過TimerTask啟動一定時任務(wù)
Connection.getCancelTimer().schedule(timeoutTask,  this.timeoutInMillis);
  

?

對應(yīng)的CancelTask的代碼:?

?

    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)絡(luò)不通,出現(xiàn)阻塞現(xiàn)象,對應(yīng)的kill命令也發(fā)不出去,所以timeout設(shè)置的超時沒效果。

4.最后

最后還是決定配置testWhileIdle掃描,主要考慮:

  1. pool池中的鏈接如果未被使用,可以通過testWhileIdle進行鏈接檢查,避免在使用時后總要失敗那么一次,可以及時預(yù)防
  2. 配合連接池的minEvictableIdleTimeMillis(空閑鏈接),removeAbandoned(未釋放的鏈接),可以更好的去避免因為一些異常情況引起的問題,防范于未然。比如使用一些分布式數(shù)據(jù)庫的中間件,會有空閑鏈接關(guān)閉的動作,動態(tài)伸縮連接池,這時候需要能及時的發(fā)現(xiàn),避免請求失敗。
  3. testOnBorrow個人不太建議使用,存在性能問題,試想一下連接一般會在什么情況出問題,網(wǎng)絡(luò)或者服務(wù)端異常終端空閑鏈接,網(wǎng)絡(luò)中斷你testOnBorrow檢查發(fā)現(xiàn)不對再取一個鏈接還是不對,針對空閑鏈接處理異常關(guān)閉,可以從好業(yè)務(wù)端的重試策略進行考慮,同時配置客戶端的空閑鏈接超時時間,maxIdle,minIdle等。

?

--------------------------------------------

新加的內(nèi)容:

5.dbcp密碼加密處理

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

?

?

    <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的對應(yīng) SecureIdentityLoginModule 的實現(xiàn),無非就是走了Blowfish加密算法,自己拷貝實現(xiàn)一份。

?

?

    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();
    }
  
?

最后的配置替換為:

?

?

    <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)絡(luò)異常中斷后,原先的建立的tcp 鏈接,應(yīng)該能進行自動切換。比如網(wǎng)站演習(xí)中的交換機重啟會導(dǎo)致網(wǎng)絡(luò)瞬斷

3. 分布式數(shù)據(jù)庫中間件,比如amoeba 會定時的將空閑鏈接異常關(guān)閉,客戶端會出現(xiàn)半開的空閑鏈接。

?

大致的解決思路:?

1. sql 心跳檢查

? 主動式 ,即我前面提到的sql validate相關(guān)配置

2. 請求探雷

??? 犧牲小我,完成大我的精神。 拿鏈接嘗試一下,發(fā)現(xiàn)處理失敗丟棄鏈接,探雷的請求總會失敗幾個,就是前面遇到的問題一,dbcp已經(jīng)支持該功能,不需要額外置。

3. 設(shè)置合理的超時時間,

????? 解決半開鏈接. 一般數(shù)據(jù)庫mysql,oracle都有一定的鏈接空閑斷開的機制,而且當你使用一些分布式中間件(軟件一類的),空閑鏈接控制會更加嚴格,這時候設(shè)置合理的超時時間可以有效 避免半開鏈接。

???? 一般超時時間,dbcp主要是minEvictableIdleTimeMillis(空閑鏈接) , removeAbandonedTimeout(鏈接泄漏)。可以見前面的參數(shù)解釋。

?

?

?

dbcp基本配置和重連配置


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。。?/p>

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产中文字幕在线 | 日本伊人色综合网站 | 色婷婷综合久久久中文字幕 | 这里只有精品在线视频观看 | 人人舔人人爱 | 日本一级特黄a大片在线 | 精品国产91亚洲一区二区三区www | 久久伊人国产 | 亚洲精品免费观看 | 丁香婷婷色综合亚洲小说 | 久久亚洲国产精品 | 久久久久成人精品 | 久久精品视频日本 | 韩国三级中文字幕hd久久精品 | 成人日韩在线 | 理论片午午伦夜理片在线播放 | 欧美一区二区三区免费观看视频 | 亚洲欧美精品 | 免费看成年视频网页 | 男女午夜影院 | www国产视频 | 日韩av资源站 | 国产高清一区二区 | 性生潮久久久不久久久久 | 狠狠影院 | 久久久久亚洲一区二区三区 | a级高清免费 | 久久综合成人 | 亚洲欧美日韩三级 | 久久免费视频在线 | 欧美黄视频| 国产精品国产午夜免费福利看 | 国产精品乱码人人做人人爱 | 波多野结衣精品一区二区三区 | 亚洲精品久久久久一区二区 | 国产精品久久久久久久7电影 | 亚洲激情视频在线观看 | 亚洲经典在线中文字幕 | 一区二区日韩精品 | 成人免费视频观看视频 | 欧美精品一区二区在线观看 |