精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

我所理解的 Go 的 GPM 模型

開發 前端 人工智能
理解 ??main?? 函數本身也是一個 goroutine 有助于更好地認識 Go 的并發模型的一致性:所有用戶代碼都運行在 goroutine 之上,由統一的 GPM 模型進行調度和管理。這體現了 Go 在語言層面和運行時層面將并發作為一等公民的設計哲學。

Go 語言(Golang)的一大顯著特性是在其語法層面就內建了對協程,即 goroutine 的支持,并且其運行時(runtime)系統為這一功能提供了強大且原生的支撐。在我看來,選擇使用協程而非傳統的線程來支持高并發任務,帶來了諸多益處:

  • 切換成本更低 :協程的切換是純用戶態的操作,由 Go runtime 直接控制,避免了線程切換時需要在內核態和用戶態之間傳遞上下文信息的開銷。相比之下,線程切換由操作系統(OS)層面實現,成本更高。
  • 調度靈活性 :goroutine 的調度由 Go runtime 決定,而非操作系統。這使得 Go 可以根據應用特性實現更優化的調度策略。
  • 支持大規模并發 :由于協程在用戶態實現且資源占用小(例如,初始棧空間通常只有幾 KB),因此可以輕松創建和管理成千上萬甚至數百萬的 goroutine,遠超傳統線程所能支持的并發量。
  • 創建與銷毀成本低 :goroutine 的創建和銷毀由 Go runtime 管理,其開銷遠小于操作系統線程。它們的棧空間是動態伸縮的,初始分配很小,按需增長,回收也更高效。
  • 簡化的并發編程模型 :通過 channel 和 select 等機制,goroutine 使得編寫和理解并發邏輯更為簡單和安全,減少了對傳統并發編程中復雜鎖機制的依賴。

然而,這些輕量級的 goroutine 終究需要依托實際的操作系統線程才能在 CPU 上執行。Go 語言是如何高效管理這些 goroutine 的呢?這就引出了我們今天要深入探討的核心機制—— GPM 模型 。

總體談談 GPM

GPM 是 Go 調度器中三個核心組件的縮寫:

  • G (Goroutine) :即 Go 協程。它是 Go 程序中并發執行的基本單元,擁有自己的棧空間、指令指針以及其他用于調度和執行的上下文信息。G 的數量可以非常龐大。
  • P (Processor) :邏輯處理器。P 并非指物理 CPU 核心,而是 Go runtime 中的一個概念,它代表了 M (內核線程) 執行 Go 代碼所需要的上下文和資源,例如本地可運行 G 的隊列(Local Run Queue, LRQ)、內存分配狀態等。每個 P 同時只能運行一個 G。P 的數量通常由環境變量 GOMAXPROCS 決定,默認情況下等于可用的 CPU 核心數。
  • M (Machine) :內核線程,即操作系統管理的線程。M 是實際執行 Go 代碼的實體。一個 M 必須與一個 P 關聯才能執行 G。

我們首先從宏觀層面理解這種設計背后的考量:

通過設定 GOMAXPROCS 來控制 P 的數量,Go 程序既能確保充分利用多核 CPU 的計算能力,又避免了因過多線程競爭 CPU 資源而導致的性能下降。通常,P 的數量與 CPU 核心數相等,這意味著在理想情況下,每個核心都有一個 P 在積極地調度和執行 G。

P 的角色至關重要,它作為 G 和 M 之間的橋梁。P 持有一個本地可運行 G 的隊列 (LRQ),當 M 需要執行任務時,它會從其關聯的 P 的 LRQ 中獲取 G 來執行。這種設計使得 G 的調度大部分發生在用戶態,避免了頻繁的內核態切換。

此外,P 與 M 的結合實現了線程的復用。當一個 M 因為執行的 G 進行了阻塞性的系統調用(syscall)而被阻塞時,它所關聯的 P 可以被釋放,并被另一個空閑的 M 或者一個新創建的 M 獲取,從而繼續執行 P 本地隊列中的其他 G。這樣就避免了因為少數阻塞操作導致大量線程閑置,同時也減少了線程頻繁創建和銷毀的開銷,相當于 Go runtime 內部實現了一個高效的線程池。這一切對編寫 Go 代碼的用戶來說是透明的。

GPM 是如何調度的?

