• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-4  評論-40  文章-117  trackbacks-0



            摘要:在對I/O 完成端口進行底層封裝的基礎(chǔ)上,提出一種具有高性能的、可擴展性的通用網(wǎng)絡(luò)通信模塊設(shè)計方案。該方案采用多種系
            統(tǒng)性能優(yōu)化技術(shù),如線程池、對象池和環(huán)形緩存區(qū)等。該模塊在Win32 平臺上用C++開發(fā)完成,經(jīng)過嚴格的壓力和性能測試后,實驗結(jié)果
            表明該模塊能夠支持海量并發(fā)連接,具有較高的數(shù)據(jù)吞吐量,在實際項目應(yīng)用中也取得了良好的表現(xiàn)。
            關(guān)鍵詞:完成端口;服務(wù)器;多線程;線程池;對象池;緩存區(qū)
            Design Method of Underlying Module of Network Communication
            for High Performance Server
            WANGWen-wu1,2, ZHAOWei-dong1,2,WANG Zhi-cheng1,2, CHEN Yue1,2, HAN Xia-lin1,2
            (1. State Education Commission Engineering Center for Enterprise Digital Technology, Shanghai 200092;
            2. Research Center of CAD, Tongji University, Shanghai 201804)
            【Abstract】On the base of underlying encapsulation for I/O Completion Port(IOCP), this paper presents a design solution with high performance
            and scalable module of generic network communication, which emploies a variety of optimization techniques of system performance, such as thread
            pool, object pool and ring buffer. The module is developed in C++ programming language on Win32 platform. Experimental results show that the
            module can support massive concurrent connections, and has higher data throughput based on severe pressure and performance tests. The proposed
            solution has also got a good performance in the actual project application.
            【Key words】completion port; server; multi-threading; thread pool; object pool; ring buffer

            計算機工程

            Computer Engineering

            第35 卷第3 期
            Vol.35 No.3
            2009 年2 月
            February 2009

            1 概述
            要設(shè)計與開發(fā)出一款高性能的服務(wù)器(如網(wǎng)游服務(wù)器、
            Web 服務(wù)器和代理服務(wù)器等),一般都采用高效率的網(wǎng)絡(luò)I/O
            模型[1]。Linux 平臺上經(jīng)常會采用epoll 模型,而在Win32 平
            臺上完成端口(以下簡稱IOCP)模型[2]是設(shè)計與開發(fā)高性能
            的、具有可伸縮性的服務(wù)器的最佳選擇,它可以支持海量并
            發(fā)客戶端請求。多線程編程是服務(wù)器端開發(fā)常用技術(shù),多線
            程必然涉及線程間的通信與同步。如果使用不當,也會影響
            到系統(tǒng)的性能,必須謹慎設(shè)計才能保證系統(tǒng)良好運行。減少
            數(shù)據(jù)拷貝以及小對象頻繁創(chuàng)建與銷毀是一種很重要的提高系
            統(tǒng)性能手段,可通過設(shè)計內(nèi)存池或?qū)ο蟪丶右越鉀Q。這幾個
            問題的提出,說明實際的高性能服務(wù)器研發(fā)比較復(fù)雜,尤其
            是采用高效I/O 模型來架構(gòu)服務(wù)器時,更是增加了開發(fā)的難
            度,原因是這些模型的機制比較復(fù)雜。
            底層網(wǎng)絡(luò)通信模塊是服務(wù)器應(yīng)用程序的核心模塊,也是
            高性能服務(wù)器的最基礎(chǔ)模塊之一。它主要的功能是接收海量
            并發(fā)連接、接收網(wǎng)絡(luò)數(shù)據(jù)包、暫存和發(fā)送應(yīng)用邏輯層的邏輯
            數(shù)據(jù)包,所以,它也是上次應(yīng)用邏輯和底層網(wǎng)絡(luò)之間通信的
            媒介。
            2 IOCP 機制
            要實現(xiàn)一個并發(fā)的網(wǎng)絡(luò)服務(wù)器,比較簡單的模型是:每
            當一個請求到達就創(chuàng)建一個新線程,然后在新線程中為請求
            服務(wù)。這種模型減輕了實際開發(fā)的復(fù)雜度,在并發(fā)連接較少
            的情況下可以考慮使用,然而在高并發(fā)需求下并不適用。高
            并發(fā)環(huán)境中,創(chuàng)建和銷毀大量線程所花費的時間和消耗的系
            統(tǒng)資源是巨大的,而且會加重線程調(diào)度的負擔(dān),同時線程上
            下文切換(context switch)也會浪費許多寶貴的CPU 時間。
            為了提高系統(tǒng)性能,首先必須有足夠的可運行線程來充
            分利用CPU 資源,但線程的數(shù)量不能太多。事實上,具體工
            作線程的數(shù)量和并發(fā)連接數(shù)量不是直接相關(guān)聯(lián)的。在Win32
            平臺下開發(fā)高效的服務(wù)器端應(yīng)用程序,最理想的模型是IOCP
            模型,該模型解決了一系列系統(tǒng)性能瓶頸問題。
            IOCP 提供了最好的可伸縮性,而且其執(zhí)行效率比較高,
            采用這種網(wǎng)絡(luò)模型可能會加大開發(fā)的復(fù)雜度, 但卻是
            Windows 平臺上唯一適用于開發(fā)高負載服務(wù)器的技術(shù)。
            IOCPWindows 系統(tǒng)的一種內(nèi)核對象[3],也是Win32 下最復(fù)雜
            的一種I/O 模型,它通過一定數(shù)量的工作線程對重疊I/O 請
            求進行處理,以便為已經(jīng)完成的I/O 請求提供服務(wù),相對其
            他I/O 模型,它可以管理任意數(shù)量套接字句柄。它主要由等
            待線程隊列和I/O 完成隊列2 個部分組成。一個完成端口對
            象可以和多個套接字句柄相關(guān)聯(lián),當針對某個套接字句柄發(fā)
            起的異步I/O 操作完成時,系統(tǒng)向該完成端口的I/O 完成隊
            列加入一個I/O 完成包。于此同時, 工作線程調(diào)用
            GetQueuedCompletionStatus(以下簡稱GQCS)時,如果I/O 完
            基金項目:廣東省教育部產(chǎn)學(xué)研結(jié)合基金資助項目“基于RFID 技
            術(shù)石化產(chǎn)品計量監(jiān)控管理系統(tǒng)應(yīng)用研究與開發(fā)”(2007A090302094)
            作者簡介:王文武(1983-),男,碩士研究生,主研方向:CAD,
            企業(yè)信息化;趙衛(wèi)東,研究員、博士生導(dǎo)師;王志成,博士;陳悅、
            韓下林,碩士研究生
            收稿日期:2008-11-30 E-mail:jerry.wenwu@gmail.com
            —104—
            成隊列中有完成包,當前調(diào)用就會返回,取得數(shù)據(jù)進行后續(xù)
            的處理。
            成功創(chuàng)建一個完成端口后,便可開始將套接字句柄與對
            象關(guān)聯(lián)到一起。但在關(guān)聯(lián)套接字之前,首先必須創(chuàng)建一個或
            多個工作者線程為完成端口提供服務(wù)。
            3 模塊設(shè)計方案
            3.1 架構(gòu)設(shè)計
            在充分考慮服務(wù)器性能和擴展性的基礎(chǔ)上,本文提出了
            基于三層結(jié)構(gòu)的系統(tǒng)設(shè)計方案,該模塊的架構(gòu)如圖1 所示。
            #OnConnectionEstablished() : void
            #OnReadCompleted() : void
            #OnWriteCompleted() : void
            CIocpServer
            #HandleRecvMessage() : void
            CTestServer
            #OnConnectionEstablished() : void
            #OnReadCompleted() : void
            #OnWriteCompleted() : void
            #HandleRecvMessage() : void
            CUserServer
            圖1 模塊設(shè)計架構(gòu)
            圖1 看上去并不復(fù)雜,但卻是一個兼顧可擴展性和高性
            能的架構(gòu),在實際項目應(yīng)用中也取得了很好的表現(xiàn),下面是
            對圖1 主要類的功能分析。
            CIocpServer 類是完成端口服務(wù)器基本通信類,它使用
            Windows 平臺特有的IOCP 機制,對網(wǎng)絡(luò)通信模型進行底層
            封裝。提供了基本的服務(wù)器端網(wǎng)絡(luò)通信功能,這些功能主要
            有開啟服務(wù)器、關(guān)閉服務(wù)器、管理客戶端連接列表、管理未
            決的接受請求列表、發(fā)出異步操作等。同時通過多態(tài)機制向
            它的派生類提供以下基本擴展接口:
            (1)新連接確立的處理接口。
            (2)客戶端斷開連接時的處理接口。
            (3)連接出現(xiàn)錯誤時的處理接口。
            (4)從客戶端接收完數(shù)據(jù)后的處理接口。
            (5)向客戶端發(fā)送完數(shù)據(jù)后的處理接口。
            (6)拼包處理接口。
            CUserServer 類繼承CIocpServer,在CIocpServer 的基礎(chǔ)
            上,CUserServer 加入了一些服務(wù)器邏輯處理功能,并且封裝
            了3 類數(shù)據(jù)隊列和3 類處理線程,分別如下:
            (1)接收數(shù)據(jù)包隊列及接收線程:接收隊列用于存放接收
            到的數(shù)據(jù)包,此數(shù)據(jù)包還沒有進行邏輯意義上的拼包,接收
            線程從此隊列中取出數(shù)據(jù)包,并將其拼裝成邏輯意義上完整
            的數(shù)據(jù)包加入到邏輯數(shù)據(jù)包隊列中。
            (2)邏輯數(shù)據(jù)包隊列及邏輯處理線程:邏輯隊列用于存放
            已經(jīng)拼包成了邏輯意義上的數(shù)據(jù)包,邏輯處理線程對此類數(shù)
            據(jù)包進行邏輯解析,這里就是服務(wù)器的主要邏輯部分,有的
            數(shù)據(jù)包在處理完成后,可能是需要向客戶端返回處理結(jié)果,
            此時就需要邏輯線程將處理完成的數(shù)據(jù)包放入發(fā)送數(shù)據(jù)包隊
            列中。
            (3)發(fā)送數(shù)據(jù)包隊列及發(fā)送線程:發(fā)送隊列存放待發(fā)送的
            數(shù)據(jù)包,發(fā)送線程根據(jù)數(shù)據(jù)包里的客戶端套接字發(fā)送給特定
            客戶端。
            CTestServer 類是一個測試類, 主要用于演示如何在
            CUserServer 的基礎(chǔ)上派生一個真正的應(yīng)用服務(wù)器,并用于說
            明它需要重載實現(xiàn)CUserServer 的哪些重要虛函數(shù)。
            3.2 資源管理
            用IOCP 開發(fā)服務(wù)器時,當I/O 發(fā)生錯誤時需要有效地
            釋放與套接字相關(guān)的緩存區(qū),如果對同一緩存區(qū)釋放多次,
            就會導(dǎo)致內(nèi)存釋放的錯誤。當投遞的異步I/O 請求返回了非
            WSA_IO_PENDING 錯誤時,要對此錯誤進行處理,通常執(zhí)
            行2 步操作:釋放此次操作使用的緩沖區(qū)數(shù)據(jù);關(guān)閉當前操
            作所使用的套接字句柄。同時GQCS 調(diào)用會返回FALSE,也
            要做上面2 步相同的操作,這樣就可能產(chǎn)生對同一緩存區(qū)進
            行重復(fù)釋放的錯誤。解決的辦法可以有2 種:
            (1)通過引用計數(shù)機制控制緩存區(qū)釋放;
            (2)使緩存區(qū)釋放操作線性化。
            該系統(tǒng)的設(shè)計采用了第(2)種解決方案,所謂的釋放操作
            線性化是指把可能引起2 次釋放同一緩存區(qū)的操作合并為一
            次釋放。如果在執(zhí)行異步I/O 操作過程中發(fā)生了非WSA_ IO_
            PENDING 錯誤,可以讓GQCS 返回時得知這個錯誤和發(fā)生
            錯誤時的緩存區(qū)指針,而不對該錯誤進行處理。通知的方式
            是,使用PostQueuedCompletionStatus(以下簡稱Post)函數(shù)拋
            出一個特殊標志的消息,這個特殊標志可以通過GQCS 函數(shù)
            的第2 個參數(shù),即傳送字節(jié)數(shù)來表示,可以選擇任何一個不
            可能出現(xiàn)的值,比如一個負數(shù)。當然,如果通過單句柄數(shù)據(jù)
            或單I/O 數(shù)據(jù)來傳遞也是可以的。而發(fā)生錯誤時的緩沖區(qū)指
            針,必須要通過單句柄數(shù)據(jù)或單I/O 數(shù)據(jù)來傳遞。
            把釋放操作全放在GQCS 函數(shù)里以后,對釋放操作的處
            理就比較統(tǒng)一了。當然,為了實現(xiàn)真正的線性化和原子化,
            在釋放操作的執(zhí)行邏輯上需要對釋放代碼加鎖以實現(xiàn)線程互
            斥(多線程情況下)。
            3.3 包的亂序解決方案
            如果在同一個套接字上一次提交多個異步I/O 請求,肯
            定會按照它們提交的次序完成,但在多線程環(huán)境下,完成包
            處理次序可能和提交次序不一致。該問題的一個簡單的解決
            方法是一次只投遞一個異步I/O 請求,當工作線程處理完該
            請求的完成數(shù)據(jù)包后,再投遞下一個異步I/O 請求。但這樣
            做會降低服務(wù)器的處理性能。為了保證完成包處理次序和提
            交次序相一致,可以為每個連接上投遞的請求都分配一個序
            號,單句柄數(shù)據(jù)中記錄當前需要讀取的單I/O 數(shù)據(jù)的序號,
            如果工作線程獲得的單I/O 數(shù)據(jù)的序號與單句柄數(shù)據(jù)中記錄
            的序號一致的話,就處理該數(shù)據(jù)。如果不相等,則把這個單
            I/O 數(shù)據(jù)保存到該連接的pOutOfOrderReads 列表中。
            4 性能優(yōu)化
            在網(wǎng)絡(luò)服務(wù)器的開發(fā)過程中,池(Pool)技術(shù)已經(jīng)被廣泛應(yīng)
            用。使用池技術(shù)在一定層度上可以明顯優(yōu)化服務(wù)器應(yīng)用程序
            的性能,提高程序執(zhí)行效率和降低系統(tǒng)資源開銷。這里所說
            的池是一種廣義上的池,比如數(shù)據(jù)庫連接池、線程池、內(nèi)存
            池、對象池等。其中,對象池可以看成保存對象的容器,在
            進程初始化時創(chuàng)建一定數(shù)量的對象,需要時直接從池中取出
            一個空閑對象,用完后并不直接釋放掉對象,而是再放到對
            象池中以方便下一次對象請求可以直接復(fù)用。其他幾種池的
            設(shè)計思想也是如此,池技術(shù)的優(yōu)勢是,可以消除對象創(chuàng)建所
            —105—
            帶來的延遲,從而提高系統(tǒng)的性能。
            4.1 線程池
            線程池[4]是提高服務(wù)器程序性能的一種很好技術(shù),在
            Win32 平臺下開發(fā)的網(wǎng)絡(luò)服務(wù)器程序使用的線程池可分為兩
            類:一類是由完成端口對象負責(zé)維護的工作線程池,主要負
            責(zé)網(wǎng)絡(luò)層相關(guān)處理(比如投遞異步讀或?qū)懖僮鞯?;另一類是
            負責(zé)邏輯處理的線程池,它是專門提供給應(yīng)用層來使用的。
            本文提出了一種邏輯線程池的設(shè)計方案,線程池框架結(jié)構(gòu)主
            要分為以下幾個部分:
            (1)線程池管理器:用于創(chuàng)建并管理線程,往任務(wù)隊列添
            加數(shù)據(jù)包等,并可以動態(tài)增加工作線程。
            (2)工作線程:線程池中的線程,執(zhí)行實際的邏輯處理。
            (3)任務(wù)接口:每個任務(wù)必須實現(xiàn)的接口,以供工作線程
            調(diào)度任務(wù)使用。
            (4)任務(wù)隊列:提供一種緩存機制,用于存放從網(wǎng)絡(luò)層接
            收的數(shù)據(jù)包。
            該通信模塊使用了上述線程池的設(shè)計方案,從測試結(jié)果
            來看,當并發(fā)連接數(shù)很大時,線程池對服務(wù)器的性能改善是
            顯著的。
            該設(shè)計方案有個很好的特性,就是可以創(chuàng)建工作線程數(shù)
            量固定的線程池,也可以創(chuàng)建動態(tài)線程池。如果有大量的客
            戶要求服務(wù)器為其服務(wù),但由于線程池的工作線程是有限的
            話,服務(wù)器只能為部分客戶端服務(wù),客戶端提交的任務(wù)只能
            在任務(wù)隊列中等待處理。動態(tài)改變的工作線程數(shù)目的線程池,
            可以以適應(yīng)突發(fā)性的請求。一旦請求變少了將逐步減少線程
            池中工作線程的數(shù)目。當然線程增加可以采用一種超前方式,
            即批量增加一批工作線程,而不是來一個請求才建立創(chuàng)建一
            個線程。批量創(chuàng)建是更加有效的方式,而且該方案還限制了
            線程池中工作線程數(shù)目的上限和下限,確保線程池技術(shù)能提
            高系統(tǒng)整體性能。
            4.2 對象池
            對象池[5-6]是針對特定應(yīng)用程序而設(shè)計的內(nèi)存管理方式,
            在某種場合下內(nèi)存的分配和釋放性能會大大提升。默認的內(nèi)
            存管理函數(shù)(new/delete 或malloc/free)有其不足之處,如果應(yīng)
            用程序頻繁地在堆上分配和釋放內(nèi)存,那么就會導(dǎo)致性能損
            失,并且會使系統(tǒng)中出現(xiàn)大量的內(nèi)存碎片,降低內(nèi)存的利
            用率。
            所謂對象池就是應(yīng)用程序可以通過系統(tǒng)的內(nèi)存分配調(diào)用
            預(yù)先一次性申請適當大小的內(nèi)存塊,然后可以根據(jù)特定對象
            的大小,把該塊內(nèi)存分割成一個個大小相同的對象。如果對
            象池中沒有空閑對象使用時,可以再向系統(tǒng)申請同樣大小的
            內(nèi)存塊。如果對象使用完畢后直接放到對象池中,這種內(nèi)存
            管理策略能有效地提升程序性能。
            4.2.1 對象池的應(yīng)用
            當服務(wù)器接受一個客戶端請求后,會創(chuàng)建成功返回一個
            客戶端套接字句柄。如果出現(xiàn)大量并發(fā)客戶端連接請求時,
            就會出現(xiàn)頻繁地分配和釋放對象的情況,這個過程可能會消
            耗大量的系統(tǒng)資源,有損系統(tǒng)性能。WinSock2 還提供一個接
            受擴展函數(shù)AcceptEx,它允許在接受連接之前就事先創(chuàng)建一
            個套接字句柄,使之與接受連接相關(guān)聯(lián)。在調(diào)用AcceptEx 時,
            可以直接把該句柄作為參數(shù)傳遞給AcceptEx。有了這個保證,
            可以通過采用對象池技術(shù)來提升系統(tǒng)性能,可以在接受連接
            之前就創(chuàng)建一定數(shù)量的套接字句柄,隨著新連接請求的到來
            將句柄分配出去,當客戶端斷開連接后,把相應(yīng)句柄重新放
            入套接字對象池中。
            另外需要用到對象池的地方是,在每一次投遞WSASend
            或WSARecv 操作時,都要傳進一個重疊結(jié)構(gòu)體參數(shù)。可以
            提前創(chuàng)建一個重疊結(jié)構(gòu)體對象池,當發(fā)起異步I/O 操作時,
            先從池中取一個結(jié)構(gòu)體對象,用完之后并不直接銷毀,而是
            再放回對象池以便以后重復(fù)利用。創(chuàng)建的結(jié)構(gòu)體數(shù)量取決于
            完成端口的處理效率,如果處理效率比較高,則數(shù)量可能就
            少些,反之,就需要多創(chuàng)建些對象。
            該系統(tǒng)所設(shè)計的對象池是線程安全的,可以被多個線程
            共享,在獲得和釋放對象時都需要加鎖,從而保證線程間互
            斥訪問對象池。
            4.2.2 對象池的優(yōu)點
            與系統(tǒng)直接管理內(nèi)存相比,對象池在系統(tǒng)性能優(yōu)化方面
            主要有如下優(yōu)點:
            (1)針對特殊情況,例如需要頻繁分配和釋放固定大小的
            對象時,不需要復(fù)雜的分配算法和線程同步。也不需要維護
            內(nèi)存空閑表的額外開銷,從而獲得較好的性能。
            (2)由于直接分配一定數(shù)量的連續(xù)內(nèi)存空間作為內(nèi)存塊,
            因此一定程度上提高了程序局部性能,提升了應(yīng)用程序整體
            性能。
            (3)比較容易控制頁邊界對齊和內(nèi)存字節(jié)對齊,基本沒有
            內(nèi)存碎片問題。
            4.3 環(huán)形緩存區(qū)
            基于TCP 協(xié)議的服務(wù)器應(yīng)用程序,拼包處理過程必不可
            少。由于要從接收緩存中分解出一個個邏輯數(shù)據(jù)包,因此一
            般都要涉及內(nèi)存拷貝操作,過多的內(nèi)存拷貝必然降低系統(tǒng)
            性能。
            當然,就邏輯數(shù)據(jù)包的拼裝問題而言,也完全可以避免
            數(shù)據(jù)拷貝操作,方法是使用環(huán)形緩沖區(qū)。本文所說的環(huán)形緩
            沖區(qū)是具體這種特征的接收緩沖區(qū),在服務(wù)器的接收事件里,
            當處理完了一次從緩沖區(qū)里取走所有完整邏輯包的操作后,
            可能會在緩沖區(qū)里遺留下來新的不完整數(shù)據(jù)包。使用了環(huán)形
            緩沖區(qū)后,就可以不將數(shù)據(jù)重新復(fù)制到緩沖區(qū)首部以等待后
            續(xù)數(shù)據(jù)的拼裝,可以根據(jù)記錄下的隊列首部和隊列尾部指針
            進行下一次的拼包操作。
            環(huán)形緩沖區(qū)在IOCP 的處理中,甚至在其他需要高效率
            處理數(shù)據(jù)收發(fā)的網(wǎng)絡(luò)模型的接收事件處理中,是一種被廣泛
            采用的優(yōu)化方案。
            5 實驗結(jié)果
            為了證明論文中系統(tǒng)優(yōu)化的方法能獲得預(yù)期的性能優(yōu)
            勢,對內(nèi)存池和系統(tǒng)整體性能進行了實驗測試。測試硬件是:
            CPU:AMD Turion 64,內(nèi)存:1 024 MB,網(wǎng)絡(luò):100 MB 局
            域網(wǎng),操作系統(tǒng):Windows XP Professional SP2。
            測試1:對象池性能測試
            由表1 可以看出,由于使用對象池來分配小對象的內(nèi)存,
            速度提高了52.48%,使得內(nèi)存分配獲得了顯著的效率提升。
            速度提高的原因可以歸結(jié)為以下幾點:
            (1)除了偶爾的內(nèi)存申請和銷毀會導(dǎo)致從進程堆中分配
            和銷毀內(nèi)存塊外,絕大多數(shù)的內(nèi)存申請和銷毀都由對象池在
            已經(jīng)申請到的內(nèi)存塊中進行,而沒有直接與進程打交道,而
            直接與進程打交道是很耗時的操作。
            (2)這是在單線程環(huán)境的對象池,在多線程環(huán)境下,由于
            加鎖,因此速度提高的會少些。
            (下轉(zhuǎn)第114 頁)
            posted on 2009-03-10 19:51 李陽 閱讀(2569) 評論(1)  編輯 收藏 引用 所屬分類: 游戲開發(fā)

            評論:
            # re: 高性能服務(wù)器底層網(wǎng)絡(luò)通信模塊的設(shè)計方法 2012-04-04 15:32 | xmx1108
            很有幫助的  回復(fù)  更多評論
              
            欧美一区二区三区久久综| 久久福利片| 99精品国产在热久久无毒不卡 | 新狼窝色AV性久久久久久| 亚洲中文久久精品无码| 国产精品狼人久久久久影院 | 丰满少妇人妻久久久久久| 超级碰久久免费公开视频| 亚洲精品乱码久久久久久蜜桃图片| 日产精品久久久一区二区| 久久国产三级无码一区二区| 久久精品中文字幕一区| 日韩亚洲欧美久久久www综合网| 狠狠色丁香婷婷久久综合五月 | 精品久久久久久国产潘金莲| 欧美大战日韩91综合一区婷婷久久青草 | 精品国产一区二区三区久久蜜臀| 亚洲精品国产美女久久久| 日韩一区二区三区视频久久| 亚洲国产成人久久综合一| 久久久久久国产精品无码超碰| 人妻少妇精品久久| 91精品国产91久久久久久青草| 久久综合狠狠综合久久| 久久精品一本到99热免费| 午夜肉伦伦影院久久精品免费看国产一区二区三区 | AAA级久久久精品无码区| 精品蜜臀久久久久99网站| 久久综合久久美利坚合众国| 韩国三级中文字幕hd久久精品| 久久精品国产秦先生| 国内精品人妻无码久久久影院| 亚洲精品乱码久久久久久中文字幕| 香蕉久久久久久狠狠色| 国产99久久久国产精品小说| 女人高潮久久久叫人喷水| 精品久久久久成人码免费动漫| 日日狠狠久久偷偷色综合免费| 四虎国产精品成人免费久久| 波多野结衣久久精品| 性高湖久久久久久久久|