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

慢聊Golang協(xié)程池Ants實現(xiàn)原理

開發(fā) 前端
我們知道實際用戶的任務是綁定在goWorker上的, 在執(zhí)行完任務之后Ants,會將該goWorker放回到workers結構的items數(shù)組中(協(xié)程池)。

大家都知道goroutine 是 Go語言中的輕量級線程實現(xiàn),由 Go 運行時(runtime)管理,Go 程序會智能地將 goroutine 中的任務合理地分配給每個 CPU。創(chuàng)建一個goroutine大小大概在2k左右,可以說非常的節(jié)省機器資源。

但是為什么要用池化的方式呢?機器資源總是有限的,如果創(chuàng)建了幾十萬個goroutine,那么就消耗比較大了,在一些需要對并發(fā)資源進行控制、提升性能、控制生命周期的場景中,還是需要用到協(xié)程池去處理。

今天就介紹在github用Go語言實現(xiàn)的有 11.5k?的 Ants 協(xié)程池庫的實現(xiàn)!

圖片圖片

初識Ants

Ants介紹

Go的協(xié)程非常輕量,但是在超高并發(fā)場景,每個請求創(chuàng)建一個協(xié)程也是低效的,一個簡單的思想就是協(xié)程池。

Ants實現(xiàn)了一個具有固定容量的goroutine池,管理和回收大量goroutine,允許開發(fā)人員限制并發(fā)程序中的goroutines數(shù)量。

圖片圖片

Github地址:https://github.com/panjf2000/ants

這是在github上的截圖,注意不同版本之間代碼實現(xiàn)會略有差異。

圖片圖片

特性

??Ants具有如下特性:

  • ? 自動管理和回收大量goroutine
  • ? 定期清除過期的goroutines
  • ? 豐富的API:提交任務,獲取運行goroutine的數(shù)量,動態(tài)調(diào)整池的容量,釋放池,重新啟動池
  • ? 優(yōu)雅地處理死機以防止程序崩潰
  • ? 高效的內(nèi)存使用,甚至比Golang中的無限goroutine實現(xiàn)了更高的性能
  • ? 非阻塞機制

核心概念

  • ? Pool :Ants協(xié)程池核心結構
  • ? WorkerArray:Pool池中的worker隊列,存放所有的Worker
  • ? goWorker:運行任務的實際執(zhí)行者,它啟動一個 goroutine 來接受任務并執(zhí)行函數(shù)調(diào)用
  • ? sync.Pool:golang 標準庫下并發(fā)安全的對象池,緩存申請用于之后的重用,以減輕GC的壓力
  • ? spinLock:基于CAS機制和指數(shù)退避算法實現(xiàn)的一種自旋鎖

運行流程圖

Ants運行流程圖如下:

圖片圖片

前置知識

自旋鎖 spinLock

我們先了解下什么是自旋鎖!

加鎖的目的就是保證共享資源在任意時間里,只有一個線程訪問,而自旋鎖加鎖失敗后,線程會忙等待,直到它拿到鎖。

圖片圖片

如果要實現(xiàn)鎖的話需要實現(xiàn)Go 標準庫sync的Locker接口

// A Locker represents an object that can be locked and unlocked.
type Locker interface {
     Lock()
     Unlock()
}

Ants的自旋鎖是基于CAS機制和指數(shù)退避算法實現(xiàn)的一種自旋鎖,主要利用了下面幾個關鍵的點:

  • ? sync.Locker接口
  • ? 指數(shù)退避算法
  • ? sync. atomic 原子包中的方法了解
  • ? runtime.Gosched() 讓當前goroutine讓出CPU時間片

?? Go語言中 sync/atomic包提供了底層的原子級內(nèi)存操作,可實用CAS 函數(shù)(Compare And Swap)

?? 指數(shù)退避算法以指數(shù)方式重試請求,請求失敗后重試間隔分別是 1、2、4 ...,2的n次方秒增加

我們看下具體實現(xiàn)代碼和添加的注釋:

//實現(xiàn)Locker接口
type spinLock uint32
//最大回退次數(shù)
const maxBackoff = 16
// 加鎖
func (sl *spinLock) Lock() {
    backoff := 1
    //基于CAS機制,嘗試獲取鎖
    for !atomic.CompareAndSwapUint32((*uint32)(sl), 0, 1) {
        //執(zhí)行backoff次 cpu讓出時間片次數(shù)
        for i := 0; i < backoff; i++ {
            //使當前goroutine讓出CPU時間片
            runtime.Gosched()
        }
        if backoff < maxBackoff {
            //左移后賦值 等于 backoff = backoff << 1
            //左移一位就是乘以 2的1次方
            backoff <<= 1
        }
    }
}