要理解 GPM 的調度機制,首先需要了解幾個關鍵的概念和數據結構:

  • 全局運行隊列 (Global Run Queue, GRQ) :當 P 的本地運行隊列沒有空間,或者某些 G(例如從網絡調用返回的 G、被搶占的 G)被喚醒或需要重新調度時,它們可能會被放入全局運行隊列。
  • P 的本地運行隊列 (Local Run Queue, LRQ) :每個 P 都有一個自己的 LRQ,用于存放待在該 P 上執行的 G。M 會優先從其關聯 P 的 LRQ 中獲取 G。LRQ 的存在減少了對 GRQ 的競爭,提高了調度效率。
  • g0 :每個 M 都有一個特殊的 goroutine,稱為 g0g0 擁有自己的棧空間(獨立于用戶 G 的棧,通常較大),主要用于執行調度相關的代碼、垃圾回收的輔助工作以及其他運行時任務。當 M 需要切換到某個用戶 G 執行時,會從 g0 棧切換到用戶 G 的棧;反之亦然。
  • m.curg :指向當前在 M 上運行的用戶 G。
  • G 的狀態 :Goroutine 在其生命周期中會經歷多種狀態,例如 _Gidle(閑置,剛被分配還未使用)、_Grunnable(可運行,在運行隊列中等待調度)、_Grunning(運行中,正在 M 上執行)、_Gsyscall(進行系統調用,M 已與 P 分離)、_Gwaiting(等待中,如等待 channel 操作、鎖、或定時器)、_Gdead(已結束,資源可回收)、_Gcopystack(棧復制中,通常在棧增長時發生)、_Gpreempted(被搶占,等待重新調度)。
  • P 的狀態 :P 也有不同的狀態,如 _Pidle(閑置,沒有 M 與之關聯或沒有可運行的 G)、_Prunning(運行中,有 M 與之關聯并正在執行 G 或調度代碼)、_Psyscall(其關聯的 M 正在進行一個阻塞的系統調用,P 本身可能被其他 M 使用)、_Pgcstop(因垃圾回收而停止)、_Pdead(不再使用,例如 GOMAXPROCS 被調小時)。

調度決策在很大程度上是每個 M 各自獨立在其 g0 棧上執行的。當一個 M 空閑下來(例如,其當前 G 執行完畢或被阻塞),它會運行調度代碼來尋找下一個可運行的 G。

  • 沒有單一的“總控”M :Go 的調度器設計上是去中心化的,沒有一個特定的 M 作為“總控制器”來指揮所有其他 M。這種設計避免了單點瓶頸,提高了并發度。
  • 協調機制 :盡管調度是分布式的,但 M 之間通過一些共享結構和機制進行協調:

a.全局運行隊列 (GRQ) :為所有 P 提供了一個共享的 G 來源。

b.工作竊取 (Work Stealing) :空閑的 M 會嘗試從其他 P 的 LRQ 中“竊取”任務。

c.sysmon 后臺監控線程 :這是一個特殊的 M(不與 P 綁定),它負責一些全局性的協調任務,比如垃圾回收的觸發和輔助、網絡輪詢器(Netpoller)事件的處理(間接影響調度,通過將等待 I/O 的 G 變為可運行狀態)、以及檢測并搶占長時間運行的 G。sysmon 更像是一個維護者和協調者,而非一個命令下發者。

d.P 的管理 :Go runtime 負責管理 P 的池。當 M 因系統調用阻塞時釋放 P,或當有空閑 P 和可運行 G 時,runtime 會嘗試喚醒或創建 M 來綁定這些 P。

  • 這種分布式的調度配合全局協調機制,使得 Go 的調度器既高效又具有良好的伸縮性。

接下來,我們通過幾個例子來具體闡述調度過程:

1. 基本調度流程

假設我們有一個 P0 和一個 M0,P0 的 LRQ 中有 G1。

  • 獲取 G :M0 啟動后,或者當它完成了前一個 G 的執行后,它會首先查看其關聯的 P0 的 LRQ。此時,M0 在 g0 棧上執行調度邏輯。
  • 執行 G :M0 從 P0 的 LRQ 中取出 G1。G1 的狀態從 _Grunnable 變為 _Grunning,P0 的狀態保持或變為 _Prunning。M0 的 m.curg 指向 G1。隨后,M0 從 g0 棧切換到 G1 的棧,開始執行 G1 的代碼。
  • G 執行完畢 :當 G1 執行完畢(例如函數返回),它會切換回 g0 棧。G1 的狀態變為 _Gdead,其資源會被回收。M0 (在 g0 棧上) 接著會再次嘗試從 P0 的 LRQ 尋找下一個可運行的 G。
  • LRQ 為空 :如果 P0 的 LRQ 為空,M0(在 g0 棧上)會嘗試進行 工作竊取 (work-stealing) ,它會隨機查看其他 P 的 LRQ,如果發現有 G,就竊取一半過來放到自己的 P0 的 LRQ 中。如果其他 P 的 LRQ 也都為空,M0 會嘗試從 GRQ 獲取 G。
  • GRQ 也為空 :如果 GRQ 也為空,M0 可能會將 P0 置為 _Pidle 狀態,并解除 M0 與 P0 的關聯,M0 自身也可能進入休眠(park)狀態,等待新的 G 到來時被喚醒。或者,M0 會去自旋(spinning)一段時間,期望短期內有新的 G 產生。

