六月婷婷综合激情-六月婷婷综合-六月婷婷在线观看-六月婷婷在线-亚洲黄色在线网站-亚洲黄色在线观看网站

明輝手游網中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

28條改善 ASP 性能與外觀的技巧(1-7)

[摘要]二十八條改善 ASP 性能和外觀的技巧 Len Cardinal,高級顧問,Microsoft Consulting Services George V. Reilly Microsoft IIS Performance Lead 改編自Nancy Cluts 的文章 開發人員技術工程師Micro...
二十八條改善 ASP 性能和外觀的技巧
Len Cardinal,高級顧問,Microsoft Consulting Services George V. Reilly
Microsoft IIS Performance Lead

改編自Nancy Cluts 的文章 開發人員技術工程師
Microsoft Corporation
2000 年 4 月

摘要:本文介紹優化 ASP 應用程序和 VBScript 的技巧。

目錄
技巧 1:將經常使用的數據緩存在 Web 服務器上
技巧 2:將經常使用的數據緩存在 Application 或 Session 對象中
技巧 3:將數據和 HTML 緩存在 Web 服務器的磁盤上
技巧 4:避免將非敏捷的組件緩存在 Application 或 Session 對象中
技巧 5:不要將數據庫連接緩存在 Application 或 Session 對象中
技巧 6:合理地使用 Session 對象
技巧 7:將代碼封裝在 COM 對象中
引言
性能是一個特征。您必須預先設計性能,否則您以后就得重寫應用程序。就是說,有哪些好的策略可使 Active Server Pages (ASP) 應用程序性能達到最佳?

本文介紹了優化 ASP 應用程序和 Visual Basic? Scripting Edition (VBScript) 的技巧。本文討論了許多陷阱。本文列出的建議已經在 http://www.microsoft.com 和其它站點中進行了測試,效果十分顯著。本文假定您已經對 ASP 開發,包括 VBScript 和/或 JScript、ASP Application、ASP Session 和其它 ASP 固有對象(Request、 Response 和 Server)有了基本了解。

通常,ASP 性能主要取決于 ASP 代碼本身以外的很多因素。我們不在一篇文章中羅列出所有的信息,在本文結尾處我們列出了與性能有關的資源。這些鏈接涵蓋了 ASP 和非 ASP 主題,包括 ActiveX? 數據對象 (ADO)、組件對象模型 (COM)、數據庫和 Internet Information Server (IIS) 配置。這些都是我們喜歡的一些鏈接 - 一定要去看看。

技巧 1:將經常使用的數據緩存在 Web 服務器上
典型的 ASP 頁從后端數據存儲中檢索數據,然后將結果轉換成超文本標記語言 (HTML)。無論數據庫的速度如何,從內存中檢索數據總要比從后端數據存儲中檢索數據快得多。從本地硬盤讀取數據通常也比從數據庫中檢索數據更快。因此,通常可以將數據緩存在 Web 服務器上(存儲在內存或磁盤中),來提高性能。

緩存是傳統的以空間換取時間的做法。如果您緩存的內容正確,那么您可以看到性能會有顯著的提高。為使緩存有效,必須保存那些經常重復使用的數據,且要重新計算這些數據需要(適度)大的開銷。如果緩存的都是些陳舊的數據,就會造成內存浪費。

不經常發生改變的數據是很好的緩存候選數據,因為您不必擔心隨著時間的遷移該數據與數據庫同步的問題。組合框列表、引用表、DHTML 碎片、擴展標記語言 (XML) 字符串、菜單項和站點配置變量(包括數據源名稱 (DSN)、Internet 協議 (IP) 地址和 Web 路徑)都是很好的緩存候選內容。注意您可以緩存數據的“表示”,而不緩存數據本身。如果 ASP 頁很少更改,且緩存的開銷也很大(例如,整個產品目錄),則應考慮事先產生 HTML,而不是在響應每個請求時重新顯示。

應將數據緩存在哪里,有哪些緩存策略?通常,數據緩存在 Web 服務器的內存或磁盤中。下兩個技巧講述了這兩個方法。

技巧 2: 將經常使用的數據緩存在 Application 或 Session 對象中
ASP Application 和 Session 對象為將數據緩存在內存中提供了方便的容器。您可以將數據指派到 Application 和 Session 對象中,這些數據在 HTTP 調用之間保留在內存中。Session 數據是按每個用戶分別存儲的,而 Application 數據則在所有用戶之間共享。