//釋放鎖
func (sl *spinLock) Unlock() {
    atomic.StoreUint32((*uint32)(sl), 0)
}

Gosched()使當前goroutine程放棄處理器,以讓其它goroutine運行,它不會掛起當前goroutine,因此當前goroutine未來會恢復執(zhí)行。

?? backoff <<= 1 這段代碼會有你知道什么意思嗎?

這是Go語言的位運算符 << 表示左移n位就是乘以2的n次方, 而 <<= 表示左移后賦值。

??代碼中 backoff <<= 1 其實就是 backoff = backoff << 1,這是左移一位的結果就是 backoff = backoff * 2^1。

自旋鎖執(zhí)行 backoff 次讓 cpu 時間片動作,次數(shù)分別是 1、2、4 ...,封頂16

Ants自旋鎖邏輯用圖表示如下:

圖片圖片

核心數(shù)據(jù)結構

這里簡單介紹下三個核心的結構體和屬性:

圖片圖片

Pool結構體

Pool就是協(xié)程池的實際結構,在下面代碼中已經(jīng)標記了注釋。

type Pool struct {
    // 協(xié)程池容量 
    capacity int32
    // 當前協(xié)程池中正在運行的協(xié)程數(shù)
    running int32
    // ants 實現(xiàn)的自旋鎖,用于同步并發(fā)操作
    lock sync.Locker
    // 存放一組Worker
    workers workerArray
    // 協(xié)程池狀態(tài) (1-關閉、0-開啟)
    state int32
    // 并發(fā)協(xié)調(diào)器,用于阻塞模式下,掛起和喚醒等待資源的協(xié)程
    cond *sync.Cond
    // worker 對象池
    workerCache sync.Pool
    // 等待的協(xié)程數(shù)量
    waiting int32
    // 回收協(xié)程是否關閉
    heartbeatDone int32
    // 閉回收協(xié)程的控制器函數(shù)
    stopHeartbeat context.CancelFunc
    // 協(xié)程池的配置
    options *Options
}

這里對幾個配置著重講一下:

workerCache :這是sync.Pool類型,主要作用保存和復用臨時對象,減少內(nèi)存分配,降低 GC 壓力,在Ants中是為了緩存釋放的 Worker 資源

options:可配置化過期時間、是否支持預分配、最大阻塞數(shù)量、panic 處理、日志,這里是通過函數(shù)式選項模式進行實現(xiàn)的

goWorker

goWorker 是運行任務的實際執(zhí)行者,它啟動一個 goroutine 來接受任務并執(zhí)行函數(shù)調(diào)用,這個協(xié)程是一個長期運行不會被主動回收的。

type goWorker struct {
    //goWorker 所屬的協(xié)程池
    pool *Pool
    //接收實際執(zhí)行任務的管道
    task chan func()
    //goWorker 回收到協(xié)程池的時間
    recycleTime time.Time
}

WorkerArray

workerArray 是一個接口( interface),其實現(xiàn)包含 stack 棧版本和 queue 隊列兩種實現(xiàn)。

圖片圖片

它定義了幾個通用和用于回收過期 goWorker 的 api

type workerArray interface {
 // worker 列表長度
 len() int 
 // 是否為空
 isEmpty() bool
 // 插入一個goworker
 insert(worker *goWorker) error 
 // 從WorkerArray獲取可用的goworker
 detach() *goWorker 
 // 清理pool.workers中的過期goworker
 retrieveExpiry(duration time.Duration) []*goWorker  
 // 重置,清空WorkerArray中所有的goWorker
 reset() 
}

核心方法

這是核心實現(xiàn)代碼的走讀部分,基本上都有進行了注釋,看起來可能會有點不怎么理解,多看兩遍就好,相信我 ????!

創(chuàng)建Pool

創(chuàng)建Pool其實就是New一個Pool實例,對Pool中結構體的屬性進行初始化、加載一些配置,這種方式很常見,大家可以注意觀察積累。

圖片圖片

代碼實現(xiàn)和注釋如下:

func NewPool(size int, options ...Option) (*Pool, error) {
    //讀取一些自定義的配置
    opts := loadOptions(options...)

    ...
    // 創(chuàng)建 Pool 對象
    p := &Pool{
        capacity: int32(size),
        lock:     internal.NewSpinLock(),
        options:  opts,
    }
     // 指定 sync.Pool 創(chuàng)建 worker 的方法
    p.workerCache.New = func() interface{} {
        return &goWorker{
            pool: p,
            task: make(chan func(), workerChanCap),
        }
    }
    // 初始化Pool時是否進行內(nèi)存預分配
    // 區(qū)分workerArray 的實現(xiàn)方式
    if p.options.PreAlloc {
        if size == -1 {
            return nil, ErrInvalidPreAllocSize
        }
        // 預先分配固定 Size 的池子
        p.workers = newWorkerArray(loopQueueType, size)
    } else {
        // 初始化不創(chuàng)建,運行時再創(chuàng)建
        p.workers = newWorkerArray(stackType, 0)
    }

    p.cond = sync.NewCond(p.lock)

    // 開啟一個goroutine清理過期的 worker
    go p.purgePeriodically()

    return p, nil
}

workerChanCap:確定工作程序的通道是否應為緩沖通道,當獲取給GOMAXPROCS設置的值等于1時表示單核執(zhí)行,此時的通道是無緩沖通道,否則是有緩沖通道,且容量是1。

這里講的是默認未進行預分配,采用 workerStack 棧實現(xiàn)workerArray的初始化。

清理過期goWorker

在初始化好Pool結構屬性后,會開啟一個goroutine清理過期的 worker。

??怎么判定goroutine是過期的?

Ants過期的定義是:每個 goWorker的 recycleTime 加上用戶配置的過期時間 Pool.options.ExpiryDuration 小于 time.Now() 時即認為該協(xié)程已過期。

我們看下具體流程

func (p *Pool) purgePeriodically(ctx context.Context) {
    // ExpiryDuration 默認是1s
    heartbeat := time.NewTicker(p.options.ExpiryDuration)
    ...
    for {
        select {
        case <-heartbeat.C:
        case <-ctx.Done():
            return
        }
        // pool關閉
        if p.IsClosed() {
            break
        }
        // 從 workers 中獲取過期的 worker
        p.lock.Lock()
        expiredWorkers := p.workers.retrieveExpiry(p.options.ExpiryDuration)
        p.lock.Unlock()
        // 清理過期的worker
        for i := range expiredWorkers {
            expiredWorkers[i].task <- nil
            expiredWorkers[i] = nil
        }
        // 喚醒所有等待的線程
        if p.Running() == 0 || (p.Waiting() > 0 && p.Free() > 0) {
            p.cond.Broadcast()
        }
    }
}

??清理流程如下:

  1. 1. 取出過期的goWorker
  2. 2. 通知 goWorker 退出,方式是向過期 goWorker 的 task channel 發(fā)送一個 nil
  3. 3. 接收值為 nil 的任務后goWorker會退出
  4. 4. 所有工作程序都已清理完畢,可能這時還有 goroutine 阻塞在cond.Wait上,會調(diào)用 p.cond.Broadcast() 喚醒這些 goroutine

Submit任務提交

在初始化完成Pool之后,就需要往池中提交帶執(zhí)行任務了,Pool提供了 Submit 方法,提供外部發(fā)起提交任務的接口。

func (p *Pool) Submit(task func()) error {
    // pool是否關閉
    if p.IsClosed() {
        return ErrPoolClosed
    }
    var w *goWorker
    // 嘗試獲取空閑的goWorker
    if w = p.retrieveWorker(); w == nil {
        return ErrPoolOverload
    }
    // 發(fā)送到 goWorker的channel中
    w.task <- task
    return nil
}

獲取可用goWork

Submit方法內(nèi)部調(diào)用 pool.retrieveWorker 方法并嘗試獲取一個空閑的 goWorker,如果獲取成功會將任務發(fā)送到goWorker的channel類型task中。