自旋 (spinning) 是指 M 在一個緊密的循環中不斷檢查是否有可運行的 G,而不立即放棄 CPU。

  • CPU 占用 :在自旋期間,M 會持續消耗 CPU 資源,如果該 CPU 核心上沒有其他更高優先級的任務,它可能會達到 100% 的占用率。
  • 為何自旋 :這是一種以 CPU 時間換取調度延遲的策略。如果新的 G 很快就能變為可運行狀態(例如,另一個 M 正在處理一個即將完成的短任務,或者一個 I/O 事件即將觸發),那么自旋可以避免 M 進入休眠和隨后被喚醒所帶來的開銷(這通常涉及操作系統層面的上下文切換,成本相對較高)。
  • 自旋的條件與限制 :Go runtime 中的自旋不是無限制的。

a.通常,只有當系統中存在其他活躍的 P(意味著其他 M 正在工作,有可能產生新的 G)時,M 才會進入自旋狀態。如果所有 P 都已空閑,則 M 傾向于直接休眠。

b.同時,runtime 會限制并發自旋的 M 的數量,以避免過多的 M 同時無效自旋。

c.自旋的持續時間或迭代次數是有限的。如果經過短暫的自旋后仍未找到 G,M 將停止自旋,釋放其 P(如果 P 上確實沒有 G),并進入休眠(park)狀態,將 CPU 讓給其他進程或線程。

自旋是一種短期內積極尋找任務的優化手段,適用于預期任務會很快出現的場景,以減少調度開銷,但它確實會短暫地增加 CPU 使用率。

在這個過程中,P 的狀態也會相應變化。例如,當一個 M 成功與一個 P 綁定并開始查找或執行 G 時,P 的狀態會是 _Prunning。如果 P 的 LRQ 和 GRQ 都長時間為空,并且沒有 M 依附于它,它可能進入 _Pidle 狀態。

G 的棧數據切換發生在 M 從 g0 棧切換到用戶 G 的棧,以及從用戶 G 的棧切回 g0 棧時。這個切換操作會保存和恢復各自的棧指針和寄存器等上下文信息。

2. 棧的伸縮與 P 的競爭

  • 棧的動態伸縮 :Goroutine 的棧在創建時通常較小(例如 2KB)。當 G 執行的函數調用深度增加,需要的棧空間超過當前大小時,Go runtime 會觸發一個稱為 morestack 的機制。該機制會分配一個新的、更大的棧段,并將舊棧的內容拷貝到新棧段,然后 G 繼續在新棧上執行。這個過程對用戶是透明的。當函數返回,棧使用量減少時,雖然不會立即縮小,但在垃圾回收期間,如果發現棧使用率過低,可能會進行棧的收縮(shrinkstack)。
  • P 的競爭 :在 Go 程序啟動時,會根據 GOMAXPROCS 創建相應數量的 P。如果 M 的數量少于 P 的數量(例如,某些 M 因為系統調用阻塞了),或者有空閑的 P 和待運行的 G,運行時可能會喚醒或創建新的 M 來綁定這些 P。一個 M 必須獲取到一個 P 才能運行 Go 代碼。如果所有 P 都在 _Prunning 狀態(即都有 M 在其上運行 G),那么新創建的 G 只能進入 LRQ 或 GRQ 等待。當一個 M 從阻塞的系統調用返回,或者一個 G 執行完畢,它會嘗試獲取一個 P 來繼續執行。

3. I/O 操作與網絡調度

當一個 G (假設為 Gx,在 M1/P1 上運行) 發起一個阻塞性的 I/O 操作,比如網絡讀寫時,情況會變得特殊:

  • 進入系統調用 :Gx 在 M1 上調用了一個阻塞的 read。Go runtime 的 syscall 包中的函數通常會進行特殊處理。M1 會即將進入阻塞狀態。
  • 釋放 P :為了不讓 P1 上的其他 G 被餓死,M1 會釋放 P1。P1 此時 通常會連同其 LRQ 中的 G 一起 ,被移交給一個其他可用的、處于空閑狀態的 M (例如 M2,可以是已存在的空閑 M,或者是 runtime 根據需要新創建的 M 來接管這個 P)。M1 則帶著 Gx 進入阻塞的系統調用。Gx 的狀態變為 _Gsyscall