什么時候將數據裝載到 Application 或 Session 中呢?通常,數據是在啟動 Application 或 Session 時裝載。要在 Application 或 Session 啟動過程中裝載數據,應將適當的代碼分別添加到 Application_OnStart () 或 Session_OnStart() 中。這些函數應在 Global.asa 中,如果沒有,則可以添加這些函數。還可以在第一次需要時裝載該數據。為此,在 ASP 頁中添加一些代碼(或編寫一個可重復使用的腳本函數),以檢查數據是否存在,如果不存在,就裝載數據。這是一個傳統的性能技術,稱為“惰性計算” - 在您知道需要某一個值以前不計算該值。例如:

<%
Function GetEmploymentStatusList
Dim d
d = Application(?EmploymentStatusList?)
If d = ?? Then
' FetchEmploymentStatusList function (not shown)
' fetches data from DB, returns an Array
d = FetchEmploymentStatusList()
Application(?EmploymentStatusList?) = d
End If
GetEmploymentStatusList = d
End Function
%>


可以為所需要的每個數據塊編寫類似的函數。

應以什么格式存儲數據?可以存儲任何變體類型,因為所有腳本變量都是變體型。例如,您可以存儲字符串、整數或數組。通常,您將以這些變量類型之一存儲 ADO 記錄集的內容。要從 ADO 記錄集獲取數據,您可以手工將數據復制到 VBScript 變量,一次一個字段。使用一個 ADO 記錄集持久函數 GetRows()、GetString() 或 Save()(ADO 2.5),可加快速度且更容易一些。其詳細情況已超出本文所討論的范圍,但下面給出了一個函數舉例,說明使用 GetRows() 返回記錄集數據的一個數組:

' Get Recordset, return as an Array
Function FetchEmploymentStatusList
Dim rs
Set rs = CreateObject(?ADODB.Recordset?)
rs.Open ?select StatusName, StatusID from EmployeeStatus?, _
?dsn=employees;uid=sa;pwd=;?
FetchEmploymentStatusList = rs.GetRows() ? Return data as an Array
rs.Close
Set rs = Nothing
End Function


對上面舉例做更進一步改進,可以將 HTML 緩存為列表,而不是數組。下面是簡單的示例:

' Get Recordset, return as HTML Option list
Function FetchEmploymentStatusList
Dim rs, fldName, s
Set rs = CreateObject(?ADODB.Recordset?)
rs.Open ?select StatusName, StatusID from EmployeeStatus?, _
?dsn=employees;uid=sa;pwd=;?
s = ?<select name=??EmploymentStatus??>? & vbCrLf
Set fldName = rs.Fields(?StatusName?) ' ADO Field Binding
Do Until rs.EOF
' Next line violates Don't Do String Concats,
' but it's OK because we are building a cache
s = s & ? <option>? & fldName & ?</option>? & vbCrLf
rs.MoveNext
Loop
s = s & ?</select>? & vbCrLf
rs.Close
Set rs = Nothing ' See Release Early
FetchEmploymentStatusList = s ' Return data as a String
End Function


在適當的條件下,可以將 ADO 記錄集本身緩存在 Application 或 Session 作用域中。有兩個警告:

必須將 ADO 標記為自由線程
必須使用斷開連接的記錄集。
如果不能保證滿足這兩個要求,則不要緩存 ADO 記錄集。在下面的“非敏捷組件”和“不要緩存連接”技巧中,我們將討論將 COM 對象存儲在 Application 或 Session 作用域中的危險性。

當您將數據存儲在 Application 或 Session 作用域時,數據將保留在那里,直到您以編程方式改變它、Session 過期或 Web 應用程序重新啟動為止。如果數據需要更新怎么辦?要手工強制對 Application 數據進行更新,您可以訪問只有管理員才可訪問的 ASP 頁來更新數據。或者,您可以通過函數定期自動刷新數據。下面例子存儲帶有緩存數據的時間戳,并隔一段時間后刷新數據。

<%
' error handing not shown...
Const UPDATE_INTERVAL = 300 ' Refresh interval, in seconds

' Function to return the employment status list
Function GetEmploymentStatusList
UpdateEmploymentStatus
GetEmploymentStatusList = Application(?EmploymentStatusList?)
End Function

' Periodically update the cached data
Sub UpdateEmploymentStatusList
Dim d, strLastUpdate
strLastUpdate = Application(?LastUpdate?)
If (strLastUpdate = ??) Or _
(UPDATE_INTERVAL < DateDiff(?s?, strLastUpdate, Now)) Then