func (p *Pool) retrieveWorker() (w *goWorker) {
    //創(chuàng)建一個新的goWorker,并執(zhí)行
    spawnWorker := func() {
        //實例化 worker
        w = p.workerCache.Get().(*goWorker)
        // 運行
        w.run()
    }

    // 加鎖
    p.lock.Lock()
    // 從workers 中取出一個 goWorker
    // workerStack 實現(xiàn)了p.workers的方法
    w = p.workers.detach()
    if w != nil { 
        p.lock.Unlock()
    // Pool容量大于正在工作的 goWorker 數(shù)量)
    //則調(diào)用 spawnWorker() 新建一個 goWorker
    } else if capacity := p.Cap(); capacity == -1 || capacity > p.Running() {
        
        p.lock.Unlock()
        spawnWorker()
    } else { 
          // options設置了非阻塞選項,直接返回 nil
          if p.options.Nonblocking {
            p.lock.Unlock()
            return
        }
    retry:
        //option設置了最大阻塞隊列,當前阻塞等待的任務數(shù)量已經(jīng)達設置上限,直接返回 nil
        if p.options.MaxBlockingTasks != 0 && p.Waiting() >= p.options.MaxBlockingTasks {
            p.lock.Unlock()
            return
        }
        ...
        var nw int
        //如果正在執(zhí)行的worker數(shù)量為0時,則重新創(chuàng)建woker
        if nw = p.Running(); nw == 0 { 
            p.lock.Unlock()
            spawnWorker()
            return
        }
        //p.workers中獲取可用的worker
        //執(zhí)行開頭創(chuàng)建的spawnWorker
        if w = p.workers.detach(); w == nil {
            if nw < p.Cap() {
                p.lock.Unlock()
                spawnWorker()
                return
            }
            goto retry
        }
        p.lock.Unlock()
    }
    return
}

??看完注釋后理一理retrieveWorker的執(zhí)行邏輯:

  1. 1. 聲明一個spawnWorker,從對象池 workerCache 中獲取 goWorker
  2. 2. 嘗試從 workers 中取出可用的 goWorker
  3. 3. 如未達到協(xié)程池的容量限制,獲取并啟動 spawnWorker(goWorker)
  4. 4. 如何用戶設置了非阻塞選項,直接返回空的goWorker
  5. 5. 如果正在執(zhí)行的goWorker 的數(shù)量等于0,調(diào)用 spawnWorker()
  6. 6. 未獲取到goWorker,并且Pool容量未滿,同樣調(diào)用 spawnWorker()

?? spawnWorker() 是一個創(chuàng)建和運行goWorker的函數(shù),為后面獲取不到goWorker時先進行預創(chuàng)建goWorker

任務執(zhí)行

任務執(zhí)行就是開啟了一個協(xié)程,然后執(zhí)行goWorker中channel的任務task。

func (w *goWorker) run() {
    // pool的running 加 一
    w.pool.addRunning(1)
    go func() {
        defer func() {
            ...
            if p := recover(); p != nil {
                //處理捕獲的panic
            }
            w.pool.cond.Signal()
        }()
        //任務執(zhí)行
        for f := range w.task {
            if f == nil {
                return
            }
            f()
            //執(zhí)行完后回收worker
            if ok := w.pool.revertWorker(w); !ok {
                return
            }
        }
    }()
}

goWorker放回pool

我們知道實際用戶的任務是綁定在goWorker上的, 在執(zhí)行完任務之后Ants,會將該goWorker放回到workers結構的items數(shù)組中(協(xié)程池)。

func (p *Pool) revertWorker(worker *goWorker) bool {
    if capacity := p.Cap(); (capacity > 0 && p.Running() > capacity) || p.IsClosed() {
        p.cond.Broadcast()
        return false
    }
    // 重置空閑計時器,用于判定過期
    worker.recycleTime = p.nowTime()
    p.lock.Lock()
    ...
    // 調(diào)用works的insert方法放回Pool
    err := p.workers.insert(worker)
    if err != nil {
        p.lock.Unlock()
        return false
    }
    // p.cond.Signal() 喚醒一個可能等待的線程
    p.cond.Signal()
    p.lock.Unlock()
    return true
}

責任編輯:武曉燕 來源: 小許code
相關推薦

2021-06-08 09:49:01

協(xié)程池Golang設計

2023-12-04 07:31:41

Golangwebsocket

2021-05-20 09:14:09

Kotlin協(xié)程掛起和恢復

2017-05-02 11:38:00

PHP協(xié)程實現(xiàn)過程

2024-02-05 09:06:25

Python協(xié)程Asyncio庫

2023-12-05 13:46:09

解密協(xié)程線程隊列

2025-02-28 09:04:08

2022-11-21 06:55:08