這里需要考慮到調度器內部實現的復雜性和一些邊緣情況。核心原則是: LRQ 始終與 P 綁定 。當 M1 因 Gx 的系統調用而將要阻塞時,它會釋放 P1。

  • 主要情況 :調度器會立即嘗試尋找一個空閑的 M (M2) 來接管 P1。如果找到,M2 就綁定 P1,并開始執行 P1 的 LRQ 中的 G。這時,P1 及其 LRQ 完整地從 M1 轉移到了 M2。
  • 沒有立即可用的 M:如果暫時沒有空閑的 M 可以立即接管 P1,P1 會被放入一個空閑 P 隊列 (pidle 列表)。其 LRQ 中的 G 仍然與 P1 綁定并處于 _Grunnable 狀態。一旦有 M 可用(例如 M1 從系統調用返回后變為空閑,或者 sysmon 檢測到需要更多 M 并創建/喚醒了一個),這個 M 就會從 pidle 列表中獲取 P1,并開始執行其 LRQ 中的 G。
  • 因此,P1 的 LRQ 中的 G 總是和 P1 在一起 。關鍵在于 P1 由哪個 M 來服務。如果 M1 阻塞了,它就不能服務 P1,所以 P1 必須尋找新的 M,或者等待 M 變為可用。
  • 網絡輪詢器 (Netpoller) :Go runtime 內部維護了一個網絡輪詢器(在 Linux 上通常基于 epoll,在 macOS 上基于 kqueue,在 Windows 上基于 iocp)。當 Gx 發起網絡 I/O 時,其對應的文件描述符會被注冊到這個網絡輪詢器中。M1 線程本身會阻塞在系統調用上(或者對于非阻塞 I/O,G 會等待 netpoller 的通知),但它不再持有 P。
  • I/O 就緒與喚醒 :當網絡輪詢器檢測到 Gx 等待的文件描述符上的 I/O 操作就緒(例如數據可讀),它會通知調度器。Gx 會被標記為 _Grunnable,并被放回到某個 P 的 LRQ (可能是原來的 P1,如果它恰好空閑) 或者 GRQ 中。

Go 的標準庫網絡操作在底層通常被封裝為非阻塞模式,并與 netpoller 集成。

  • 注冊與等待 :當 Gx 調用如 net.Conn.Read() 時,如果數據尚未到達,runtime 不會真的讓 M1 線程阻塞在內核的 read() 調用上。相反,它會將 Gx 的狀態置為 _Gwaiting,并將與該連接對應的文件描述符 (FD) 注冊到 netpoller 中,請求 netpoller 在該 FD 可讀時通知。然后,M1 釋放 P1(或 P1 被其他 M 接管),M1 可以去執行其他 G 或者休眠。
  • Netpoller 的監控 :Netpoller (通常是一個獨立的系統線程或由 sysmon 驅動) 使用操作系統提供的事件通知機制 (如 epoll_waitkevent 等) 來同時監控大量已注冊的 FD。這些機制允許一個線程高效地等待多個 FD 上的事件,而無需為每個 FD 單獨創建一個線程。
  • 事件通知 :當操作系統內核檢測到某個 FD 上的數據已到達(對于 read 操作)或可以發送數據(對于 write 操作)時,它會通知 netpoller。
  • G 的喚醒 :Netpoller 收到內核通知后,會識別出是哪個 G 在等待這個 FD 上的事件。它會將該 G 從 _Gwaiting 狀態轉換回 _Grunnable 狀態,并將其放入一個運行隊列 (通常是 GRQ,有時也可能是某個 P 的 LRQ,例如上次運行該 G 的 P,以期利用緩存局部性)。
  • 調度執行實際讀操作 :一旦 Gx 變為 _Grunnable,它就和其他等待調度的 G 一樣。當某個 M/P 組合選中它執行時,它會從之前中斷的地方恢復。此時,由于 netpoller 已經確認數據就緒,G 可以執行實際的、現在不會阻塞的 read() 操作來獲取數據。
  • 重新調度執行 :一旦 Gx 變為 _Grunnable,它就和其他可運行的 G 一樣,等待某個 M/P 組合來執行它。當輪到它時,它會從上次阻塞的地方繼續執行。

這種機制確保了少數 G 的阻塞性 I/O 不會阻塞整個程序的并發執行。M 的數量可能會根據需要動態調整(在一定范圍內),以適應負載情況。

創建一個 go func(){}() 發生了什么?

當你執行一行代碼 go func(){ ... }() 時,Go runtime 會執行以下步驟:

  • 創建 G 對象 :首先,runtime 會在堆上分配并初始化一個新的 G 對象。這個對象包含了新 goroutine 的棧信息(初始分配一個小棧)、程序計數器(指向匿名函數的起始位置)以及其他狀態信息。

a.設置初始狀態 :新創建的 G 的初始狀態被設置為 _Grunnable,表示它已經準備好運行,只等待調度器的調度。