' Note: two or more calls might get in here. This is okay and will simply
' result in a few unnecessary fetches (there is a workaround for this)

' FetchEmploymentStatusList function (not shown)
' fetches data from DB, returns an Array
d = FetchEmploymentStatusList()

' Update the Application object. Use Application.Lock()
' to ensure consistent data
Application.Lock
Application(?EmploymentStatusList?) = Events
Application(?LastUpdate?) = CStr(Now)
Application.Unlock
End If
End Sub


請參見 World's Fastest ListBox with Application Data,上面還有一個例子。

要知道在 Session 或 Application 對象中緩存大的數組不是一個好的做法。在訪問數組的任何元素之前,腳本語言的語法要求必須臨時復制整個數組。例如,如果將由字符串組成的有 100,000 個元素的數組(該數組將美國郵政編碼映射到當地的氣象站)緩存在 Application 對象中,ASP 必須先將所有的 100,000 個氣象站復制到臨時數組中,然后才能提取一個字符串。在這種情況下,用自定義方法建立一個自定義組件來存儲氣象站 - 或使用一個詞典組件會更好。

再警告大家一下,不要將嬰兒與洗澡水一起倒掉:數組能快速查尋和存儲在內存中是鄰近的關鍵數據對。索引一個詞典比索引一個數組要慢得多。應針對您的實際情況,選擇提供最佳性能的數據結構。

技巧 3:將數據和 HTML 緩存在 Web 服務器的磁盤上
有時,數據可能太多,無法都緩存在內存中。“太多”只是一個說法,這要看您想消耗多少內存,以及需緩存的項目數和檢索這些項目的頻率。在任何情況下,如果數據太多而無法都緩存在內存中,則考慮將數據以文本或 XML 文件緩存在 Web 服務器的硬盤上。可以同時將數據緩存在磁盤和內存中,為您的站點建立最適宜的緩存策略。

注意當測量單個 ASP 頁的性能時,檢索磁盤上的數據可能不一定要比從數據庫檢索數據更快。但緩存會降低數據庫和網絡上的負載。在高負載的情況下,這樣做可大大改善總體吞吐量。當緩存開銷很大的查詢結果(如多表聯接或復合存儲過程)或大的結果集時,這是非常有效的。與往常一樣,要測試一下幾種方案的優劣。

ASP 和 COM 提供一些建立基于磁盤的緩存方案的工具。ADO 記錄集 Save() 和 Open() 函數保存和裝載磁盤中的記錄集。可以使用這些方法重新編寫上面 Application 數據緩存技巧中的代碼示例,用文件的 Save() 代替寫到 Application 對象中的代碼。

有一些其它組件可以用于文件:

Scripting.FileSystemObject 可使您創建、讀和寫文件。
與 Internet Explorer 一起提供的 Microsoft? XML 解析器 (MSXML) 支持保存和裝載 XML 文檔。
LookupTable 對象(例如,用在 MSN 上)是從磁盤裝載簡單列表的最好選擇。
最后,應考慮將數據的表示緩存在磁盤上,而不是數據本身。預先轉換的 HTML 可以用 .htm 或 .asp 文件存儲在磁盤上,超級鏈接可以直接指向這些文件。可以使用商用工具,如 XBuilder,或 Microsoft? SQL Server? Internet 發布功能將產生 HTML 的過程自動化。或者,您可以將 HTML 代碼片斷放在 .asp 文件中。還可以使用 FileSystemObject 從磁盤讀取 HTML 文件,或使用 XML 盡早轉換。

技巧 4:避免將非敏捷的組件緩存在 Application 或 Session 對象中
盡管將數據緩存在 Application 或 Session 對象中是一個好的做法,但緩存 COM 對象卻有嚴重的陷阱。通常,人們傾向于將經常使用的 COM 對象緩存到 Application 或 Session 對象中。很遺憾,許多 COM 對象(包括所有以 Visual Basic 6.0 或更低版本編寫的對象)當存儲在 Application 或 Session 對象時,會引起嚴重的瓶頸。

具體來講,當任何不敏捷的組件緩存在 Session 或 Application 對象時,將引起性能瓶頸。敏捷的組件是被標記為 ThreadingModel=Both 的組件,它聚集 Free-threaded marshaler (FTM);或被標記為 ThreadingModel=Neutral 的組件。(Neutral 模型是 Windows? 2000 和 COM+ 的新增模型。) 下列組件不是敏捷的:

自由線程的組件(除非它們聚集 FTM)。
單元線程組件。
單線程組件。
配置的組件(Microsoft Transaction Server (MTS)/COM+ 庫和服務器程序包/應用程序)不是敏捷的,除非它們是 Neutral 線程。單元線程組件和其它非敏捷的組件在頁作用域內是最適合的(即,它們在單個 ASP 頁上創建和銷毀)。

在 IIS 4.0 中,被標記為 ThreadingModel=Both 的組件被認為是敏捷的。在 IIS 5.0 中,只有這一點還不夠。組件必須不僅被標記 Both,還必須聚集 FTM。有關敏捷性的文章講述了如何使以 Active Template Library 編寫的 C++ 組件聚集 FTM。要注意如果組件緩存界面指針,那么那些指針本身必須是敏捷的,或必須存儲在 COM 共用界面表 (GIT) 中。如果您不能重新編譯 Both 線程組件以聚集 FTM,那么您可以將組件標記為 ThreadingModel=Neutral。或者,如果您不想讓 IIS 執行敏捷性檢查(因此,您可以允許非敏捷的組件存儲在 Application 或 Session 作用域中),您可以在配置數據庫中將 AspTrackThreadingModel 設置為 True。不建議更改 AspTrackThreadingModel。

如果您想將以 Server.CreateObject 創建的非敏捷的組件存儲在 Application 對象中,IIS 5.0 將出現一個錯誤。您可以在 Global.asa 中使用 <object runat=server scope=application ...> 避免這一錯誤,但不建議這樣做,因為這會導致匯集和串行化,關于這一點將在下面講述。

如果您緩存非敏捷的組件會出現什么毛病?緩存在 Session 對象中的非敏捷的組件將 Session 鎖定于 ASP 工作者線程。ASP 維護一個工作者線程池來處理請求。通常情況下,一個新請求總是由第一個可用的工作者線程來處理。如果 Session 被鎖定于一個線程,那么請求必須等到其相關的線程可用為止。這里有一個類比,也許會有所幫助:您去一家超級市場,挑選了一些商品,并在 #_3 收款臺付款。其后,每當您在那家超級市場為商品付款時,您總是必須在 #_3 收款臺付款,即使其它收款臺前排隊的人較少或者沒有人排隊,也是如此。

將非敏捷的組件存儲在 Application 作用域對性能的影響甚至更壞。ASP 必須創建一個特殊的線程運行存儲在 Application 作用域中的非敏捷組件。這會有兩個結果:所有調用都必須匯集到此線程,且所有調用都排成長隊。“匯集”的意思是參數必須存儲在內存的共享區域;執行一個開銷很大的到特殊線程的上下文切換;執行組件的方法;將結果匯集到共享區域;執行另一個開銷很大的上下文切換,將控制返回到原始的線程。“串行化”意思是指每次只運行一個方法。兩個不同的 ASP 工作者線程不能同時在共享組件上執行多個方法。這樣就杜絕了并發性,特別是在多處理器計算機上。更糟的是,所有非敏捷的 Application 作用域的組件共享一個線程(主機 STA),因此串行化的影響甚至更顯著。

如之奈何?下面是一些一般的規則。如果您使用 Visual Basic (6.0) 或更早版本編寫對象,那么不要將它們緩存在 Application 或 Session 對象中。如果您不知道對象的線程模型,不要緩存它。不要緩存非敏捷的對象,而應在每個頁面創建和釋放它們。對象直接在 ASP 工作者線程上運行,因此沒有匯集或串行化。如果 COM 對象在 IIS 服務器上運行,且如果它們不花長時間初始化和刪除,性能尚可。注意單線程對象不應該這樣使用。小心 - VB 可創建單線程對象!如果您必須這樣使用單線程對象(如 Microsoft Excel 電子表格),別指望會有很高的吞吐量。

當 ADO 被標記為自由線程,ADO 記錄集可以安全地緩存。要將 ADO 標記為自由線程,使用 Makfre15.bat 文件,該文件通常位于目錄 \\Program Files\Common\System\ADO 中。

警告 如果您使用 Microsoft Access 作為數據庫,不應將 ADO 標記為自由線程的。ADO 記錄集也必須切斷連接。一般來說,如果您不能控制站點中的 ADO 配置(例如,您是一個獨立的軟件廠商 [ISV],向管理他們自己的配置客戶銷售 Web 應用程序),最好不要緩存記錄集。

詞典組件也是敏捷的對象。LookupTable 從數據文件中裝載其數據,可用于組合框數據和配置信息。Duwamish Books 中的 PageCache 對象可提供詞典語法,Caprock Dictionary 也可提供。這些對象或其派生對象可以構成有效緩存策略的基礎。注意 Scripting.Dictionary 對象不是敏捷的,不應該存儲在 Application 或 Session 作用域中。