golang協(xié)程

2021-09-16 09:59:13

PythonJavaScript代碼

2021-08-04 16:19:55

AndroidKotin協(xié)程Coroutines

2025-06-03 00:00:02

Go協(xié)程鎖機制

2023-04-19 21:20:49

Tars-Cpp協(xié)程

2022-10-28 10:45:22

Go協(xié)程GoFrame

2025-06-10 02:00:00

Golangmap

2024-05-29 08:05:15

Go協(xié)程通信

2023-11-17 11:36:59

協(xié)程纖程操作系統(tǒng)

2023-11-23 08:31:51

競爭鎖共享字段

2025-06-26 04:10:00

2020-06-11 11:36:49

線程池Java場景

2022-06-01 09:51:51

Golang方法接收者
點贊
收藏

51CTO技術棧公眾號

亚洲三级电影全部在线观看高清| 天天做综合网| 欧美色xxxx| 久久av一区二区三区漫画| 自拍偷拍18p| 99久久精品费精品国产风间由美| 日韩精品专区在线影院观看 | 99国产精品免费视频观看| 欧美一级片免费看| www黄色av| 在线播放免费av| 2020国产精品自拍| 91免费在线视频| 国产99久久久| 亚洲精品久久久| 亚洲欧美日韩精品| 性高潮久久久久久| 国产亚洲欧美日韩精品一区二区三区| 亚洲毛片av在线| 色一情一区二区三区四区| 国产 欧美 自拍| 麻豆一区二区99久久久久| 欧美亚洲国产成人精品| 国产一级二级毛片| 91精品国产成人观看| 亚洲丝袜av一区| 欧美精品色综合| 免费无码不卡视频在线观看| 国产精品va在线观看视色| 久久久三级国产网站| 粉嫩精品一区二区三区在线观看| 中文字幕人妻丝袜乱一区三区| 亚洲激情视频| 欧美丰满片xxx777| 日韩欧美国产成人精品免费| 精品国产a一区二区三区v免费| 亚洲精品在线观看视频| 性色av浪潮av| 91精品国产一区二区在线观看 | 日批视频在线免费看| 在线观看h网| 亚洲免费观看高清| 一本久久a久久精品vr综合| 色视频在线观看| 97久久超碰精品国产| 国产精品一区二区免费看| 国产av无码专区亚洲av麻豆| 精品一区二区三区视频在线观看| 国产精品电影网| 中文字幕在线观看视频免费| 欧美亚洲三区| 国产成人激情视频| 一级一级黄色片| 日韩不卡一区二区| 国产精品对白刺激| 最近中文字幕在线观看视频| 日韩av电影天堂| 国产精品伦子伦免费视频| 曰批又黄又爽免费视频| 麻豆精品一区二区三区| 国产欧美精品va在线观看| 懂色av蜜臀av粉嫩av喷吹| 成人国产免费电影| 午夜精品视频一区二区三区在线看| 夜夜嗨av色一区二区不卡| 日韩av片在线| 99热在线成人| 欧美区在线播放| 国产精品2020| 久久久精品网| 国产一区欧美二区三区| av小说天堂网| 91亚洲精品久久久蜜桃| 欧美日韩国产三区| 色综合久久影院| 一区二区三区在线视频观看58| www.日本三级| 精品91久久| 欧美另类一区二区三区| 97人妻精品一区二区三区免费| 欧美a一欧美| 在线精品91av| 久草视频精品在线| 久久国产日本精品| 国产美女精彩久久| 人妻妺妺窝人体色www聚色窝| 91免费小视频| 椎名由奈jux491在线播放| 91桃色在线| 日本久久电影网| 天天av天天操| 亚洲午夜久久| 九九精品在线播放| 懂色av中文字幕| 国产成人av自拍| 天天人人精品| 色资源二区在线视频| 欧美日韩高清一区二区不卡| 美女伦理水蜜桃4| 日韩在线第七页| 97精品视频在线播放| 亚洲视频在线观看一区二区| 不卡的av电影| 伊人久久av导航| 中文字幕资源网在线观看免费| 在线成人小视频| 国产熟妇久久777777| 欧美视频一区| 国产精品视频资源| 三级在线电影| 亚洲一区二区精品视频| 欧美在线高清视频| 国产盗摄视频在线观看| 色偷偷偷在线视频播放| 日韩欧美中文字幕制服| 影音先锋男人在线| 国产欧美日韩一区二区三区在线| 成人午夜在线观看| 国产有码在线| 五月综合激情网| 91精品无人成人www| 亚洲aaa级| 欧美猛交免费看| 在线播放国产一区| 久久九九影视网| 1024av视频| 成人免费在线电影网| 久久久成人的性感天堂| 亚洲 小说区 图片区| 99国产精品久久久久久久久久久| 亚洲精品少妇一区二区| 日韩毛片免费视频一级特黄| 中文字幕日韩av电影| 国产高清中文字幕| 成人av在线影院| 9191国产视频| 欧美国产中文高清| 久久伊人色综合| 一级黄色小视频| 中文成人av在线| 国产精品久久a| 日本精品黄色| 国产欧美精品一区二区| 91免费在线| 欧美日韩国产在线观看| 开心激情五月网| 久久国产免费看| 欧美精品一区二区性色a+v| 亚洲欧洲一二区| www国产亚洲精品久久网站| 在线观看中文字幕网站| 国产精品三级在线观看| 91制片厂毛片| 国产大片一区| 亚洲最大的免费| 亚洲卡一卡二| 亚洲第一色在线| 亚洲天堂一区在线观看| 久久久99久久| 日本肉体xxxx裸体xxx免费| 久久国产成人精品| 91免费国产网站| 亚洲欧美成人影院| 亚洲国产一区二区三区在线观看| 日韩高清精品免费观看| av不卡在线播放| 91传媒久久久| 精品视频免费| 91在线|亚洲| 欧美黑人xx片| 国产视频精品在线| 真实的国产乱xxxx在线91| 综合av第一页| 精品人妻伦一二三区久| 久久天天综合| 影音先锋在线亚洲| 成人高潮a毛片免费观看网站| 欧美亚洲成人xxx| av国产在线观看| 日韩免费观看高清完整版在线观看| 日本熟妇毛茸茸丰满| 国产亚洲一区二区三区| 拔插拔插华人永久免费| 尤物在线精品| 日日噜噜噜噜夜夜爽亚洲精品| 四虎国产精品成人免费影视| 欧美激情第一页xxx| 毛片网站在线| 欧美一级生活片| 黄色片中文字幕| 亚洲日穴在线视频| 欧美性xxxx图片| 激情偷乱视频一区二区三区| 久久国产亚洲精品无码| 香蕉av一区二区| 久久福利电影| 韩国三级成人在线| 欧美最猛性xxxxx免费| 成人免费观看视频大全| 国产午夜精品麻豆| 国产精品欧美激情在线| 欧美性少妇18aaaa视频| 丰满少妇高潮久久三区| 久久精品亚洲精品国产欧美kt∨| 欧美视频亚洲图片| 久久一区视频| 天堂а√在线中文在线| 国产va免费精品观看精品视频| 99精品国产高清在线观看| 色综合天天色| 国产91精品青草社区| 中国av在线播放| 在线视频免费一区二区| 日本在线一二三| 欧美精品一区二区三区一线天视频| 91 中文字幕| 一本色道综合亚洲| 久久久久97国产| 亚洲天堂免费看| 小早川怜子久久精品中文字幕| 成人国产精品免费观看| 午夜大片在线观看| 青青青爽久久午夜综合久久午夜| 国产96在线 | 亚洲| 国产一区清纯| 免费在线精品视频| 久久婷婷蜜乳一本欲蜜臀| 秋霞毛片久久久久久久久| 国产精品xxxav免费视频| 91香蕉电影院| 羞羞视频在线观看一区二区| 国产成人精品国内自产拍免费看| 国产色播av在线| 久久久久久有精品国产| 人人澡人人添人人爽一区二区| 久久福利网址导航| 久草免费在线观看| 日韩在线观看免费av| 最新av网站在线观看| 一区二区三区动漫| 国产专区在线| 一区二区欧美久久| 国产九九在线| 中国china体内裑精亚洲片| 国产高清视频在线| 国产一区二区黄| 亚洲欧美视频一区二区| 色悠悠国产精品| 毛片在线看片| 久久99久久亚洲国产| 男男gaygays亚洲| 国内精品国产三级国产在线专| 欧美性受ⅹ╳╳╳黑人a性爽| 九九久久精品一区| 成人免费高清观看| 午夜伦理精品一区| 亚洲黄色免费看| 国产精品男人的天堂| 日韩免费在线电影| 99电影网电视剧在线观看| 久久365资源| 欧美亚州在线观看| 日韩av在线中文字幕| 艳母动漫在线免费观看| 欧美婷婷在线| 欧美在线观看成人| 青青草伊人久久| 亚洲第一区第二区第三区| 国产高清视频一区| 亚洲一级av无码毛片精品| 久久嫩草精品久久久精品| 女人十八毛片嫩草av| 亚洲欧美另类图片小说| 久久久久久激情| 色综合久久久久久久久| 在线免费观看av片| 欧美精品一区二区三区久久久| 每日更新av在线播放| 色久欧美在线视频观看| 毛片网站在线看| 日本老师69xxx| 国产精品一区免费在线| 国产精品手机视频| 精品久久不卡| 大荫蒂性生交片| 久久先锋资源| 国产成人美女视频| av综合在线播放| 亚洲熟女毛茸茸| 婷婷六月综合亚洲| 国产又粗又猛又爽| 精品丝袜一区二区三区| 黄色网页在线播放| 91av视频在线播放| 成人免费91| 清纯唯美一区二区三区| 欧美日韩三区| jizz18女人| 26uuu久久综合| 老女人性淫交视频| 欧洲一区在线观看| 少妇av在线播放| 久久精品视频导航| 色综合天天色| 久久99精品久久久久久久青青日本| 久久五月天小说| 欧美激情国产精品日韩| 国产福利精品一区二区| 免费看的黄色网| 欧美日韩亚洲国产一区| www.色亚洲| 久久精品成人动漫| 国产 日韩 欧美一区| 国产精品一区二区三区免费观看 | 久88久久88久久久| 欧美一区二区三区成人精品| 亚洲欧美日韩在线| 精品一区二三区| 亚洲乱码一区av黑人高潮| 丰乳肥臀在线| 91丝袜脚交足在线播放| 91亚洲国产高清| 亚洲少妇久久久| 久久精品人人做人人爽人人| 日本一区二区不卡在线| 日韩亚洲欧美高清| 日p在线观看| 国产精品免费小视频| 蜜桃精品噜噜噜成人av| 妞干网在线视频观看| 国产·精品毛片| 青青草激情视频| 91精品一区二区三区在线观看| av黄色在线观看| 国产美女精品视频| 日韩欧美视频| 97超碰成人在线| 中文字幕在线不卡一区| 中文永久免费观看| 日韩在线视频网站| 伊人久久大香伊蕉在人线观看热v| 先锋影音网一区| 美女国产一区二区三区| 18精品爽国产三级网站| 欧美人与性动xxxx| 老司机午夜在线| 亚洲最大av网| 伊人久久亚洲影院| 99久久免费看精品国产一区| 午夜精品久久久久久久久久久| 色屁屁草草影院ccyycom| 668精品在线视频| 九九免费精品视频在线观看| 青青在线视频观看| 亚洲国产精品成人综合| 又色又爽又黄无遮挡的免费视频| 日韩最新在线视频| 精品国产不卡一区二区| 亚洲色成人www永久在线观看| 成人免费黄色在线| 国产日产精品一区二区三区| 亚洲欧洲一区二区三区久久| 成人午夜精品| 免费观看黄色的网站| 成人污污视频在线观看| 日本一区二区三区精品| 亚洲图片制服诱惑| 99精品视频在线免费播放| 97久久国产亚洲精品超碰热| 波多野结衣视频一区| 日日夜夜操视频| www.日韩av.com| 999在线精品| 欧美激情国产精品日韩| 综合在线观看色| 人妻精品无码一区二区| 国产精品99久久99久久久二8| 亚洲精品一二三区区别| 日韩av无码一区二区三区不卡| 色嗨嗨av一区二区三区| 在线观看二区| 国产精品日本一区二区 | 免费在线观看污网站| 亚洲自拍偷拍麻豆| 欧美色综合一区二区三区| 成人啪啪免费看| 毛片一区二区| 福利所第一导航| 日韩精品999| 99精品视频在线免费播放| 欧美综合在线播放| 国产精品第四页| 亚洲三级中文字幕| 91老司机精品视频| 久久久久久黄| 免费一级a毛片夜夜看| 一区二区三区精品99久久 | 中国色在线日|韩| 日韩精品一区二区三区电影| 久久免费精品国产久精品久久久久|