b.放入隊列 :這個新的 _Grunnable 的 G 通常會被嘗試放入當前 M 所關聯的 P 的 LRQ。

  • 如果該 P 的 LRQ 已滿,runtime 會嘗試將 P 的 LRQ 中的一部分 G(包括這個新的 G)均衡到 GRQ 中。
  • 在某些情況下,如果創建 G 的 P 處于特殊狀態,或者為了更好的負載均衡,新的 G 也可能直接被放入 GRQ。
  • 創建 G 的函數返回 :go 語句本身是一個非阻塞調用。執行 go 語句的 goroutine 會繼續執行其后續代碼,而不會等待新創建的 goroutine 開始或完成執行。
  • 調度與執行 :新創建的 G 現在位于某個運行隊列中。當某個 M(可能就是當前的 M,也可能是其他 M)在未來的某個調度點(例如,當前 G 執行完畢、發生搶占、或 M 從系統調用返回時)查找可運行的 G 時,它就有機會從 LRQ 或 GRQ 中獲取這個新的 G。獲取到 G 后,M 會設置好運行環境(切換到該 G 的棧,設置 G 的狀態為 _Grunning 等),然后開始執行該匿名函數內的代碼。

整個過程與上面描述的 GPM 調度機制緊密相連,新的 G 只是作為調度器可調度的一個單元被高效地管理起來。

調度策略與搶占機制

Go 的調度器采用了一些關鍵策略來保證公平性和效率:

  • 工作竊取 (Work Stealing) :如前所述,當一個 P 的 LRQ 為空時,其關聯的 M 會嘗試從其他 P 的 LRQ 中“竊取”一半的 G 到自己的 LRQ,或者從 GRQ 中獲取 G。這有助于在 P 之間均勻分配工作負載,防止某些 P 空閑而另一些 P 過載。
  • 搶占 (Preemption) :在 Go 的早期版本中(1.14 之前),搶占主要是協作式的。也就是說,一個 goroutine 主動放棄 CPU 的執行權通常發生在函數調用時(編譯器會在函數入口處插入檢查點,判斷是否需要進行棧增長以及是否需要被搶占)、channel 操作、select 語句、以及一些同步原語的調用點。這意味著如果一個 goroutine 執行一個沒有任何函數調用的密集計算循環 (for {}),它可能會長時間占據 M,導致同一個 P 上的其他 goroutine 餓死。

從 Go 1.14 版本開始,引入了 基于信號的異步搶占機制 (asynchronous preemption) ,以解決上述問題:

  • sysmon 后臺監控線程 :Go runtime 有一個名為 sysmon 的特殊 M(不關聯 P),它會定期進行一些維護工作,其中就包括檢查是否有 G 運行時間過長(例如,超過一個固定的時間片,通常是 10ms)。
  • 發送信號 :如果 sysmon 發現某個 G 在一個 M 上運行時間過長,它會向該 M 發送一個搶占信號(例如,在 Unix 系統上是 SIGURG)。
  • 信號處理 :M 接收到信號后,會中斷當前正在執行的 G。G 的上下文(主要是寄存器)會被保存,其狀態會被標記為 _Gpreempted 或類似狀態,然后被放回到運行隊列(通常是 GRQ,以給其他 P 機會執行它,避免立即在同一個 P 上再次調度)。
  • 重新調度 :M 隨后會進入調度循環(在其 g0 棧上),選擇下一個可運行的 G 來執行。

這種異步搶占機制確保了即使是那些沒有主動讓出 CPU 的計算密集型 goroutine 也能夠被公平地調度,從而提高了整個系統的響應性和并發任務的并行度。它使得調度器更加健壯,不易受到不良編寫的 goroutine 的影響。

func main 也是一個 goroutine

當一個 Go 程序啟動時,main 包下的 main 函數并不是直接在某個原始線程上執行,而是由 Go runtime 創建的第一個用戶級 goroutine,通常被稱為 main goroutine 。

  • 初始化過程 :Go 程序的入口點實際上是 runtime 的一段引導代碼。這段代碼會負責初始化調度器、垃圾回收器、創建必要的 M 和 P,然后創建一個 G 來執行用戶編寫的 main.main() 函數。
  • 與其他 goroutine 平等 :這個 main goroutine 在行為上與用戶通過 go 關鍵字創建的其他 goroutine 是平等的。它也擁有自己的棧,受 GPM 調度器的管理,可以被搶占,也可以創建新的 goroutine。
  • 程序生命周期 :main goroutine 的結束標志著整個程序的結束。當 main 函數返回時,Go runtime 會開始關閉程序。此時,所有其他仍在運行的 goroutine 都會被強制終止,除非程序使用了像 sync.WaitGroup 這樣的機制來顯式等待其他 goroutine 完成。
  • 退出碼 :main 函數沒有返回值。程序如果正常退出,通常退出碼為 0。如果發生 panic 且未被 recover,或者調用了 os.Exit(code),則會以相應的狀態退出。

