日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

阿里 双11 同款,流量防卫兵 Sentinel go 源码解读

發(fā)布時間:2025/3/20 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 阿里 双11 同款,流量防卫兵 Sentinel go 源码解读 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

作者 | 于雨? apache/dubbo-go 項目負(fù)責(zé)人

本文作者系 apache/dubbo-go 項目負(fù)責(zé)人,目前在 dubbogo 項目中已內(nèi)置可用 sentinel-go,如果想單獨使用可參考 在 dubbo-go 中使用 sentinel 一文,若有其他疑問可進(jìn) dubbogo社區(qū)【釘釘群 23331795】進(jìn)行溝通。

導(dǎo)讀:本文主要分析阿里巴巴集團(tuán)開源的流量控制中間件 Sentinel,其原生支持了 Java/Go/C++ 等多種語言,本文僅僅分析其 Go 語言實現(xiàn)。下文如無特殊說明,sentinel 指代 Sentinel-Go。

1 基本概念 Resource ?和 Rule

1.1 Resource

// ResourceType represents classification of the resourcestype ResourceType int32const (ResTypeCommon ResourceType = iotaResTypeWebResTypeRPC)// TrafficType describes the traffic type: Inbound or Outboundtype TrafficType int32const (// Inbound represents the inbound traffic (e.g. provider)Inbound TrafficType = iota// Outbound represents the outbound traffic (e.g. consumer)Outbound)// ResourceWrapper represents the invocationtype ResourceWrapper struct {// global unique resource namename string// resource classificationclassification ResourceType// Inbound or OutboundflowType TrafficType}

Resource(ResourceWrapper) 存儲了應(yīng)用場景 ResourceType,以及目標(biāo)流控的方向 FlowType(TrafficType)。

1.2 Entry

// EntryOptions represents the options of a Sentinel resource entry.type EntryOptions struct {resourceType base.ResourceTypeentryType base.TrafficTypeacquireCount uint32slotChain *base.SlotChain}type EntryContext struct {entry *SentinelEntry// Use to calculate RTstartTime uint64Resource *ResourceWrapperStatNode StatNodeInput *SentinelInput// the result of rule slots checkRuleCheckResult *TokenResult}type SentinelEntry struct {res *ResourceWrapper// one entry bounds with one contextctx *EntryContextsc *SlotChain}

Entry 實體 SentinelEntry 關(guān)聯(lián)了 Resource(ResourceWrapper) 以及其流控規(guī)則集合 SlotChain。每個 Entry 實體有一個上下文環(huán)境 EntryContext,存儲每個 Rule 檢測時用到的一些流控參數(shù)和流控判定結(jié)果。

值得注意的是,SentinelEntry.sc 值來自于 EntryOptions.slotChain,EntryOptions.slotChain 存儲了全局 SlotChain 對象 api/slot_chain.go:globalSlotChain。

至于何為 SlotChain,就是 sentinel 提供的所有的流控組件的集合,可以簡單地認(rèn)為每個流控組件就是一個 Slot,其詳細(xì)分析見[3.5 SlotChain]。

sentinel 一些變量和函數(shù)命名的可讀性較差,如 EntryOptions.acquireCount 實在無法讓人望文生義,看過函數(shù) core/api.go:WithAcquireCount() 的注釋才明白:EntryOptions.acquireCount 是批量動作執(zhí)行次數(shù)。如有的一次 RPC 請求中調(diào)用了服務(wù)端的一個服務(wù)接口,則取值 1【也是 EntryOptions.acquireCount 的默認(rèn)取值】,如果調(diào)用了服務(wù)端的 3 個服務(wù)接口,則取值 3。所以建議改名為 EntryOptions.batchCount 比較好,考慮到最小改動原則,可以在保留 core/api.go:WithAcquireCount() 的同時增加一個同樣功能的 core/api.go:WithBatchCount() 接口。相關(guān)改進(jìn)已經(jīng)提交到 ?pr 263。

1.3 Rule

type TokenCalculateStrategy int32const (Direct TokenCalculateStrategy = iotaWarmUp)type ControlBehavior int32const (Reject ControlBehavior = iotaThrottling)// Rule describes the strategy of flow control, the flow control strategy is based on QPS statistic metrictype Rule struct {// Resource represents the resource name.Resource string `json:"resource"`ControlBehavior ControlBehavior `json:"controlBehavior"`// Threshold means the threshold during StatIntervalInMs// If StatIntervalInMs is 1000(1 second), Threshold means QPSThreshold float64 `json:"threshold"`MaxQueueingTimeMs uint32 `json:"maxQueueingTimeMs"`// StatIntervalInMs indicates the statistic interval and it's the optional setting for flow Rule.// If user doesn't set StatIntervalInMs, that means using default metric statistic of resource.// If the StatIntervalInMs user specifies can not reuse the global statistic of resource,// sentinel will generate independent statistic structure for this rule.StatIntervalInMs uint32 `json:"statIntervalInMs"`}

Rule 記錄了某 Resource 的限流判定閾值 Threshold、限流時間窗口計時長度 StatIntervalInMs 以及 觸發(fā)限流后的判罰動作 ControlBehavior。

上面核心是 Rule 的接口 RuleCheckSlot,至于 StatSlot 則用于統(tǒng)計 sentinel 自身的運行 metrics。

1.4 Flow

當(dāng)前章節(jié)主要分析流控中的限流(core/flow),根據(jù)流控的處理流程梳理 sentinel 整體骨架。

1.4.1 TrafficShapingController

所謂 TrafficShapingController,顧名思義,就是 流量塑形控制器,是流控的具體實施者。

// core/flow/traffic_shaping.go// TrafficShapingCalculator calculates the actual traffic shaping threshold// based on the threshold of rule and the traffic shaping strategy.type TrafficShapingCalculator interface {CalculateAllowedTokens(acquireCount uint32, flag int32) float64}type DirectTrafficShapingCalculator struct {threshold float64}func (d *DirectTrafficShapingCalculator) CalculateAllowedTokens(uint32, int32) float64 {return d.threshold}

TrafficShapingCalculator 接口用于計算限流的上限,如果不使用 warm-up 功能,可以不去深究其實現(xiàn),其實體之一 DirectTrafficShapingCalculator 返回 Rule.Threshold【用戶設(shè)定的限流上限】。

// TrafficShapingChecker performs checking according to current metrics and the traffic// shaping strategy, then yield the token result.type TrafficShapingChecker interface {DoCheck(resStat base.StatNode, acquireCount uint32, threshold float64) *base.TokenResult}type RejectTrafficShapingChecker struct {rule *Rule}func (d *RejectTrafficShapingChecker) DoCheck(resStat base.StatNode, acquireCount uint32, threshold float64) *base.TokenResult {metricReadonlyStat := d.BoundOwner().boundStat.readOnlyMetricif metricReadonlyStat == nil {return nil}curCount := float64(metricReadonlyStat.GetSum(base.MetricEventPass))if curCount+float64(acquireCount) > threshold {return base.NewTokenResultBlockedWithCause(base.BlockTypeFlow, "", d.rule, curCount)}return nil}

RejectTrafficShapingChecker 依據(jù) Rule.Threshold 判定 Resource 在當(dāng)前時間窗口是否超限,其限流結(jié)果 TokenResultStatus 只可能是 Pass 或者 Blocked。

sentinel flow 還有一個勻速限流 ThrottlingChecker,它的目的是讓請求勻速被執(zhí)行,把一個時間窗口【譬如 1s】根據(jù) threshold 再細(xì)分為更細(xì)的微時間窗口,在每個微時間窗口最多執(zhí)行一次請求,其限流結(jié)果 TokenResultStatus 只可能是 Pass 或者 Blocked 或者 Wait,其相關(guān)意義分別為:

  • Pass:在微時間窗口內(nèi)無超限,請求通過;
  • Wait:在微時間窗口內(nèi)超限,被滯后若干時間窗口執(zhí)行,在這段時間內(nèi)請求需要等待;
  • Blocked:在微時間窗口內(nèi)超限,且等待時間超過用戶設(shè)定的最大愿意等待時間長度【Rule.MaxQueueingTimeMs】,請求被拒絕。
