久久精品五月,日韩不卡视频在线观看,国产精品videossex久久发布 ,久久av综合

站長資訊網(wǎng)
最全最豐富的資訊網(wǎng)站

一文聊聊go語言中的限流漏桶和令牌桶庫

本篇文章帶大家聊聊go語言中的限流漏桶和令牌桶庫,介紹令牌桶和漏桶的實(shí)現(xiàn)原理以及在實(shí)際項(xiàng)目中簡單應(yīng)用。

一文聊聊go語言中的限流漏桶和令牌桶庫

為什么需要限流中間件?

在大數(shù)據(jù)量高并發(fā)訪問時(shí),經(jīng)常會(huì)出現(xiàn)服務(wù)或接口面對(duì)大量的請(qǐng)求而導(dǎo)致數(shù)據(jù)庫崩潰的情況,甚至引發(fā)連鎖反映導(dǎo)致整個(gè)系統(tǒng)崩潰?;蛘哂腥藧阂夤艟W(wǎng)站,大量的無用請(qǐng)求出現(xiàn)會(huì)導(dǎo)致緩存穿透的情況出現(xiàn)。使用限流中間件可以在短時(shí)間內(nèi)對(duì)請(qǐng)求進(jìn)行限制數(shù)量,起到降級(jí)的作用,從而保障了網(wǎng)站的安全性。

應(yīng)對(duì)大量并發(fā)請(qǐng)求的策略?

  • 使用消息中間件進(jìn)行統(tǒng)一限制(降速)

  • 使用限流方案將多余請(qǐng)求返回(限流)

  • 升級(jí)服務(wù)器

  • 緩存(但仍然有緩存穿透等危險(xiǎn))

  • 等等

可以看出在代碼已經(jīng)無法提升的情況下,只能去提升硬件水平。或者改動(dòng)架構(gòu)再加一層!也可以使用消息中間件統(tǒng)一處理。而結(jié)合看來,限流方案是一種既不需要大幅改動(dòng)也不需要高額開銷的策略。

常見的限流方案

  • 令牌桶算法

  • 漏桶算法

  • 滑動(dòng)窗口算法

  • 等等

漏桶

引入ratelimit庫

go get -u go.uber.org/ratelimit

庫函數(shù)源代碼

 // New returns a Limiter that will limit to the given RPS.  func New(rate int, opts ...Option) Limiter {      return newAtomicBased(rate, opts...)  }    // newAtomicBased returns a new atomic based limiter.  func newAtomicBased(rate int, opts ...Option) *atomicLimiter {      // TODO consider moving config building to the implementation      // independent code.      config := buildConfig(opts)      perRequest := config.per / time.Duration(rate)      l := &atomicLimiter{          perRequest: perRequest,          maxSlack:   -1 * time.Duration(config.slack) * perRequest,          clock:      config.clock,      }        initialState := state{          last:     time.Time{},          sleepFor: 0,      }      atomic.StorePointer(&l.state, unsafe.Pointer(&initialState))      return l  }
登錄后復(fù)制

該函數(shù)使用了函數(shù)選項(xiàng)模式對(duì)多個(gè)結(jié)構(gòu)體對(duì)象進(jìn)行初始化

根據(jù)傳入的值來初始化一個(gè)桶結(jié)構(gòu)體 rateint 傳參 。

初始化過程中包括了

  • 每一滴水需要的時(shí)間 perquest = config.per / time.Duration(rate)
  • maxSlack 寬松度(寬松度為負(fù)值)-1 * time.Duration(config.slack) * perRequest 松緊度是用來規(guī)范等待時(shí)間的

 // Clock is the minimum necessary interface to instantiate a rate limiter with  // a clock or mock clock, compatible with clocks created using  // github.com/andres-erbsen/clock.  type Clock interface {     Now() time.Time     Sleep(time.Duration)  }
登錄后復(fù)制

同時(shí)還需要結(jié)構(gòu)體Clock來記錄當(dāng)前請(qǐng)求的時(shí)間now和此刻的請(qǐng)求所需要花費(fèi)等待的時(shí)間sleep

 type state struct {     last     time.Time     sleepFor time.Duration  }
登錄后復(fù)制

state 主要用來記錄上次執(zhí)行的時(shí)間以及當(dāng)前執(zhí)行請(qǐng)求需要花費(fèi)等待的時(shí)間(作為中間狀態(tài)記錄)