技巧 5:不要將數據庫連接緩存在 Application 或 Session 對象中
緩存 ADO 連接通常是很糟糕的策略。如果一個 Connection 對象存儲在 Application 對象中,并在所有的頁面中使用,那么所有頁面將爭搶這一連接。如果 Connection 對象存儲在 ASP Session 對象中,那么將為每個用戶創建數據庫連接。這就會使連接池的優勢蕩然無存,并給 Web 服務器和數據庫帶來不必要的壓力。

可以不緩存數據庫連接,而是在使用 ADO 的每個 ASP 頁面中創建和刪除 ADO 對象。這是很有效的,因為 IIS 內嵌了數據庫連接池。更準確地說,IIS 自動啟用 OLEDB 和 ODBC 連接池。這就能確保在每個頁面上創建和刪除連接將是有效的。

因為連接的記錄集存儲一個到數據庫連接的引用,所以您不應將連接的記錄集緩存在 Application 或 Session 對象中。但是,您可以安全地緩存斷開連接的記錄集,它們不保存到其數據連接的引用。要斷開記錄集連接,執行下面的兩個步驟:

Set rs = Server.CreateObject(?ADODB.RecordSet?)
rs.CursorLocation = adUseClient ' step 1

' Populate the recordset with data
rs.Open strQuery, strProv

' Now disconnect the recordset from the data provider and data source
rs.ActiveConnection = Nothing ' step 2


有關連接池的更詳細信息,可以在 ADO 和 SQL Server 參考資料中找到。

技巧 6:合理地使用 Session 對象
既然我們已經討論了緩存在 Application 和 Session 中的優點,現在開始討論避免使用 Session 對象的問題。正如下面所討論的,當與忙的站點一起使用時,Session 有幾個缺點。“忙”的意思一般是指一秒鐘要求幾百頁面或成千上萬同時用戶的站點。這個技巧對于必須水平擴展的站點 - 即,那些利用多臺服務器以處理負載或實現容錯的站點 - 甚至更重要。對于較小的站點,諸如 Intranet 站點,要想實現 Session 帶來的方,必然增大系統開銷。

簡言之,ASP 自動為每個訪問 Web 服務器的用戶創建一個 Session。每個 Session 大約需要 10 KB 的內存開銷(最主要的是數據存儲在 Session 中),這就使所有的請求都減慢。在配置的超時時段(通常是 20 分鐘)結束以前,Session 一直保留有效。

Session 的最大的問題不是性能,而是可擴展性。Session 不能跨越幾臺 Web 服務器,一旦在一臺服務器上創建 Session,其數據就留在那兒。這就意味著如果您在一個 Web 服務器群使用 Session,您必須設計一個策略,將每個用戶請求始終發到用戶 Session 所在的那臺服務器上。這被稱為將用戶“粘”在 Web 服務器上。術語“粘性會話”就是從這里派生而來的。如果 Web 服務器崩潰,被“粘住的”用戶將丟失他們的會話狀態,因為會話不是粘到磁盤上。

實現粘性會話的策略包括硬件和軟件解決方案。諸如 Windows 2000 Advanced Server 中的網絡負載平衡和 Cisco 的 Local Director 之類的解決方案都可以實現粘性會話,代價是要損失一定程度的可擴展性。這些解決方案是不完善的。不建議此時部署您自己的軟件解決方案(我們過去常常使用 ISAPI 篩選器和 URL 轉換等等)。

Application 對象也不跨越多臺服務器,如果您必須跨越 Web 服務器群共享和更新 Application 數據,您必須使用后端數據庫。但是,只讀 Application 數據在 Web 服務器群中仍是有用的。

如果只是因為要增加運行時間(處理故障轉移和服務器維護),大多數關鍵任務站點至少需部署兩臺 Web 服務器。因此,在設計關鍵任務應用程序時,必須實現“粘性會話”,或干脆避免使用 Session,以及任何其它將用戶狀態存儲在單個 Web 服務器上的狀態管理技術。

如果您不使用 Session,一定要將它們關閉。您可以通過 Internet Services Manager,為應用程序執行此操作(參見 ISM 文檔)。如果您決定使用 Session,您可以采用一些方法減輕它們對性能的影響。