理解 main 函數本身也是一個 goroutine 有助于更好地認識 Go 的并發模型的一致性:所有用戶代碼都運行在 goroutine 之上,由統一的 GPM 模型進行調度和管理。這體現了 Go 在語言層面和運行時層面將并發作為一等公民的設計哲學。

責任編輯:姜華 來源: Piper蛋窩
相關推薦

2025-06-03 02:00:00

2025-06-09 01:15:00

2025-05-28 03:00:00

2024-01-22 10:18:32

平臺工程開發人員技術

2019-10-08 10:37:46

設計技術程序員

2015-11-09 10:12:08

大數據個性化推薦

2016-11-29 16:46:17

存儲閃存經濟學

2013-07-11 10:37:20

Java內存模型

2009-08-07 14:09:47

垃圾郵件企業郵件安全梭子魚

2023-03-03 15:37:32

GMP 模型goroutine

2021-02-22 09:30:09

go開發環境桌面系統

2018-07-10 08:56:19

編程程序員開發

2024-12-03 15:15:22

2019-12-26 09:15:44

網絡IOLinux

2021-03-28 20:58:25

Go語言線程

2015-09-02 09:02:21

阿里無線前端架構

2017-05-24 10:12:54

前端FlexboxCSS3

2022-07-06 08:30:36

vuereactvdom

2022-04-30 18:42:38

Go編程語言

2024-10-12 10:29:11

計算機圖形
點贊
收藏

51CTO技術棧公眾號