最重要的Take邏輯

 func (t *atomicLimiter) Take() time.Time {     var (        newState state        taken    bool        interval time.Duration     )     for !taken {        now := t.clock.Now()          previousStatePointer := atomic.LoadPointer(&t.state)        oldState := (*state)(previousStatePointer)          newState = state{           last:     now,           sleepFor: oldState.sleepFor,        }         if oldState.last.IsZero() {           taken = atomic.CompareAndSwapPointer(&t.state, previousStatePointer, unsafe.Pointer(&newState))           continue        }        // 計(jì)算是否需要進(jìn)行等待取水操作        newState.sleepFor += t.perRequest(每兩滴水之間的間隔時(shí)間) - now.Sub(oldState.last)(當(dāng)前時(shí)間與上次取水時(shí)間的間隔)                  // 如果等待取水時(shí)間特別小,就需要松緊度進(jìn)行維護(hù)        if newState.sleepFor < t.maxSlack {           newState.sleepFor = t.maxSlack        }         // 如果等待時(shí)間大于0,就進(jìn)行更新        if newState.sleepFor > 0 {           newState.last = newState.last.Add(newState.sleepFor)           interval, newState.sleepFor = newState.sleepFor, 0        }        taken = atomic.CompareAndSwapPointer(&t.state, previousStatePointer, unsafe.Pointer(&newState))     }     t.clock.Sleep(interval)     // 最后返回需要等待的時(shí)間      return newState.last  }
登錄后復(fù)制

實(shí)現(xiàn)一個(gè)Take方法

  • 該Take方法會(huì)進(jìn)行原子性操作(可以理解為加鎖和解鎖),在大量并發(fā)請(qǐng)求下仍可以保證正常使用。

  • 記錄下當(dāng)前的時(shí)間 now := t.clock.Now()

  • oldState.last.IsZero()判斷是不是第一次取水,如果是就直接將state結(jié)構(gòu)體中的值進(jìn)行返回。而這個(gè)結(jié)構(gòu)體中初始化了上次執(zhí)行時(shí)間,如果是第一次取水就作為當(dāng)前時(shí)間直接傳參。

  • 如果 newState.sleepFor 非常小,就會(huì)出現(xiàn)問題,因此需要借助寬松度,一旦這個(gè)最小值比寬松度小,就用寬松度對(duì)取水時(shí)間進(jìn)行維護(hù)。

  • 如果newState.sleepFor > 0 就直接更新結(jié)構(gòu)體中上次執(zhí)行時(shí)間newState.last = newState.last.Add(newState.sleepFor)并記錄需要等待的時(shí)間interval, newState.sleepFor = newState.sleepFor, 0。

  • 如果允許取水和等待操作,那就說明沒有發(fā)生并發(fā)競(jìng)爭的情況,就模擬睡眠時(shí)間t.clock.Sleep(interval)。然后將取水的目標(biāo)時(shí)間進(jìn)行返回,由服務(wù)端代碼來判斷是否打回響應(yīng)或者等待該時(shí)間后繼續(xù)響應(yīng)。

t.clock.Sleep(interval)

 func (c *clock) Sleep(d time.Duration) { time.Sleep(d) }
登錄后復(fù)制

實(shí)際上在一個(gè)請(qǐng)求來的時(shí)候,限流器就會(huì)進(jìn)行睡眠對(duì)應(yīng)的時(shí)間,并在睡眠后將最新取水時(shí)間返回。

實(shí)際應(yīng)用(使用Gin框架)

 func ratelimit1() func(ctx *gin.Context) {      r1 := rate1.New(100)      return func(ctx *gin.Context) {          now := time.Now()          //  Take 返回的是一個(gè) time.Duration的時(shí)間          if r1.Take().Sub(now) > 0 {              // 返回的時(shí)間比當(dāng)前的時(shí)間還大,說明需要進(jìn)行等待              // 如果需要等待, 就 time.Sleep(r1.Take().Sub(now())) 然后放行              // 如果不需要等待請(qǐng)求時(shí)間,就直接進(jìn)行Abort 然后返回              response(ctx, http.StatusRequestTimeout, "rate1 limit...")              fmt.Println("rate1 limit...")              ctx.Abort()              return          }          // 放行          ctx.Next()      }  }
登錄后復(fù)制

這里你可以進(jìn)行選擇是否返回。因?yàn)門ake一定會(huì)執(zhí)行sleep函數(shù),所以當(dāng)執(zhí)行take結(jié)束后表示當(dāng)前請(qǐng)求已經(jīng)接到了水。當(dāng)前演示使用第一種情況。

  • 如果你的業(yè)務(wù)要求響應(yīng)不允許進(jìn)行等待。那么可以在該請(qǐng)求接完水之后然后,如上例。

  • 如果你的業(yè)務(wù)允許響應(yīng)等待,那么該請(qǐng)求等待對(duì)應(yīng)的接水時(shí)間后進(jìn)行下一步。具體代碼就是將if中的內(nèi)容直接忽略。(建議使用)

測(cè)試代碼

這里定義了一個(gè)響應(yīng)函數(shù)和一個(gè)handler函數(shù)方便測(cè)試

 func response(c *gin.Context, code int, info any) {     c.JSON(code, info)  }    func pingHandler(c *gin.Context) {     response(c, 200, "ping ok~")  }
登錄后復(fù)制

執(zhí)行go test -run=Run -v先開啟一個(gè)web服務(wù)

 func TestRun(t *testing.T) {     r := gin.Default()       r.GET("/ping1", ratelimit1(), pingHandler)     r.GET("/ping2", ratelimit2(), helloHandler)       _ = r.Run(":4399")  }
登錄后復(fù)制

使用接口壓力測(cè)試工具go-wrk進(jìn)行測(cè)試->tsliwowicz/go-wrk: go-wrk)

在golang引入install版本可以直接通過go install github.com/tsliwowicz/go-wrk@latest下載

使用幫助

    Usage: go-wrk <options> <url>     Options:      -H       Header to add to each request (you can define multiple -H flags) (Default )      -M       HTTP method (Default GET)      -T       Socket/request timeout in ms (Default 1000)      -body    request body string or @filename (Default )      -c       Number of goroutines to use (concurrent connections) (Default 10)      -ca      CA file to verify peer against (SSL/TLS) (Default )      -cert    CA certificate file to verify peer against (SSL/TLS) (Default )      -d       Duration of test in seconds (Default 10)      -f       Playback file name (Default <empty>)      -help    Print help (Default false)      -host    Host Header (Default )      -http    Use HTTP/2 (Default true)      -key     Private key file name (SSL/TLS (Default )      -no-c    Disable Compression - Prevents sending the "Accept-Encoding: gzip" header (Default false)      -no-ka   Disable KeepAlive - prevents re-use of TCP connections between different HTTP requests (Default false)      -no-vr   Skip verifying SSL certificate of the server (Default false)      -redir   Allow Redirects (Default false)      -v       Print version details (Default false)
登錄后復(fù)制

-t 8個(gè)線程 -c 400個(gè)連接 -n 模擬100次請(qǐng)求 -d 替換-n 表示連接時(shí)間

輸入go-wrk -t=8 -c=400 -n=100 http://127.0.0.1:4399/ping1

可以稍微等待一下水流積攢(壓測(cè)速度過快)。

一文聊聊go語言中的限流漏桶和令牌桶庫可以看出,89個(gè)請(qǐng)求全部返回。也就是說在一段請(qǐng)求高峰期,不會(huì)有請(qǐng)求進(jìn)行響應(yīng)。因此我認(rèn)為既然內(nèi)部已經(jīng)睡眠,那么就也就應(yīng)該對(duì)請(qǐng)求放行處理。

令牌桶

引入ratelimit

go get -u github.com/juju/ratelimit

初始化

 // NewBucket returns a new token bucket that fills at the  // rate of one token every fillInterval, up to the given  // maximum capacity. Both arguments must be  // positive. The bucket is initially full.  func NewBucket(fillInterval time.Duration, capacity int64) *Bucket {     return NewBucketWithClock(fillInterval, capacity, nil)  }    // NewBucketWithClock is identical to NewBucket but injects a testable clock  // interface.  func NewBucketWithClock(fillInterval time.Duration, capacity int64, clock Clock) *Bucket {     return NewBucketWithQuantumAndClock(fillInterval, capacity, 1, clock)  }
登錄后復(fù)制

進(jìn)行Bucket桶的初始化。

 func NewBucketWithQuantumAndClock(fillInterval time.Duration, capacity, quantum int64, clock Clock) *Bucket {     if clock == nil {        clock = realClock{}     }      // 填充速率     if fillInterval <= 0 {        panic("token bucket fill interval is not > 0")     }      // 最大令牌容量     if capacity <= 0 {        panic("token bucket capacity is not > 0")     }      // 單次令牌生成量     if quantum <= 0 {        panic("token bucket quantum is not > 0")     }     return &Bucket{        clock:           clock,        startTime:       clock.Now(),        latestTick:      0,        fillInterval:    fillInterval,        capacity:        capacity,        quantum:         quantum,        availableTokens: capacity,     }  }
登錄后復(fù)制

令牌桶初始化過程,初始化結(jié)構(gòu)體 fillInterval(填充速率) cap(最大令牌量) quannum(每次令牌生成量)。

如果三個(gè)變量有一個(gè)小于或者等于0的話直接進(jìn)行報(bào)錯(cuò)返回。在最開始就將當(dāng)前令牌數(shù)初始化為最大容量。

調(diào)用

 // TakeAvailable takes up to count immediately available tokens from the  // bucket. It returns the number of tokens removed, or zero if there are  // no available tokens. It does not block.  func (tb *Bucket) TakeAvailable(count int64) int64 {     tb.mu.Lock()     defer tb.mu.Unlock()     return tb.takeAvailable(tb.clock.Now(), count)  }
登錄后復(fù)制

調(diào)用TakeAvailable函數(shù),傳入?yún)?shù)為需要取出的令牌數(shù)量,返回參數(shù)是實(shí)際能夠取出的令牌數(shù)量。

內(nèi)部實(shí)現(xiàn)

 func (tb *Bucket) takeAvailable(now time.Time, count int64) int64 {     // 如果需要取出的令牌數(shù)小于等于零,那么就返回0個(gè)令牌      if count <= 0 {        return 0     }      // 根據(jù)時(shí)間對(duì)當(dāng)前桶中令牌數(shù)進(jìn)行計(jì)算     tb.adjustavailableTokens(tb.currentTick(now))      // 計(jì)算之后的令牌總數(shù)小于等于0,說明當(dāng)前令牌不足取出,那么就直接返回0個(gè)令牌     if tb.availableTokens <= 0 {        return 0     }      // 如果當(dāng)前存儲(chǔ)的令牌數(shù)量多于請(qǐng)求數(shù)量,那么就返回取出令牌數(shù)     if count > tb.availableTokens {        count = tb.availableTokens     }      // 調(diào)整令牌數(shù)     tb.availableTokens -= count     return count  }
登錄后復(fù)制

  • 如果需要取出的令牌數(shù)小于等于零,那么就返回0個(gè)令牌

  • 根據(jù)時(shí)間對(duì)當(dāng)前桶中令牌數(shù)進(jìn)行計(jì)算

  • 計(jì)算之后的令牌總數(shù)小于等于0,說明當(dāng)前令牌不足取出,那么就直接返回0個(gè)令牌

  • 如果當(dāng)前存儲(chǔ)的令牌數(shù)量多于請(qǐng)求數(shù)量,那么就返回取出令牌數(shù)

  • 調(diào)整令牌數(shù)

調(diào)整令牌

 func (tb *Bucket) adjustavailableTokens(tick int64) {     lastTick := tb.latestTick     tb.latestTick = tick      // 如果當(dāng)前令牌數(shù)大于最大等于容量,直接返回最大容量     if tb.availableTokens >= tb.capacity {        return     }      // 當(dāng)前令牌數(shù) += (當(dāng)前時(shí)間 - 上次取出令牌數(shù)的時(shí)間) * quannum(每次生成令牌量)     tb.availableTokens += (tick - lastTick) * tb.quantum      // 如果當(dāng)前令牌數(shù)大于最大等于容量, 將當(dāng)前令牌數(shù) = 最大容量 然后返回 當(dāng)前令牌數(shù)     if tb.availableTokens > tb.capacity {        tb.availableTokens = tb.capacity     }     return  }
登錄后復(fù)制

  • 如果當(dāng)前令牌數(shù)大于最大等于容量,直接返回最大容量

  • 當(dāng)前令牌數(shù) += (當(dāng)前時(shí)間 – 上次取出令牌數(shù)的時(shí)間) * quannum(每次生成令牌量)

  • 如果當(dāng)前令牌數(shù)大于最大等于容量, 將當(dāng)前令牌數(shù) = 最大容量 然后返回 當(dāng)前令牌數(shù)

實(shí)現(xiàn)原理

  • 加鎖 defer 解鎖

  • 判斷count(想要取出的令牌數(shù)) 是否小于等于 0,如果是直接返回 0

  • 調(diào)用函數(shù)adjustTokens 獲取可用的令牌數(shù)量

  • 如果當(dāng)前可以取出的令牌數(shù)小于等于0 直接返回 0

  • 如果當(dāng)前可以取出的令牌數(shù)小于當(dāng)前想要取出的令牌數(shù)(count) count = 當(dāng)前可以取出的令牌數(shù)

  • 當(dāng)前的令牌數(shù) -= 取出的令牌數(shù) (count)

  • 返回 count(可以取出的令牌數(shù))

額外介紹

take函數(shù),能夠返回等待時(shí)間和布爾值,允許欠賬,沒有令牌也可以取出。

func (tb *Bucket) Take(count int64) time.Duration

takeMaxDuration函數(shù),可以根據(jù)最大等待時(shí)間來進(jìn)行判斷。

func (tb *Bucket) TakeMaxDuration(count int64, maxWait time.Duration) (time.Duration, bool)

因?yàn)樗麄儍?nèi)部的實(shí)現(xiàn)都基于令牌調(diào)整,我這里不做過多介紹,如果感興趣可以自行研究一下。

測(cè)試

 func ratelimit2() func(ctx *gin.Context) {      // 生成速率 最大容量      r2 := rate2.NewBucket(time.Second, 200)      return func(ctx *gin.Context) {          //r2.Take() // 允許欠賬,令牌不夠也可以接收請(qǐng)求          if r2.TakeAvailable(1) == 1 {              // 如果想要取出1個(gè)令牌并且能夠取出,就放行              ctx.Next()              return          }          response(ctx, http.StatusRequestTimeout, "rate2 limit...")          ctx.Abort()          return      }  }
登錄后復(fù)制

一文聊聊go語言中的限流漏桶和令牌桶庫壓測(cè)速度過于快速,在實(shí)際過程中可以根據(jù)調(diào)整令牌生成速率來進(jìn)行具體限流!

小結(jié)

令牌桶可以允許自己判斷請(qǐng)求是否繼續(xù),內(nèi)部不會(huì)進(jìn)行睡眠操作。而漏桶需要進(jìn)行睡眠,并沒有提供方法讓程序員進(jìn)行判斷是否放行。

贊(0)
分享到: 更多 (0)
?
網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)
久久精品五月,日韩不卡视频在线观看,国产精品videossex久久发布 ,久久av综合
欧美日一区二区在线观看| 99成人在线| 亚洲另类av| 在线国产精品一区| 欧美有码在线| 国产中文在线播放| 国内精品99| 亚洲三区欧美一区国产二区| 日韩激情av在线| 麻豆视频观看网址久久| 日韩超碰人人爽人人做人人添| 国产色噜噜噜91在线精品| 久久一区欧美| 1000部精品久久久久久久久| 水蜜桃久久夜色精品一区的特点 | 欧美精品高清| 亚洲少妇自拍| 日韩av一区二区在线影视| 国产精品亚洲综合色区韩国 | 伊人久久高清| 亚洲一区二区成人| 日韩亚洲精品在线观看| 卡一卡二国产精品| 99久久精品费精品国产| 天堂va在线高清一区| 精品视频一区二区三区在线观看 | 日韩在线精品| 亚洲一区二区网站| 国产精品一区二区精品视频观看 | 精品国产一区二区三区2021| 欧美日韩高清| 国产精品视频首页| 蜜臀久久99精品久久一区二区| 午夜亚洲福利| 久久九九电影| 欧美一区影院| 伊人精品一区| 欧美精品福利| 国产二区精品| 国产精品天天看天天狠| 九色精品91| 久久精品国产久精国产爱| 91精品电影| 日本国产亚洲| 欧美粗暴jizz性欧美20| 国产精品自拍区| 一级欧洲+日本+国产| 国产视频网站一区二区三区| 欧美精品激情| 韩日一区二区| 日韩一二三区在线观看| 91精品精品| 狂野欧美性猛交xxxx| 一区二区高清| 欧美中文一区二区| 欧美激情日韩| 亚洲人成网站在线在线观看| 91亚洲国产| 日韩精品一区二区三区中文字幕| 久久午夜影院| 日韩国产91| 性一交一乱一区二区洋洋av| 国产精品毛片久久| 青青青国产精品| 亚洲欧美日本日韩| 久久麻豆精品| 91亚洲成人| 久久丁香四色| 久久国产三级精品| 亚洲精品少妇| 亚洲激情精品| 日本高清不卡一区二区三区视频| 国产精品国码视频| 在线综合亚洲| 亚洲午夜在线| 欧产日产国产精品视频| 欧美激情福利| 日韩不卡一二三区| 日日夜夜免费精品| 91视频一区| 国产视频网站一区二区三区| 久久精品国产99久久| 久久夜色精品| 日韩中文字幕亚洲一区二区va在线 | 国产亚洲一级| 欧美日韩免费看片| 久久亚洲精品中文字幕蜜潮电影| 伊人网在线播放| 国产91精品对白在线播放| 国产欧美一区二区三区精品酒店| 国产欧美日韩影院| 精品国产a一区二区三区v免费| 国产极品一区| 免费精品视频在线| 97在线精品| 噜噜噜躁狠狠躁狠狠精品视频| 韩日一区二区三区| 国产精品福利在线观看播放| 日韩欧美午夜| 国产精品欧美大片| 中文一区一区三区免费在线观 | 国产日韩欧美三区| 亚洲天堂一区二区| 日本免费在线视频不卡一不卡二| 蜜桃成人av| 美女视频一区在线观看| 欧美日韩免费观看视频| 久久黄色影视| 亚洲欧洲一区| 久久久精品区| 五月婷婷六月综合| 不卡一区综合视频| 国产欧美精品久久| 欧美精选一区二区三区| 欧洲亚洲一区二区三区| 久久久成人网| av中文字幕在线观看第一页| 精品中文字幕一区二区三区| 久久精品国语| 午夜日韩福利| 国产精品久久久久久久久久10秀| 99精品美女| 久久激情综合网| 亚洲精品乱码| 久久不见久久见国语| 亚洲高清不卡| 久久福利影视| 国产精品成人**免费视频| 欧美1区2区3| 日韩中文字幕av电影| 欧美日韩xxxx| 视频一区日韩精品| 日韩亚洲精品在线| 欧美aⅴ一区二区三区视频| 成人免费电影网址| 一本综合精品| 麻豆精品一区二区综合av| 99精品电影| 亚洲中午字幕| 99国产精品免费视频观看| 红桃视频国产一区| 黄色在线观看www| 国产人成精品一区二区三| 日本欧美不卡| 日韩欧美精品综合| 国产精品国产一区| 老司机免费视频一区二区三区| 欧美日一区二区在线观看| 深夜福利亚洲| 日韩高清在线不卡| 日韩动漫一区| 亚洲经典在线| 欧美午夜三级| 亚洲精品自拍| 综合激情视频| 欧美日中文字幕| 精品国产aⅴ| 91视频一区| 欧美特黄视频| 日本亚洲欧洲无免费码在线| 亚洲欧洲美洲国产香蕉| 日韩精品免费视频一区二区三区| 91精品福利| 麻豆国产精品一区二区三区| 91精品在线免费视频| 亚洲精品大全| 国产精品一区亚洲| 99久久99视频只有精品| 综合在线一区| 日韩国产一区二区| 国产麻豆精品久久| 99久久精品网站| 久久国产三级| 中文欧美日韩| av高清一区| 久久久久亚洲精品中文字幕| 日韩欧美中文字幕电影| а√天堂8资源在线| 99久久婷婷| 欧美日韩色图| 久久网站免费观看| 成人亚洲欧美| 日韩免费小视频| a天堂资源在线| 国产精品久久久久久久免费观看 | 亚洲天堂av影院| 日韩一区二区三区在线看| 国产精品久久观看| 亚洲第一精品影视| 日韩午夜电影| 久久久水蜜桃av免费网站| 欧美国产另类| 成人片免费看| 婷婷久久免费视频| 欧美精品一区二区三区精品| 国产精品最新自拍| 男女男精品视频网| 在线观看免费一区二区| 欧美日韩午夜| 蜜臀av性久久久久蜜臀aⅴ四虎 |