您可以將不需要 Session 的內容(如幫助屏幕,訪問者區域等等)移到另一個關閉了 Session 的 ASP 應用程序中。您可以逐頁提示 ASP,您不再需要該頁面上的 Session 對象,使用以下放在 ASP 頁面最上面的指令:

<% @EnableSessionState=False %>


使用這一指令有一個很好的理由是,這些 Session 在框架集方面存在一個有意思的問題。ASP 保證任何時候 Session 只有一個請求執行。這樣就確保如果瀏覽器為一個用戶請求多個頁面,一次只有一個 ASP 請求接觸 Session,這樣就避免了當訪問 Session 對象時發生的多線程問題。很遺憾,一個框架集中的所有頁面將以串行方式顯示,一個接一個,而不是同時顯示。用戶可能必須等候很長時間,才能看到所有的框架。該故事的寓意:如果某些框架集頁面不依靠 Session,一定要使用 @EnableSessionState=False 指令告訴 ASP。

有許多管理 Session 狀態的方法,可替代 Session 對象的使用。對于少量的狀態(少于 4 KB),我們通常建議使用 Cookies、QueryString 變量和隱式變量。對于更大數據量,如購物小車,后端數據庫是最適合的選擇。有關 Web 服務器群中狀態管理技術的文章很多。有關詳細信息,請參見 Session 狀態參考資料。

技巧 7: 將代碼封裝在 COM 對象中
如果您有許多 VBScript 或 JScript,您可以經常將代碼移到編譯的 COM 對象中,從而可改善性能。編譯的代碼通常比解釋的代碼運行得更快。編譯的 COM 對象可以通過“早綁定”訪問其它 COM 對象,與腳本使用的“晚綁定”相比,“早綁定”是調用 COM 對象的更有效方法。

將代碼封裝在 COM 對象中還有一些優點(除性能之外):

COM 對象有利于將表示邏輯與業務邏輯分開。
COM 對象可以保證代碼重復使用。
許多開發人員發現以 VB、C++ 或 Visual J++ 編寫的代碼比 ASP 更容易調試。
COM 對象也有缺點,包括初始開發時間和需要不同的程序設計技巧。注意封裝少量的 ASP 可能引起性能下降,而不會得到性能改進。這種情況通常在少量的 ASP 代碼被封裝進 COM 對象時發生。在這種情況下,創建和調用 COM 對象的系統開銷超過了編譯的代碼的優點。應反復地試驗,以確定什么樣的 ASP 腳本和 COM 對象代碼的組合產生最好的性能。注意,與 Microsoft Windows NT? 4.0/IIS 4.0 相比,Windows 2000/IIS 5.0 中在腳本和 ADO 性能方面有了很大的改進。因此,隨著 IIS 5.0 的推出,編譯代碼比 ASP 代碼的性能優勢有所降低。

有關在 ASP 中使用 COM 的優點和缺點的詳細討論,參見 ASP Component Guidelines and Programming Distributed Applications with and Microsoft Visual Basic 6.0。如果您部署 COM 組件,以負荷對它們進行測試特別重要。事實上,理所當然應對所有的 ASP 應用程序進行負荷測試。  





主站蜘蛛池模板: 亚洲视频一区在线观看 | 日本在线观看一区二区三区 | 一级做a爰性色毛片免费 | 三级黄色片在线免费观看 | 日本三级香港三级人妇99 | 色精品一区二区三区 | 酥酥影院一级毛片在线看 | 一个色综合网站 | 日韩国产欧美在线观看 | 日韩一区二区在线观看 | 在线视频国产一区 | 亚洲天堂男人网 | 一级做a爰片 | 午夜影视在线观看免费完整高清大全 | 日本高清色本在线www游戏 | 综合色在线观看 | 亚洲国产精品欧美日韩一区二区 | 五月婷婷六月丁香 | 日日摸日日添夜夜爽97 | 欧美在线观看第一页 | 人人婷婷色综合五月第四人色阁 | 亚洲视频在线免费 | 欧美一级淫片aaaaaaa视频 | 亚洲欧美一级视频 | 色狠狠色狠狠综合天天 | 人人精品久久 | 速度与激情9免费完整版高清 | 永久免费毛片 | 日本高清一本视频 | 伊香蕉大综综综合久久 | 中文字幕一二三四 | 欧美资源在线观看 | 呦呦国产| 亚洲网址在线 | 亚洲日本在线观看网址 | 午夜无遮挡怕怕怕免费视频 | 一级免费a | 奇米久久| 中文字幕乱偷乱码亚洲 | 中文字幕亚洲综久久2021 | 午夜影院黄色片 |