久久精品72免费观看| 久久精品国产亚洲5555| 一区在线播放视频| 不卡一区二区三区视频| 国产高潮久久久| 日韩精品免费| 亚洲国产成人久久综合| 天天干天天操天天做| av2020不卡| 欧美激情一区二区三区全黄| av色综合网| 日韩黄色片网站| 欧美精品国产| 亚洲性av网站| 在线观看亚洲免费视频| 成人国产精品| 欧美日韩亚洲一区二| 久久久一二三四| 全色精品综合影院| 岛国一区二区在线观看| 国产日产欧美精品| 波多野结衣 久久| 狠狠噜噜久久| 啊v视频在线一区二区三区 | 国产激情视频一区二区在线观看| 26uuu另类亚洲欧美日本老年| 人与动物性xxxx| 亚洲图区在线| 亚洲国产日韩精品在线| 亚洲AV无码久久精品国产一区| 国产精品专区免费| 香蕉影视欧美成人| www.-级毛片线天内射视视| 可以在线观看的黄色| 成人av免费在线播放| 成人亲热视频网站| 91免费视频播放| 天堂va蜜桃一区二区三区漫画版| 久久免费国产视频| 免费在线看黄网址| 一区二区国产在线| 久久精品成人动漫| 久久精品三级视频| 欧美色女视频| 国产一区二区三区毛片| 91精品人妻一区二区三区蜜桃欧美| 成人h动漫免费观看网站| 日韩视频一区在线观看| 91精品视频国产| 亚洲精品自拍| 欧美群妇大交群中文字幕| 久久久久国产一区| 欧美成人家庭影院| 欧美日韩精品欧美日韩精品| 在线观看免费黄网站| 成人在线免费电影网站| 欧美挠脚心视频网站| 欧美午夜aaaaaa免费视频| 黄色成人在线观看网站| 欧美精品日日鲁夜夜添| 8x8x成人免费视频| 日本超碰一区二区| 精品免费日韩av| 国产女人18毛片水真多18| 久久久久观看| 亚洲欧美激情精品一区二区| 国产高清一区二区三区四区| 日韩片欧美片| 欧美成人午夜视频| 久久精品国产亚洲av高清色欲 | 日韩av.com| 国产精品一区二区精品| 精品欧美一区二区久久| 一区二区视频观看| 成人影院在线| 久久中文字幕一区| 日韩av一二三区| 全国精品久久少妇| 亚洲a级在线播放观看| 午夜美女福利视频| 99re成人精品视频| 色狠狠久久av五月综合|| 精品黄色免费中文电影在线播放| 一区二区三区四区在线| 国产日产欧美视频| 久久av影院| 精品国产伦一区二区三区观看体验| 91av在线免费| 欧美电影一区| 97国产精品免费视频| 日韩国产亚洲欧美| 国产成人av电影在线播放| 欧美日韩一区二| 69成人在线| 91国产精品成人| 老女人性生活视频| 国产精品密蕾丝视频下载| 不卡av电影院| 亚洲天堂一区在线| 国内国产精品久久| 蜜桃传媒一区二区| 中文字幕资源网在线观看| 懂色av影视一区二区三区| 福利片一区二区三区| 一区三区在线欧| 欧美成年人视频| 中文字幕一区二区人妻视频| 成人午夜精品在线| 在线国产伦理一区| 亚洲欧美小说色综合小说一区| 91精品在线免费| 国精产品一区二区三区| 亚洲激情国产| 91影视免费在线观看| 国内在线免费高清视频| 亚洲香蕉伊在人在线观| 中文字幕 欧美日韩| 亚洲精品亚洲人成在线观看| 免费av在线一区| 一级特黄aaa大片| 久久精品亚洲麻豆av一区二区| 亚洲熟妇无码av在线播放| 另类一区二区三区| 亚洲欧洲日产国码av系列天堂| 精品无码黑人又粗又大又长| 国产一本一道久久香蕉| 亚洲精品一区二区三区蜜桃久| 九九精品调教| 日韩欧美国产一区二区三区| 日本激情视频一区二区三区| 日本va欧美va瓶| 日本福利一区二区三区| 色在线中文字幕| 亚洲国产私拍精品国模在线观看| 欧美精品久久久久性色| 激情都市一区二区| 亚洲色图自拍| 99久久er| 色综合伊人色综合网| 中国一级特黄视频| 中文字幕av免费专区久久| 北条麻妃在线视频| 国产欧美久久一区二区三区| 日本午夜人人精品| 欧美高清电影在线| 日本乱码高清不卡字幕| 91精品人妻一区二区三区| 玖玖视频精品| 亚洲不卡1区| 欧美成人三级| 久久视频在线观看免费| 国产精品视频在线观看免费| 亚洲欧洲成人自拍| 三年中文在线观看免费大全中国| 99久久夜色精品国产亚洲96| 国产一区二区丝袜| 毛片在线视频| 日韩视频国产视频| 国产一级做a爰片在线看免费| 懂色av一区二区夜夜嗨| 男人日女人视频网站| 亚州综合一区| 国产成人亚洲综合| 日本亚洲精品| 日韩一区二区三区在线视频| 欧美三根一起进三p| 成人福利视频在线| 男女曰b免费视频| 清纯唯美综合亚洲| 91传媒视频在线观看| bl在线肉h视频大尺度| 亚洲精品日韩欧美| 中文字幕在线一| 亚洲免费大片在线观看| www.17c.com喷水少妇| 久久精品中文| 正义之心1992免费观看全集完整版| 亚洲网站三级| 高清欧美性猛交| 国产人成在线视频| 这里只有精品电影| 亚洲 欧美 日韩 综合| 国产精品视频yy9299一区| 1314成人网| 久久国产日本精品| 天天干天天操天天干天天操| 国产成人在线中文字幕| 国产成人精品久久二区二区91| 免费看美女视频在线网站| 精品99999| 国产九色91回来了| 亚洲一级在线观看| ass极品国模人体欣赏| 国产成人av在线影院| 性生交免费视频| 在线国产日韩| 中文字幕一区二区三区有限公司| 哺乳挤奶一区二区三区免费看| 国产不卡一区二区在线播放| 蜜臀av在线| 最好看的2019年中文视频| 高清毛片aaaaaaaaa片| 欧美日韩一区二区三区免费看| 国产精品2020| 亚洲欧美中日韩| 女尊高h男高潮呻吟| 国产一区二区三区四| 久久精品网站视频| 亚洲乱码视频| 成人午夜免费剧场| 日韩欧美不卡| 久久国产精品久久精品国产| 久久综合给合| 国产精选久久久久久| 亚洲国产福利| 久久久久久久香蕉网| 麻豆视频免费在线观看| 亚洲无限av看| 神马午夜电影一区二区三区在线观看| 欧美浪妇xxxx高跟鞋交| 亚洲欧美偷拍一区| 亚洲国产美女搞黄色| 日韩欧美国产成人精品免费| 国产人成亚洲第一网站在线播放 | aiai久久| 99精品国产一区二区| 国产精品视频一区二区三区综合 | 91蜜桃臀久久一区二区| 91久久精品视频| 国产亚洲欧美日韩精品一区二区三区| 欧美亚洲国产视频| caoporn视频在线| 欧美日本亚洲视频| www.欧美日本韩国| 久久精品99国产精品酒店日本| 五月天婷婷在线视频| 中文在线不卡视频| 91美女视频在线| 在线视频免费一区二区| 国产精品二线| 在线日韩第一页| 97超碰人人在线| 中文字幕日韩综合av| 超碰免费在线| 视频在线观看99| 日本韩国在线视频爽| 久久久av一区| 综合久久2019| 性亚洲最疯狂xxxx高清| 午夜影院在线播放| 日本高清视频精品| 国产精品字幕| 成人精品一区二区三区电影免费 | 欧美一区二区三区小说| 国产特级aaaaaa大片| 日韩欧美成人一区| 日本xxxxxwwwww| 日韩经典第一页| 国内在线精品| 色偷偷亚洲男人天堂| 99视频免费在线观看| 欧美精品激情在线| 91av亚洲| 国产欧美 在线欧美| 经典三级久久| 精品一区久久| 成人久久综合| 中文字幕一区综合| 欧美体内she精视频在线观看| 欧美亚洲日本一区二区三区 | 国产精品成人aaaaa网站| 国产福利一区二区三区在线播放| 91精品久久久久久久久久| 日本在线成人| 精品欧美国产一区二区三区不卡| 国产欧美日韩在线观看视频| 中文字幕日韩精品久久| 欧美三级小说| 黄色av免费在线播放| 国产在线视频一区二区三区| 又黄又爽的网站| 国产精品人成在线观看免费| 农村黄色一级片| 午夜私人影院久久久久| 成人黄色激情视频| 欧美草草影院在线视频| 黄色在线观看网| 欧美另类高清videos| 国产精品一区二区av影院萌芽| 91色琪琪电影亚洲精品久久| 欧美三级电影在线| 一区二区av| 香蕉久久a毛片| 91蝌蚪视频在线| 久久久久久免费| 91精品国产高清一区二区三蜜臀| 色综合天天性综合| 精品久久久免费视频| 国产亚洲综合久久| 成年女人在线看片| 91免费精品视频| 精品国产日韩欧美| 给我免费播放片在线观看| 久久成人麻豆午夜电影| 巨胸大乳www视频免费观看| 一二三四社区欧美黄| 怡春院在线视频| 亚洲精品网站在线播放gif| 欧美草逼视频| 成人女保姆的销魂服务| 欧洲乱码伦视频免费| 又粗又黑又大的吊av| 国产成人免费视频网站高清观看视频| 欧美 日韩 国产 成人 在线观看| 亚洲高清不卡在线| a在线观看视频| 日韩中文在线中文网三级| jk漫画禁漫成人入口| 粉嫩av免费一区二区三区| 亚洲国产精品91| 亚洲一区日韩精品| 久久免费精品国产久精品久久久久| 久久久久久久久精| 337p亚洲精品色噜噜| 最新电影电视剧在线观看免费观看| 7m精品福利视频导航| 成人性生交大片免费看96| 久久视频免费在线| 极品少妇xxxx偷拍精品少妇| 五月婷六月丁香| 色综合一个色综合| 天堂av在线资源| 欧美在线www| 日本中文字幕在线一区| 国产免费黄色小视频| 成熟亚洲日本毛茸茸凸凹| 九九精品在线观看视频| 欧美一卡二卡三卡| 18视频在线观看| 动漫美女被爆操久久久| 黑人一区二区三区四区五区| 少妇伦子伦精品无吗| 亚洲国产一区二区三区| 欧美熟妇另类久久久久久不卡| 久久久久久国产精品三级玉女聊斋| 亚洲精品v亚洲精品v日韩精品| 日韩a级黄色片| 成人av动漫在线| 日日噜噜噜噜人人爽亚洲精品| 国产视频精品在线| 日韩一区二区三区免费| 日韩尤物视频| 国产呦精品一区二区三区网站| 免费在线黄色网| 欧美mv日韩mv| 美女高潮视频在线看| 欧美激情www| 日本免费在线视频不卡一不卡二| www.99re6| 日韩欧美国产综合| 性欧美xxx69hd高清| 欧美一区二区三区四区在线观看地址| 日韩福利电影在线| 极品美妇后花庭翘臀娇吟小说| 日韩欧美国产一区二区在线播放| av在线理伦电影| 欧美一区视久久| 久久99国内精品| 久久久久亚洲av片无码下载蜜桃| 日韩av中文字幕在线| 日本欧美韩国| 免费观看亚洲视频| 91丨porny丨在线| 在线视频 91| 欧美极品第一页| 国产成人精品免费视| 中文 日韩 欧美| 欧美日韩国产专区| 秋霞影院午夜丰满少妇在线视频| 97av影视网在线观看| 久久久综合网| 丁香花五月激情| 亚洲美女视频网| 日韩国产一二三区| 免费观看美女裸体网站| 国产精品热久久久久夜色精品三区| 亚洲第一成年人网站| 国产经典一区二区| 国产精品99一区二区| 影音先锋制服丝袜| 精品欧美乱码久久久久久1区2区| 二吊插入一穴一区二区| 国产成人一二三区| 久久久综合网站| 高h放荡受浪受bl| 国产在线播放91| 午夜在线一区| 欧美交换国产一区内射| 最近的2019中文字幕免费一页| 久久亚州av|