type TrafficShapingController struct {flowCalculator TrafficShapingCalculatorflowChecker TrafficShapingCheckerrule *Rule// boundStat is the statistic of current TrafficShapingControllerboundStat standaloneStatistic}func (t *TrafficShapingController) PerformChecking(acquireCount uint32, flag int32) *base.TokenResult {allowedTokens := t.flowCalculator.CalculateAllowedTokens(acquireCount, flag)return t.flowChecker.DoCheck(resStat, acquireCount, allowedTokens)}

在 Direct + Reject 限流的場景下,這三個接口其實并無多大意義,其核心函數(shù) TrafficShapingController.PerformChecking() 的主要流程是:

  • 1 ?從 TrafficShapingController.boundStat 中獲取當(dāng)前 Resource 的 metrics 值【curCount】;
  • 2 如果 curCount + batchNum(acquireCount) > Rule.Threshold,則 pass,否則就 reject。

在限流場景下, TrafficShapingController 四個成員的意義如下:

  • flowCalculator 計算限流上限;
  • flowChecker 執(zhí)行限流 Check 動作;
  • rule 存儲限流規(guī)則;
  • boundStat 存儲限流的 Check 結(jié)果和時間窗口參數(shù),作為下次限流 Check 動作判定的依據(jù)。

1.4.2 TrafficControllerMap

在執(zhí)行限流判定時,需要根據(jù) Resource 名稱獲取其對應(yīng)的 TrafficShapingController。

// TrafficControllerMap represents the map storage for TrafficShapingController.type TrafficControllerMap map[string][]*TrafficShapingController// core/flow/rule_manager.gotcMap = make(TrafficControllerMap)

package 級別全局私有變量 tcMap 存儲了所有的 Rule,其 key 為 Resource 名稱,value 則是與 Resource 對應(yīng)的 TrafficShapingController。

用戶級別接口函數(shù) core/flow/rule_manager.go:LoadRules() 會根據(jù)用戶定義的 Rule 構(gòu)造其對應(yīng)的 TrafficShapingController 存入 tcMap,這個接口調(diào)用函數(shù) generateStatFor(*Rule) 構(gòu)造 TrafficShapingController.boundStat。

限流場景下,函數(shù) generateStatFor(*Rule) 的核心代碼如下:

func generateStatFor(rule *Rule) (*standaloneStatistic, error) {resNode = stat.GetOrCreateResourceNode(rule.Resource, base.ResTypeCommon)// default case, use the resource's default statisticreadStat := resNode.DefaultMetric()retStat.reuseResourceStat = trueretStat.readOnlyMetric = readStatretStat.writeOnlyMetric = nilreturn &retStat, nil}

2 Metrics

Resource 的指標(biāo) Metrics 是進(jìn)行 Rule 判定的基礎(chǔ)。

2.1 原子時間輪 AtomicBucketWrapArray

Sentinel 庫功能豐富,但無論是限流還是熔斷,其存儲基礎(chǔ)都是滑動時間窗口。其間包含了眾多優(yōu)化:如無鎖定長時間輪。

滑動窗口實現(xiàn)有很多種,時間輪算法是其中一種比較簡單的實現(xiàn),在時間輪算法之上可以實現(xiàn)多種限流方法。時間輪整體框圖如下:

1 BucketWrap

時間輪的最基本單元是一個桶【時間窗口】。

// BucketWrap represent a slot to record metrics// In order to reduce the usage of memory, BucketWrap don't hold length of BucketWrap// The length of BucketWrap could be seen in LeapArray.// The scope of time is [startTime, startTime+bucketLength)// The size of BucketWrap is 24(8+16) bytestype BucketWrap struct {// The start timestamp of this statistic bucket wrapper.BucketStart uint64// The actual data structure to record the metrics (e.g. MetricBucket).Value atomic.Value}

補(bǔ)充:這里之所以用指針,是因為以 BucketWrap 為基礎(chǔ)的 AtomicBucketWrapArray 會被多個 sentinel 流控組件使用,每個組件的流控參數(shù)不一,例如:

  • 1 core/circuitbreaker/circuit_breaker.go:slowRtCircuitBreaker 使用的 slowRequestLeapArray 的底層參數(shù) slowRequestCounter
// core/circuitbreaker/circuit_breaker.gotype slowRequestCounter struct {slowCount uint64totalCount uint64}
  • 2 core/circuitbreaker/circuit_breaker.go:errorRatioCircuitBreaker 使用的 errorCounterLeapArray 的底層參數(shù) errorCounter
// core/circuitbreaker/circuit_breaker.gotype errorCounter struct {errorCount uint64totalCount uint64}

1.1 MetricBucket

BucketWrap 可以認(rèn)作是一種 時間桶模板,具體的桶的實體是 MetricsBucket,其定義如下:

// MetricBucket represents the entity to record metrics per minimum time unit (i.e. the bucket time span).// Note that all operations of the MetricBucket are required to be thread-safe.type MetricBucket struct {// Value of statisticcounter [base.MetricEventTotal]int64minRt int64}

MetricBucket 存儲了五種類型的 metric:

// There are five events to record// pass + block == Totalconst (// sentinel rules check passMetricEventPass MetricEvent = iota// sentinel rules check blockMetricEventBlockMetricEventComplete// Biz error, used for circuit breakerMetricEventError// request execute rt, unit is millisecondMetricEventRt// hack for the number of eventMetricEventTotal)

2 AtomicBucketWrapArray

每個桶只記錄了其起始時間和 metric 值,至于每個桶的時間窗口長度這種公共值則統(tǒng)一記錄在 AtomicBucketWrapArray 內(nèi),AtomicBucketWrapArray 定義如下:

// atomic BucketWrap array to resolve race condition// AtomicBucketWrapArray can not append or delete element after initializingtype AtomicBucketWrapArray struct {// The base address for real data arraybase unsafe.Pointer// The length of slice(array), it can not be modified.length intdata []*BucketWrap}

AtomicBucketWrapArray.base 的值是 AtomicBucketWrapArray.data slice 的 data 區(qū)域的首指針。因為 AtomicBucketWrapArray.data 是一個固定長度的 slice,所以 AtomicBucketWrapArray.base 直接存儲數(shù)據(jù)內(nèi)存區(qū)域的首地址,以加速訪問速度。

其次,AtomicBucketWrapArray.data 中存儲的是 BucketWrap 的指針,而不是 BucketWrap。

NewAtomicBucketWrapArrayWithTime() 函數(shù)會預(yù)熱一下,把所有的時間桶都生成出來。

2.2 時間輪

1 leapArray

// Give a diagram to illustrate// Suppose current time is 888, bucketLengthInMs is 200ms,// intervalInMs is 1000ms, LeapArray will build the below windows// B0 B1 B2 B3 B4// |_______|_______|_______|_______|_______|// 1000 1200 1400 1600 800 (1000)// ^// time=888type LeapArray struct {bucketLengthInMs uint32sampleCount uint32intervalInMs uint32array *AtomicBucketWrapArray// update lockupdateLock mutex}

LeapArray 各個成員解析:

  • bucketLengthInMs 是漏桶長度,以毫秒為單位;
  • sampleCount 則是時間漏桶個數(shù);
  • intervalInMs 是時間窗口長度,以毫秒為單位。

其注釋中的 ASCII 圖很好地解釋了每個字段的含義。

LeapArray 核心函數(shù)是 LeapArray.currentBucketOfTime(),其作用是根據(jù)某個時間點獲取其做對應(yīng)的時間桶 BucketWrap,代碼如下:

func (la *LeapArray) currentBucketOfTime(now uint64, bg BucketGenerator) (*BucketWrap, error) {if now <= 0 {return nil, errors.New("Current time is less than 0.")}idx := la.calculateTimeIdx(now)bucketStart := calculateStartTime(now, la.bucketLengthInMs)for { //spin to get the current BucketWrapold := la.array.get(idx)if old == nil {// because la.array.data had initiated when new la.array// theoretically, here is not reachablenewWrap := &BucketWrap{BucketStart: bucketStart,Value: atomic.Value{},}newWrap.Value.Store(bg.NewEmptyBucket())if la.array.compareAndSet(idx, nil, newWrap) {return newWrap, nil} else {runtime.Gosched()}} else if bucketStart == atomic.LoadUint64(&old.BucketStart) {return old, nil} else if bucketStart > atomic.LoadUint64(&old.BucketStart) {// current time has been next cycle of LeapArray and LeapArray dont't count in last cycle.// reset BucketWrapif la.updateLock.TryLock() {old = bg.ResetBucketTo(old, bucketStart)la.updateLock.Unlock()return old, nil} else {runtime.Gosched()}} else if bucketStart < atomic.LoadUint64(&old.BucketStart) {// TODO: reserve for some special case (e.g. when occupying "future" buckets).return nil, errors.New(fmt.Sprintf("Provided time timeMillis=%d is already behind old.BucketStart=%d.", bucketStart, old.BucketStart))}}}

其 for-loop 核心邏輯是:

  • 1 獲取時間點對應(yīng)的時間桶 old;
  • 2 如果 old 為空,則新建一個時間桶,以原子操作的方式嘗試存入時間窗口的時間輪中,存入失敗則重新嘗試;
  • 3 如果 old 就是當(dāng)前時間點所在的時間桶,則返回;
  • 4 如果 old 的時間起點小于當(dāng)前時間,則通過樂觀鎖嘗試 reset 桶的起始時間等參數(shù)值,加鎖更新成功則返回;
  • 5 如果 old 的時間起點大于當(dāng)前時間,則系統(tǒng)發(fā)生了時間扭曲,返回錯誤。

2 BucketLeapArray

leapArray 實現(xiàn)了滑動時間窗口的所有主體,其對外使用接口則是 BucketLeapArray:

// The implementation of sliding window based on LeapArray (as the sliding window infrastructure)// and MetricBucket (as the data type). The MetricBucket is used to record statistic// metrics per minimum time unit (i.e. the bucket time span).type BucketLeapArray struct {data LeapArraydataType string}

從這個 struct 的注釋可見,其時間窗口 BucketWrap 的實體是 MetricBucket。

2.3 Metric 數(shù)據(jù)讀寫

SlidingWindowMetric

// SlidingWindowMetric represents the sliding window metric wrapper.// It does not store any data and is the wrapper of BucketLeapArray to adapt to different internal bucket// SlidingWindowMetric is used for SentinelRules and BucketLeapArray is used for monitor// BucketLeapArray is per resource, and SlidingWindowMetric support only read operation.type SlidingWindowMetric struct {bucketLengthInMs uint32sampleCount uint32intervalInMs uint32real *BucketLeapArray}

SlidingWindowMetric 是對 BucketLeapArray 的一個封裝,只提供了只讀接口。

ResourceNode

type BaseStatNode struct {sampleCount uint32intervalMs uint32goroutineNum int32arr *sbase.BucketLeapArraymetric *sbase.SlidingWindowMetric}type ResourceNode struct {BaseStatNoderesourceName stringresourceType base.ResourceType}// core/stat/node_storage.gotype ResourceNodeMap map[string]*ResourceNodevar (inboundNode = NewResourceNode(base.TotalInBoundResourceName, base.ResTypeCommon)resNodeMap = make(ResourceNodeMap)rnsMux = new(sync.RWMutex))

BaseStatNode 對外提供了讀寫接口,其數(shù)據(jù)寫入 BaseStatNode.arr,讀取接口則依賴 BaseStatNode.metric。BaseStatNode.arr 是在 NewBaseStatNode() 中創(chuàng)建的,指針 SlidingWindowMetric.real 也指向它。

ResourceNode 則顧名思義,其代表了某資源和它的 Metrics 存儲 ?ResourceNode.BaseStatNode。

全局變量 resNodeMap 存儲了所有資源的 Metrics 指標(biāo)數(shù)據(jù)。

3 限流流程

本節(jié)只分析 Sentinel 庫提供的最基礎(chǔ)的流量整形功能 – 限流,限流算法多種多樣,可以使用其內(nèi)置的算法,用戶自己也可以進(jìn)行擴(kuò)展。

限流過程有三步步驟:

  • 1 針對特定 Resource 構(gòu)造其 EntryContext,存儲其 Metrics、限流開始時間等,Sentinel 稱之為 StatPrepareSlot;
  • 2 依據(jù) Resource 的限流算法判定其是否應(yīng)該進(jìn)行限流,并給出限流判定結(jié)果,Sentinel 稱之為 RuleCheckSlot;
    • 補(bǔ)充:這個限流算法是一系列判斷方法的合集(SlotChain);
  • 3 判定之后,除了用戶自身根據(jù)判定結(jié)果執(zhí)行相應(yīng)的 action,Sentinel 也需要根據(jù)判定結(jié)果執(zhí)行自身的 Action,以及把整個判定流程所使用的的時間 RT 等指標(biāo)存儲下來,Sentinel 稱之為 StatSlot。

整體流程如下圖所示:

3.1 Slot

針對 Check 三個步驟,有三個對應(yīng)的 Slot 分別定義如下:

// StatPrepareSlot is responsible for some preparation before statistic// For example: init structure and so ontype StatPrepareSlot interface {// Prepare function do some initialization// Such as: init statistic structure、node and etc// The result of preparing would store in EntryContext// All StatPrepareSlots execute in sequence// Prepare function should not throw panic.Prepare(ctx *EntryContext)}// RuleCheckSlot is rule based checking strategy// All checking rule must implement this interface.type RuleCheckSlot interface {// Check function do some validation// It can break off the slot pipeline// Each TokenResult will return check result// The upper logic will control pipeline according to SlotResult.Check(ctx *EntryContext) *TokenResult}// StatSlot is responsible for counting all custom biz metrics.// StatSlot would not handle any panic, and pass up all panic to slot chaintype StatSlot interface {// OnEntryPass function will be invoked when StatPrepareSlots and RuleCheckSlots execute pass// StatSlots will do some statistic logic, such as QPS、log、etcOnEntryPassed(ctx *EntryContext)// OnEntryBlocked function will be invoked when StatPrepareSlots and RuleCheckSlots fail to execute// It may be inbound flow control or outbound cir// StatSlots will do some statistic logic, such as QPS、log、etc// blockError introduce the block detailOnEntryBlocked(ctx *EntryContext, blockError *BlockError)// OnCompleted function will be invoked when chain exits.// The semantics of OnCompleted is the entry passed and completed// Note: blocked entry will not call this functionOnCompleted(ctx *EntryContext)}

拋卻 Prepare 和 Stat,可以簡單的認(rèn)為:所謂的 slot,就是 sentinel 提供的某個流控組件。

值得注意的是,根據(jù)注釋 StatSlot.OnCompleted 只有在 RuleCheckSlot.Check 通過才會執(zhí)行,用于計算從請求開始到結(jié)束所使用的 RT 等 Metrics。

3.2 Prepare

// core/base/slot_chain.go// StatPrepareSlot is responsible for some preparation before statistic// For example: init structure and so ontype StatPrepareSlot interface {// Prepare function do some initialization// Such as: init statistic structure、node and etc// The result of preparing would store in EntryContext// All StatPrepareSlots execute in sequence// Prepare function should not throw panic.Prepare(ctx *EntryContext)}// core/stat/stat_prepare_slot.gotype ResourceNodePrepareSlot struct {}func (s *ResourceNodePrepareSlot) Prepare(ctx *base.EntryContext) {node := GetOrCreateResourceNode(ctx.Resource.Name(), ctx.Resource.Classification())// Set the resource node to the context.ctx.StatNode = node}

如前面解釋,Prepare 主要是構(gòu)造存儲 Resource Metrics 所使用的 ResourceNode。所有 Resource 的 StatNode 都會存儲在 package 級別的全局變量 core/stat/node_storage.go:resNodeMap [type: map[string]*ResourceNode] 中,函數(shù) GetOrCreateResourceNode 用于根據(jù) Resource Name 從 resNodeMap 中獲取其對應(yīng)的 StatNode,如果不存在則創(chuàng)建一個 StatNode 并存入 resNodeMap。

3.3 Check

RuleCheckSlot.Check() 執(zhí)行流程:

  • 1 根據(jù) Resource 名稱獲取其所有的 Rule 集合;
  • 2 遍歷 Rule 集合,對 Resource 依次執(zhí)行 Check,任何一個 Rule 判定 Resource 需要進(jìn)行限流【Blocked】則返回,否則放行。
type Slot struct {}func (s *Slot) Check(ctx *base.EntryContext) *base.TokenResult {res := ctx.Resource.Name()tcs := getTrafficControllerListFor(res)result := ctx.RuleCheckResult// Check rules in orderfor _, tc := range tcs {r := canPassCheck(tc, ctx.StatNode, ctx.Input.AcquireCount)if r == nil {// nil means passcontinue}if r.Status() == base.ResultStatusBlocked {return r}if r.Status() == base.ResultStatusShouldWait {if waitMs := r.WaitMs(); waitMs > 0 {// Handle waiting action.time.Sleep(time.Duration(waitMs) * time.Millisecond)}continue}}return result}func canPassCheck(tc *TrafficShapingController, node base.StatNode, acquireCount uint32) *base.TokenResult {return canPassCheckWithFlag(tc, node, acquireCount, 0)}func canPassCheckWithFlag(tc *TrafficShapingController, node base.StatNode, acquireCount uint32, flag int32) *base.TokenResult {return checkInLocal(tc, node, acquireCount, flag)}func checkInLocal(tc *TrafficShapingController, resStat base.StatNode, acquireCount uint32, flag int32) *base.TokenResult {return tc.PerformChecking(resStat, acquireCount, flag)}

3.4 Exit

sentinel 對 Resource 進(jìn)行 Check 后,其后續(xù)邏輯執(zhí)行順序是:

  • 1 如果 RuleCheckSlot.Check() 判定 pass 通過則執(zhí)行 StatSlot.OnEntryPassed(),否則 RuleCheckSlot.Check() 判定 reject 則執(zhí)行 StatSlot.OnEntryBlocked();
  • 2 如果 RuleCheckSlot.Check() 判定 pass 通過,則執(zhí)行本次 Action;
  • 3 如果 RuleCheckSlot.Check() 判定 pass 通過,則執(zhí)行 SentinelEntry.Exit() --> SlotChain.ext() --> StatSlot.OnCompleted() 。

第三步驟的調(diào)用鏈路如下:

StatSlot.OnCompleted()

// core/flow/standalone_stat_slot.gotype StandaloneStatSlot struct {}func (s StandaloneStatSlot) OnEntryPassed(ctx *base.EntryContext) {res := ctx.Resource.Name()for _, tc := range getTrafficControllerListFor(res) {if !tc.boundStat.reuseResourceStat {if tc.boundStat.writeOnlyMetric != nil {tc.boundStat.writeOnlyMetric.AddCount(base.MetricEventPass, int64(ctx.Input.AcquireCount))}}}}func (s StandaloneStatSlot) OnEntryBlocked(ctx *base.EntryContext, blockError *base.BlockError) {// Do nothing}func (s StandaloneStatSlot) OnCompleted(ctx *base.EntryContext) {// Do nothing}

SlotChain.exit()

// core/base/slot_chain.gotype SlotChain struct {}func (sc *SlotChain) exit(ctx *EntryContext) {// The OnCompleted is called only when entry passedif ctx.IsBlocked() {return}for _, s := range sc.stats {s.OnCompleted(ctx)}}

SentinelEntry.Exit()

// core/base/entry.gotype SentinelEntry struct {sc *SlotChainexitCtl sync.Once}func (e *SentinelEntry) Exit() {e.exitCtl.Do(func() {if e.sc != nil {e.sc.exit(ctx)}})}

從上面執(zhí)行可見,StatSlot.OnCompleted() 是在 Action 【如一次 RPC 的請求-響應(yīng) Invokation】完成之后調(diào)用的。如果有的組件需要計算一次 Action 的時間耗費 ?RT,就在其對應(yīng)的 StatSlot.OnCompleted() 中依據(jù) EntryContext.startTime 完成時間耗費計算。

3.5 SlotChain

Sentinel 本質(zhì)是一個流控包,不僅提供了限流功能,還提供了眾多其他諸如自適應(yīng)流量保護(hù)、熔斷降級、冷啟動、全局流量 Metrics 結(jié)果等功能流控組件,Sentinel-Go 包定義了一個 SlotChain 實體存儲其所有的流控組件。

// core/base/slot_chain.go// SlotChain hold all system slots and customized slot.// SlotChain support plug-in slots developed by developer.type SlotChain struct {statPres []StatPrepareSlotruleChecks []RuleCheckSlotstats []StatSlot}// The entrance of slot chain// Return the TokenResult and nil if internal panic.func (sc *SlotChain) Entry(ctx *EntryContext) *TokenResult {// execute prepare slotsps := sc.statPresif len(sps) > 0 {for _, s := range sps {s.Prepare(ctx)}}// execute rule based checking slotrcs := sc.ruleChecksvar ruleCheckRet *TokenResultif len(rcs) > 0 {for _, s := range rcs {sr := s.Check(ctx)if sr == nil {// nil equals to check passcontinue}// check slot resultif sr.IsBlocked() {ruleCheckRet = srbreak}}}if ruleCheckRet == nil {ctx.RuleCheckResult.ResetToPass()} else {ctx.RuleCheckResult = ruleCheckRet}// execute statistic slotss := sc.statsruleCheckRet = ctx.RuleCheckResultif len(ss) > 0 {for _, s := range ss {// indicate the result of rule based checking slot.if !ruleCheckRet.IsBlocked() {s.OnEntryPassed(ctx)} else {// The block error should not be nil.s.OnEntryBlocked(ctx, ruleCheckRet.blockErr)}}}return ruleCheckRet}func (sc *SlotChain) exit(ctx *EntryContext) {if ctx == nil || ctx.Entry() == nil {logging.Error(errors.New("nil EntryContext or SentinelEntry"), "")return}// The OnCompleted is called only when entry passedif ctx.IsBlocked() {return}for _, s := range sc.stats {s.OnCompleted(ctx)}// relieve the context here}

建議:Sentinel 包針對某個 Resource 無法確知其使用了那個組件,在運行時會針對某個 Resource 的 EntryContext 依次執(zhí)行所有的組件的 Rule。Sentinel-golang 為何不給用戶相關(guān)用戶提供一個接口讓其設(shè)置使用的流控組件集合,以減少下面函數(shù) SlotChain.Entry() 中執(zhí)行 RuleCheckSlot.Check() 執(zhí)行次數(shù)?相關(guān)改進(jìn)已經(jīng)提交到 pr 264【補(bǔ)充,代碼已合并,據(jù)負(fù)責(zé)人壓測后回復(fù) sentinel-go 效率整體提升 15%】。

globalSlotChain

Sentinel-Go 定義了一個 SlotChain 的 package 級別的全局私有變量 globalSlotChain 用于存儲其所有的流控組件對象。相關(guān)代碼示例如下。因本文只關(guān)注限流組件,所以下面只給出了限流組件的注冊代碼。

// api/slot_chain.gofunc BuildDefaultSlotChain() *base.SlotChain {sc := base.NewSlotChain()sc.AddStatPrepareSlotLast(&stat.ResourceNodePrepareSlot{})sc.AddRuleCheckSlotLast(&flow.Slot{})sc.AddStatSlotLast(&flow.StandaloneStatSlot{})return sc}var globalSlotChain = BuildDefaultSlotChain()

Entry

在 Sentinel-Go 對外的最重要的入口函數(shù) api/api.go:Entry() 中,globalSlotChain 會作為 EntryOptions 的 SlotChain 參數(shù)被使用。

// api/api.go// Entry is the basic API of Sentinel.func Entry(resource string, opts ...EntryOption) (*base.SentinelEntry, *base.BlockError) {options := entryOptsPool.Get().(*EntryOptions)options.slotChain = globalSlotChainreturn entry(resource, options)}

Sentinel 的演進(jìn)離不開社區(qū)的貢獻(xiàn)。Sentinel Go 1.0 GA 版本即將在近期發(fā)布,帶來更多云原生相關(guān)的特性。我們非常歡迎感興趣的開發(fā)者參與貢獻(xiàn),一起來主導(dǎo)未來版本的演進(jìn)。我們鼓勵任何形式的貢獻(xiàn),包括但不限于:

? bug fix
? new features/improvements
? dashboard
? document/website
? test cases

開發(fā)者可以在 GitHub 上面的 good first issue 列表上挑選感興趣的 issue 來參與討論和貢獻(xiàn)。我們會重點關(guān)注積極參與貢獻(xiàn)的開發(fā)者,核心貢獻(xiàn)者會提名為 Committer,一起主導(dǎo)社區(qū)的發(fā)展。我們也歡迎大家有任何問題和建議,都可以通過 GitHub issue、Gitter 或釘釘群(群號:30150716)等渠道進(jìn)行交流。Now start hacking!

? Sentinel Go repo: https://github.com/alibaba/sentinel-golang
? 企業(yè)用戶歡迎進(jìn)行登記:https://github.com/alibaba/Sentinel/issues/18

作者簡介

于雨(github @AlexStocks),apache/dubbo-go 項目負(fù)責(zé)人,一個有十多年服務(wù)端基礎(chǔ)架構(gòu)研發(fā)一線工作經(jīng)驗的程序員,目前在螞蟻金服可信原生部從事容器編排和 service mesh 工作。熱愛開源,從 2015 年給 Redis 貢獻(xiàn)代碼開始,陸續(xù)改進(jìn)過 Muduo/Pika/Dubbo/Dubbo-go 等知名項目。

“阿里巴巴云原生關(guān)注微服務(wù)、Serverless、容器、Service Mesh 等技術(shù)領(lǐng)域、聚焦云原生流行技術(shù)趨勢、云原生大規(guī)模的落地實踐,做最懂云原生開發(fā)者的公眾號。”

總結(jié)

以上是生活随笔為你收集整理的阿里 双11 同款,流量防卫兵 Sentinel go 源码解读的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

日韩毛片一区 | 激情大尺度视频 | 超碰在线人 | 国产精品福利午夜在线观看 | 四虎永久网站 | 三级av网站 | 国产精品久久久久9999吃药 | 亚洲视频免费在线看 | av在线网站大全 | 久草在线资源网 | 久久久久国产a免费观看rela | 亚洲精品av中文字幕在线在线 | 国产在线观看a | 日韩手机视频 | 亚洲国产免费 | 99人成在线观看视频 | av在线超碰 | 国产一区二区精品久久 | 91丨九色丨高潮丰满 | 夜夜高潮夜夜爽国产伦精品 | 国产成人精品亚洲a | 国内丰满少妇猛烈精品播 | 国产一区在线看 | 超碰成人免费电影 | 国产一区网址 | 91人人干| 国产探花视频在线播放 | 国产黄 | 一区av在线播放 | 六月激情网| 亚洲精品国偷拍自产在线观看蜜桃 | 久草在线观 | 免费高清av在线看 | 激情综合网天天干 | 国产资源站 | 国产99久久久欧美黑人 | 久久综合毛片 | 日韩三级免费观看 | 免费久草视频 | 五月天亚洲激情 | 天天爱天天射天天干天天 | 日韩av中文在线 | 久久无码av一区二区三区电影网 | 综合久久精品 | 97超碰色偷偷 | 亚洲精品在线一区二区三区 | 国产在线播放观看 | 亚洲闷骚少妇在线观看网站 | 免费av观看网站 | 亚洲精品欧美视频 | 欧美精品一区二区在线观看 | 亚洲视频每日更新 | 国产精品久久久久久久久久久免费看 | 精品亚洲va在线va天堂资源站 | 亚洲精品视频在线免费播放 | 欧美日本不卡高清 | 国产精品99久久久久 | 97av视频 | 91超级碰 | 中文字幕av一区二区三区四区 | 国产小视频精品 | 一级黄色片在线免费观看 | 久在线观看视频 | 狠狠久久 | 午夜久久久久久久久久久 | 免费韩国av| 欧美日韩电影在线播放 | 一本一本久久a久久精品综合 | 免费在线91| 欧美日韩不卡在线视频 | 深爱激情开心 | 国产手机视频在线观看 | 精品久久久久久久久久久院品网 | 亚洲精品国产自产拍在线观看 | 中文字幕亚洲综合久久五月天色无吗'' | 国产精品女视频 | 久久精品一区二区三区四区 | 亚洲黄色免费 | 国色天香永久免费 | 高清av免费观看 | 国产不卡网站 | 五月天激情视频 | 中文字幕视频免费观看 | 国产精品少妇 | 欧美一区,二区 | 欧美激情综合色 | 婷婷激情影院 | 日本二区三区在线 | 91在线国内视频 | 免费看三片 | 中文字幕在线播放日韩 | 国产不卡视频在线 | 亚洲国产中文字幕在线 | 久久99国产一区二区三区 | 伊人在线视频 | 91视频啪| 日韩精品一区二区久久 | 天天做综合网 | wwwav视频| 97在线视频观看 | 制服丝袜在线91 | 美女视频黄色免费 | 欧美综合在线观看 | 日韩专区av | 婷婷在线免费视频 | 亚州天堂 | 九九爱免费视频 | 国产免费区 | 日产中文字幕 | 亚洲五月激情 | 国产亚洲精品久久久久久移动网络 | 国产一区精品在线 | 欧美日韩国产精品爽爽 | 亚洲电影自拍 | 欧美日韩不卡在线视频 | 日韩视频在线一区 | 久久99精品久久久久久秒播蜜臀 | 97碰碰精品嫩模在线播放 | 国产高清日韩 | 国产一区视频导航 | 深爱五月激情五月 | 日韩精品一区二区在线视频 | 国产va在线 | 特级免费毛片 | 精品成人在线 | 手机成人免费视频 | 999男人的天堂 | 国产91成人在在线播放 | 天天综合网久久综合网 | 精品999在线观看 | 91人人爽人人爽人人精88v | 天天操天天爽天天干 | 亚洲视频在线观看网站 | 国产精品日韩 | 亚洲永久精品一区 | 国产又粗又猛又爽又黄的视频免费 | 国产精品毛片久久久久久 | 国产粉嫩在线观看 | 日日干日日 | av成人免费观看 | 99久久久久久久久 | 免费黄色看片 | 国产1区2区3区精品美女 | 久久久久国产精品午夜一区 | 成人影片免费 | 人人爱在线视频 | 国产精品一区二区免费在线观看 | 免费成人在线网站 | 久久久久久久久黄色 | 视频一区亚洲 | 国产精品免费观看视频 | 日韩精品最新在线观看 | 日韩在线播放av | 午夜精品久久久久久久99 | 国色天香永久免费 | 夜夜躁狠狠躁日日躁视频黑人 | 在线视频婷婷 | 福利视频区 | 国产午夜精品福利视频 | 久久久久国产精品厨房 | 日本精品中文字幕在线观看 | 亚洲欧美日韩一区二区三区在线观看 | 国产精品美女久久久久久网站 | 久久人91精品久久久久久不卡 | 婷婷狠狠操 | 免费成人短视频 | 国产精品高潮呻吟久久av无 | 97超碰在线久草超碰在线观看 | 欧美日韩国产一区二区在线观看 | 欧洲精品在线视频 | 天天做天天爱夜夜爽 | 毛片播放网站 | 91传媒免费在线观看 | 97av.com| 国产精品96久久久久久吹潮 | 成人av免费在线观看 | 日本bbbb摸bbbb| 国产精品久久精品 | 狠色狠色综合久久 | 五月婷婷在线观看 | a级黄色片视频 | av线上看 | 日韩在线观看你懂得 | 黄色影院在线免费观看 | 久久免费电影网 | 中文字幕 国产视频 | 激情视频在线高清看 | 久久综合偷偷噜噜噜色 | 婷婷网站天天婷婷网站 | 香蕉视频日本 | av中文字幕在线播放 | 91中文字幕在线视频 | 成人精品一区二区三区电影免费 | 精品黄色在线 | av网站地址| 日韩av一区二区三区在线观看 | 一本到在线 | 欧美日韩裸体免费视频 | 日韩成人高清在线 | 国产精品自产拍在线观看中文 | 有码视频在线观看 | 天堂在线一区二区 | 在线免费黄色 | 精品在线小视频 | 黄污污网站 | 狠狠的操狠狠的干 | 久久一二三四 | 日韩精品久久久久久中文字幕8 | 国产精品久久久精品 | 波多野结衣一区三区 | 91av原创| 玖玖视频精品 | 欧美国产一区二区 | 久久亚洲人 | 最近最新中文字幕 | 亚洲国产成人精品电影在线观看 | 亚洲精品小视频在线观看 | 国产亚洲欧洲 | 久九视频| 亚洲成av人片 | 五月天久久婷 | 免费十分钟 | 中文字幕免费高清av | 久久精品看| 亚洲激情精品 | 日韩理论在线观看 | 色偷偷人人澡久久超碰69 | 亚洲免费精品视频 | 狠狠干综合 | 国产亚洲精品综合一区91 | 亚洲精品一区二区网址 | 九九热国产视频 | 久草视频在线资源 | 亚州精品在线视频 | av在线免费在线 | 91中文字幕在线观看 | 中文字幕一区二区三区在线播放 | 成x99人av在线www | 亚洲福利精品 | 奇米影音四色 | 一区二区三区精品久久久 | 色婷婷亚洲 | 一区二区视频在线免费观看 | 99久久日韩精品免费热麻豆美女 | 91香蕉视频黄色 | 久久久久久久久久久免费视频 | 免费在线观看av片 | 国产99精品 | 狠狠色丁香久久婷婷综合丁香 | 欧美做受高潮1 | 毛片永久新网址首页 | 精品 一区 在线 | 在线观看mv的中文字幕网站 | 一区二区三区四区免费视频 | 综合久久综合久久 | 在线观看免费成人 | 日韩精品 在线视频 | 国产精品久久久久久久久免费看 | av电影中文字幕在线观看 | 久久成人国产 | 国产二区视频在线 | 亚洲人成免费 | 免费福利在线 | 97国产情侣爱久久免费观看 | 综合精品在线 | 97电院网手机版 | 久草视频免费在线播放 | 天天艹天天 | 在线精品观看国产 | 91精品免费看 | 狠狠操操操 | 香蕉视频网址 | 国产无限资源在线观看 | 精品国产一区二区三区蜜臀 | 国产91免费观看 | 999久久久免费视频 午夜国产在线观看 | 国语精品久久 | 成人在线观看日韩 | 在线观看国产www | 99福利片 | 欧美日韩精品在线视频 | 在线观看免费av网 | 成人国产精品免费 | 国产精品久久久久永久免费看 | 久操视频在线观看 | 久久看免费视频 | 成人在线视频免费观看 | 香蕉在线播放 | 九九色视频 | 日韩精品aaa | 中文字幕日本在线 | 久久久久 免费视频 | 日韩手机视频 | 国产在线永久 | 中文字幕综合在线 | 中文字幕美女免费在线 | 日韩av资源在线观看 | www.av中文字幕.com | 久久99视频精品 | 久久一区二区三区超碰国产精品 | 国产人成一区二区三区影院 | 日韩91av | 91免费观看视频网站 | 久人人 | 午夜视频久久久 | 香蕉精品视频在线观看 | 国产精品久久久久av | 国产精品区在线观看 | 日韩三级在线观看 | 日日夜夜av| 久久国产成人午夜av影院潦草 | 久久99精品久久久久久秒播蜜臀 | 国产精品福利在线观看 | 久久最新| 欧美一级在线看 | 美女视频免费精品 | 国产精品福利在线 | 久久久国产一区 | 欧美日韩一二三四区 | 91在线视频| 日本精品久久久久影院 | 超碰999| av在线播放网址 | av软件在线观看 | 一区二区精品在线观看 | 美女网站在线看 | 天天操比 | 成人中文字幕在线观看 | 又湿又紧又大又爽a视频国产 | 日韩欧美v | 国产美女黄网站免费 | 国产美女视频免费观看的网站 | 在线观看色网站 | 欧美永久视频 | 国产福利一区二区在线 | 最近中文字幕mv免费高清在线 | 中文字幕有码在线 | 欧美专区国产专区 | 91香蕉视频720p | 伊人五月天婷婷 | 99精品视频在线观看 | 国产黑丝一区二区 | 天堂在线成人 | 精品中文字幕在线 | 欧美日本三级 | av综合站 | 91av中文 | 国产91精品在线播放 | 亚洲视频一级 | 91桃色国产在线播放 | 在线看毛片网站 | 中文字幕在线视频网站 | 欧美视频xxx | 国产视频日韩视频欧美视频 | 久久亚洲婷婷 | 成人av在线直播 | 激情婷婷综合网 | 欧美精品一区二区三区四区在线 | 天天综合网天天综合色 | 四虎国产精品成人免费影视 | 亚洲区精品视频 | 久久久久欧美精品999 | 99视频国产在线 | 日韩动漫免费观看高清完整版在线观看 | 久久久久在线 | 久久久免费观看完整版 | 国产精品电影一区二区 | 在线导航av | 亚洲电影自拍 | 国产特级毛片aaaaaa毛片 | 精品欧美一区二区精品久久 | 日本特黄一级 | 欧美色图亚洲图片 | 欧美日韩中字 | 亚洲精品影视在线观看 | 麻豆国产精品va在线观看不卡 | 激情五月婷婷丁香 | 国产又粗又猛又黄视频 | 麻花豆传媒mv在线观看网站 | 国产日本亚洲高清 | 国产手机av | 黄色免费av | 欧美日韩视频观看 | 97精品电影院| 久免费 | 国内精品久久久久久久影视麻豆 | 欧美一区二区三区在线视频观看 | 五月天六月婷婷 | 久久夜色精品国产欧美一区麻豆 | 激情综合中文娱乐网 | 欧美日韩视频一区二区 | 国产99久久久国产精品 | 国产精品自在线拍国产 | 日日夜夜骑 | 波多野结衣电影久久 | 丁香狠狠 | 国产久视频 | 黄色的视频| 国产亚洲婷婷免费 | 久久精品欧美日韩精品 | 97香蕉超级碰碰久久免费软件 | 中文超碰字幕 | 天天躁日日 | 欧美少妇18p| 波多野结衣一区二区三区中文字幕 | 亚洲国产欧美在线人成大黄瓜 | 97超碰国产精品 | 天堂在线视频免费观看 | 丁香影院在线 | 国产精品一区二区久久精品爱微奶 | 精品国产伦一区二区三区观看体验 | 亚洲精品在线一区二区三区 | 欧美一级艳片视频免费观看 | 日韩视频一区二区在线 | 亚洲精品黄色在线观看 | 亚洲精品系列 | 久久精品国产成人 | se婷婷| 久久综合九色欧美综合狠狠 | 蜜桃麻豆www久久囤产精品 | 久草精品视频在线播放 | 亚洲国产精品久久久 | 国产麻豆成人传媒免费观看 | 午夜精品久久久久久久久久久久久久 | 91高清免费| 日韩在线观看中文 | 国产精品99久久久久久武松影视 | 插婷婷 | 国产精品a久久久久 | 一级成人免费视频 | 最新日本中文字幕 | 丰满少妇在线观看 | 免费av在线| 最近中文字幕免费大全 | 美女视频a美女大全免费下载蜜臀 | 久久免费看| 久久久99国产精品免费 | 天天天综合 | 久久美女精品 | 夜夜夜夜猛噜噜噜噜噜初音未来 | 在线激情影院一区 | 国产3p视频 | 亚洲国产精品一区二区久久hs | 亚洲狠狠婷婷综合久久久 | 伊人成人精品 | 91激情视频在线 | 日韩二区在线观看 | 中文字幕成人av | 国产精品五月天 | 国产91在 | 精品av网站 | 久久久久亚洲精品 | 国产91精品一区二区麻豆网站 | 欧美激情视频一二区 | www黄色 | 最近中文字幕大全中文字幕免费 | 中文字幕久久精品亚洲乱码 | 国语对白少妇爽91 | 亚洲激情网站免费观看 | 中文字幕一区在线观看视频 | 97视频在线观看视频免费视频 | 丁香免费视频 | 中文字幕在线观看国产 | 日韩v欧美v日本v亚洲v国产v | 黄色av电影| 久久婷亚洲五月一区天天躁 | 亚洲精品男人的天堂 | 91网页版免费观看 | 国产精品久久艹 | 九九综合九九 | 国产精品白浆视频 | 国产精品一区二区三区免费视频 | 黄色福利网 | 国产精品手机在线观看 | 久久久麻豆 | 色五月激情五月 | 91成人免费在线 | 国产黄色美女 | 手机看片国产 | 天天综合网~永久入口 | 亚洲精品中文字幕在线观看 | 综合黄色网 | 狠狠色丁香婷婷综合 | 久久精品99国产 | 中文字幕av一区二区三区四区 | 免费国产在线视频 | 亚洲综合色网站 | 国产成人专区 | 国产区精品视频 | 中文字幕av日韩 | 亚洲一区二区三区在线看 | 国产精品乱看 | 久久精品美女视频 | 五月天婷亚洲天综合网精品偷 | 国产免费人成xvideos视频 | 91高清免费 | 97国产超碰 | 久久国产精品免费观看 | 99精品视频网站 | 欧美在线视频二区 | 免费影视大全推荐 | 最新日韩精品 | av片一区 | 欧美99精品 | 久草在线中文888 | 亚洲精品午夜国产va久久成人 | 视频在线国产 | 久久1区| 国产少妇在线观看 | 久草在线欧美 | 亚洲九九九在线观看 | 13日本xxxxxⅹxxx20| 黄污网 | 丝袜制服天堂 | av福利在线播放 | 97电影在线| 精品视频区 | 2021av在线 | 精品美女在线观看 | 国产一级精品在线观看 | 国产一级性生活 | 亚在线播放中文视频 | 日韩xxxbbb | 黄色三级免费网址 | 久久国产精品免费看 | 色婷婷综合久久久久中文字幕1 | 国产玖玖在线 | 中文字幕高清在线 | 国产高清久久久久 | 欧美一性一交一乱 | 午夜精品久久久久久 | 99高清视频有精品视频 | 久99久久| 精品一区二区三区四区在线 | 成人av一级片| 日本不卡123 | 91精品视频免费看 | 日韩理论在线播放 | 色a综合| 久久精品久久久久久久 | 午夜神马福利 | 99精品欧美一区二区三区黑人哦 | 久久福利综合 | 中文字幕在线观看播放 | 五月天婷亚洲天综合网精品偷 | 99综合久久| 九色91在线 | 99麻豆视频| 亚洲一级黄色 | 中文字幕观看在线 | 欧美日韩高清在线一区 | 91免费看片黄 | 亚洲涩涩涩涩涩涩 | 精品xxx | 高清免费在线视频 | 91精品国产乱码久久桃 | 欧美大片在线看免费观看 | 色在线网站 | 亚洲在线视频免费观看 | 成人黄色毛片视频 | 亚洲精品88欧美一区二区 | 国产精品久久网站 | 国产一区二区高清视频 | 亚洲天堂在线观看完整版 | 韩国一区二区三区视频 | 亚洲91精品| 国产精品福利在线观看 | 91亚洲精品国偷拍 | 国产免费国产 | 久久夜色精品亚洲噜噜国4 午夜视频在线观看欧美 | 久久九九影视 | 成+人+色综合 | 国产亚洲精品久久久久秋 | 色久综合 | 国产成人久久精品一区二区三区 | 狠狠干天天操 | 天天综合视频在线观看 | 日日干狠狠操 | www亚洲一区| www.av免费| 伊人资源视频在线 | 久99久在线视频 | 婷五月天激情 | 一区二区三区精品在线 | 麻豆国产精品视频 | 一区二区三区高清在线观看 | 五月天亚洲精品 | 精品国产欧美一区二区 | 国产不卡在线观看 | 超碰97国产精品人人cao | av成人亚洲 | 丁香网五月天 | 美女在线免费观看视频 | 国产在线看 | 婷婷天天色 | 欧美在线观看视频一区二区 | 97成人精品视频在线观看 | 91黄视频在线观看 | 国产成人精品综合 | 亚洲欧美成aⅴ人在线观看 四虎在线观看 | www色av| 蜜臀91丨九色丨蝌蚪老版 | 在线观看中文av | 国产精品久久久久久电影 | 黄网在线免费观看 | 一本色道久久综合亚洲二区三区 | 免费观看性生交大片3 | 一区二区三区精品久久久 | 精品久久久久久国产偷窥 | 一区二区中文字幕在线观看 | 国产做a爱一级久久 | 日韩欧美视频二区 | 天天射天天干天天插 | 国产精品区一区 | 国产日韩欧美在线观看 | 久久精品伊人 | 日韩一区二区三免费高清在线观看 | 婷婷视频在线观看 | 国产精品高清免费在线观看 | 国产精品99免视看9 国产精品毛片一区视频 | 国产精品视频免费看 | 国产免费小视频 | 有没有在线观看av | 国产免费观看久久 | 一本一道久久a久久综合蜜桃 | 在线观看视频免费大全 | 碰超在线观看 | 福利久久久 | 97福利在线| 久久久久美女 | 天堂av网站 | 免费a一级 | 国产手机av| 日本午夜在线亚洲.国产 | 亚洲成人资源在线 | 日韩在线字幕 | 欧美激情精品久久久久久变态 | 婷婷色亚洲| 91久久久久久久一区二区 | 狠狠色伊人亚洲综合网站色 | 国产精华国产精品 | 韩国av免费观看 | 亚洲九九 | 一区二区三区在线观看免费视频 | 国产黑丝袜在线 | 婷婷综合网 | 久久一区二 | 99在线热播精品免费99热 | 久久精品美女视频网站 | 久在线| 91av视频在线免费观看 | 国产精品热视频 | 欧美日韩裸体免费视频 | 国产精品毛片一区二区三区 | 中文字幕在线不卡国产视频 | 久久久久久久久亚洲精品 | 国产精品中文字幕在线 | 欧美日韩视频在线播放 | 狠狠狠狠干 | 最新在线你懂的 | 日韩在线视频一区 | 中文字幕在线观看1 | 久久伊人精品天天 | 天堂网在线视频 | 香蕉久久久久久av成人 | www在线观看视频 | 久草在线视频网站 | 国产一区二区在线播放视频 | 亚洲精品videossex少妇 | 亚洲激情网站免费观看 | 五月天综合网站 | 欧美国产一区二区 | 最近中文字幕在线中文高清版 | 色婷婷综合久色 | aaa日本高清在线播放免费观看 | 99国产一区二区三精品乱码 | 国产一区在线视频观看 | 91成人精品一区在线播放69 | www.久草视频| 亚洲日本va午夜在线影院 | 亚洲91中文字幕无线码三区 | 国产91精品看黄网站在线观看动漫 | 亚洲天堂自拍视频 | 99视频国产精品 | 亚洲国产小视频在线观看 | 天天射综合网视频 | 午夜精品99久久免费 | 国产午夜精品av一区二区 | 狠狠色丁香 | www蜜桃视频 | 四虎在线免费观看 | 久久少妇免费视频 | 日韩精品一区二区免费视频 | 久久国产精品第一页 | 精品一区二区三区电影 | 天天操天天干天天摸 | 国产尤物一区二区三区 | 激情综合网色播五月 | 欧美aa在线 | 国产精品久久久久久av | 婷婷精品国产一区二区三区日韩 | 国产性xxxx| 最新av免费在线观看 | 成人国产精品一区 | h动漫中文字幕 | 91探花视频 | 在线视频久| 国产一级片免费播放 | 久久五月婷婷综合 | 久久久久久欧美二区电影网 | 九九综合久久 | 精品久久精品久久 | 成人性生活大片 | 欧美精品三级 | 日韩一区二区三区高清在线观看 | 免费a一级| 超级碰碰碰免费视频 | 96av在线视频 | 日韩欧美精品免费 | 日本久久免费视频 | 欧美日韩国产精品爽爽 | 美女久久久久久久 | 成人手机在线视频 | 色美女在线 | 国产一区在线视频 | 日韩精品无码一区二区三区 | 久久精品系列 | 综合天天 | 一区二区三区视频网站 | 人人爽人人舔 | 九九九九精品九九九九 | 在线观看久久久久久 | 久久国产亚洲精品 | 亚州国产精品视频 | 中文十次啦 | 在线观影网站 | 久久艹人人 | 欧美一区二区三区在线 | 亚洲经典视频在线观看 | 久久综合偷偷噜噜噜色 | 国产精品一区二区吃奶在线观看 | 四虎国产免费 | 96精品视频 | 国产成人精品福利 | 成人毛片在线观看视频 | 欧美在线一级片 | 久久国产经典视频 | 人人狠| 在线免费观看成人 | 亚洲综合国产精品 | 久久久久久网址 | 日本色小说视频 | 欧美日韩免费看 | 精品亚洲国产视频 | 在线 精品 国产 | 日韩免费中文 | aaa日本高清在线播放免费观看 | 色偷偷88888欧美精品久久久 | 999久久久国产精品 高清av免费观看 | 亚洲永久精品在线观看 | 久久九九影视网 | 亚洲激情视频在线观看 | 蜜桃麻豆www久久囤产精品 | 国产一区二三区好的 | 久久艹精品 | 久久天天躁狠狠躁夜夜不卡公司 | 久久久久久久久久久久久久电影 | 久草在线资源观看 | 黄色免费视频在线观看 | 久久福利在线 | 伊人狠狠 | 深爱婷婷激情 | 国产一区二区三区高清播放 | 日韩三区在线 | 欧美精品久久久久久久久老牛影院 | 在线之家免费在线观看电影 | 国产拍揄自揄精品视频麻豆 | 日韩在线精品视频 | 欧美a影视 | 最近中文字幕完整高清 | 国产精品入口66mio女同 | 91视频久久久久 | 国产一区二区在线播放 | 国产黄色片久久 | 色婷婷成人网 | 久久久精品久久 | 亚洲激情六月 | 亚洲欧洲国产视频 | 成人久久 | 麻豆激情电影 | 久久精品国产一区 | 少妇激情久久 | 亚洲美女视频网 | 超碰97成人 | 国产精品高潮呻吟久久av无 | 亚洲综合在线五月天 | 五月天婷婷在线观看视频 | 成人免费视频视频在线观看 免费 | 久久刺激视频 | 久久久综合精品 | 欧美视频在线二区 | 日日操网 | 国产生活一级片 | 色狠狠狠 | 狠狠插狠狠操 | 日韩高清一区 | av电影中文字幕在线观看 | 久久免费精品国产 | 激情五月开心 | 最近高清中文在线字幕在线观看 | 九九精品在线观看 | 国产亚洲精品久久久久久久久久 | 2021国产在线视频 | 国产精品毛片 | 在线亚洲人成电影网站色www | 亚洲人成在线电影 | 久久有精品| 69国产精品视频免费观看 | av免费看看 | 六月丁香久久 | 四虎成人精品永久免费av九九 | 97视频免费看 | 中文字幕有码在线 | 久久久久久久久久久影视 | 婷婷六月天丁香 | 麻豆91精品| 91重口视频| 欧美极品少妇xxxx | 在线婷婷 | 精品国产伦一区二区三区 | 亚洲精品美女久久久久 | 欧美射射射 | 99久久99久久精品国产片 | 婷婷久久五月天 | 成人免费av电影 | 99在线免费观看视频 | 国产破处在线视频 | 久草影视在线 | 国产视频网站在线观看 | 亚洲精品在线一区二区三区 | 91精品久久久久久久99蜜桃 | 伊人看片 | 午夜黄色 | 久久国产乱 | av网址aaa| 亚洲一区二区三区毛片 | 日日夜夜操操 | 久久免费视频网站 | 国产一区在线精品 | 国内视频一区二区 | 日本黄色免费看 | 欧美精品黑人性xxxx | 欧美日韩p片 | 日韩成人免费电影 | 黄色精品免费 | 日本高清xxxx | 亚洲乱码精品久久久久 | 伊人天天综合 | 97国产一区二区 | 欧美日本国产在线观看 | av一区二区在线观看中文字幕 | 视频一区二区视频 | 日本中文字幕久久 | 国产一级二级三级视频 | 成年人在线播放视频 | 国产在线不卡一区 | 婷婷丁香色 | 黄a在线观看 | 久艹在线观看视频 | 日韩精品一区二区三区外面 | 黄色三级网站 | 国产精品福利无圣光在线一区 | a色视频| 久久久九九 | 国产一区久久久 | 欧美性精品 | 日本久久久精品视频 | 久草在线高清 | 欧美午夜剧场 | 精品久久亚洲 | 九九热只有精品 | 亚洲一区精品人人爽人人躁 | 在线观看亚洲精品 | 国产精品美女久久久久久网站 | 国产精品18久久久久久首页狼 | 国产视频久久 | 精品人妖videos欧美人妖 | 涩涩网站在线看 | 久久黄色小说视频 | 91九色porn在线资源 | 天天射射天天 | 日韩成人免费在线观看 | www.黄色小说.com| 成人午夜电影网站 | 日韩小视频 | 国产精品久久久久久久久软件 | 亚洲精品 在线视频 | 亚洲资源在线观看 | 99久久99视频| 日韩av免费一区二区 | 免费在线观看一区 | 婷婷综合 | 日韩综合在线观看 | 亚洲黄色在线播放 | 欧美日韩在线视频免费 | 国产黄色免费看 | 日本性xxx | a久久免费视频 | 国产免费又黄又爽 | 亚洲精品免费在线观看 | 国产精品毛片一区 | 中文字幕无吗 | 中文字幕在线精品 | 黄色电影网站在线观看 | 美女av在线免费 | 国产高h视频 | 久久夜色精品国产欧美乱 | 国产高清一区二区 | 中文字幕a在线 | 亚洲精品免费在线 | 国产欧美精品一区二区三区四区 | 最近在线中文字幕 | 国产高清不卡一区二区三区 | 国产精美视频 | 免费av免费观看 | 怡红院久久 | 亚洲精品色婷婷 | 久久成年人网站 | 国产视频精品免费播放 | 天天操导航 | 中文字幕观看视频 | 欧洲高潮三级做爰 | 我要看黄色一级片 | 国产美女精品人人做人人爽 | 久久成人麻豆午夜电影 | 国产裸体永久免费视频网站 | 亚洲天堂精品视频在线观看 | 精品久久综合 | 午夜12点 | 国产91精品欧美 | 久在线观看视频 | 亚洲精品伦理在线 | 久久人人干 | 国产黄色精品在线观看 | 成年人三级网站 | 欧美日韩亚洲第一页 | 色综合激情网 | 免费观看黄色12片一级视频 | 91av免费观看 | 在线观看视频亚洲 | 久草网在线观看 | 在线国产视频观看 | 成人午夜片av在线看 | 国产欧美精品xxxx另类 | 国产精品午夜8888 | 欧美一级免费片 | 色偷偷97| 国产在线污 | 久久不见久久见免费影院 | 久久免费精品国产 | 国产一级免费播放 | 欧美日韩视频网站 | 99热官网 | 91在线一区二区 | 黄色在线观看污 | 夜夜操狠狠干 | 欧美另类调教 | 国产男男gay做爰 | 国产精品美女久久久久久久久 | www.天天色.com | 伊人黄| 日本丰满少妇免费一区 | 久久麻豆视频 | 久久久精品| 97超碰资源总站 | 精品国产1区2区3区 国产欧美精品在线观看 | 欧美精品久久久久久久久久久 | 中文字幕人成一区 | 欧美日韩不卡在线 | 丁香六月色 | 国产亚洲免费观看 | 国产一级精品绿帽视频 | 99一级片 | 亚洲精品视频免费在线 | 国产96在线 | 亚洲最新在线视频 | 网址你懂的在线观看 | 亚洲 中文 欧美 日韩vr 在线 | 久久精品123 | 中文字幕在线视频第一页 | 午夜精品一二区 | 狠狠躁夜夜躁人人爽超碰91 | 午夜视频色 | 美州a亚洲一视本频v色道 | 欧美另类色图 | 成年人视频免费在线播放 | 国产剧情一区二区 | 久久综合加勒比 |