在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Retry和Fallback該怎么抉擇呢?

jf_ro2CN3Fa ? 來源:geekhalo ? 2023-02-21 17:15 ? 次閱讀

1. 概覽

在分布式場(chǎng)景中,Retry 和 Fallback 是最常見的容災(zāi)方案。

Retry 就是在調(diào)用遠(yuǎn)程接口失敗時(shí),Client 主動(dòng)發(fā)起重試請(qǐng)求,以期待獲得最終結(jié)果,從而完成整個(gè)流程

Fallback 是在調(diào)用遠(yuǎn)程接口失敗時(shí),Client 不進(jìn)行重試而是調(diào)用一個(gè)特殊的 fallback 方法,從這個(gè)方法中獲取結(jié)果,使流程能夠繼續(xù)下去

那 Retry 和 Fallback 該怎么抉擇呢?

1.1. 背景

首先,先看下 Retry 和 Fallback 都是怎么幫助流程進(jìn)行自我恢復(fù)的。

1.1.1. Retry

現(xiàn)在有一個(gè)生單流程:

e715a98e-af6d-11ed-bfe3-dac502259ad0.png

核心流程如下:

商品服務(wù)中獲取商品信息

根據(jù)商品信息創(chuàng)建訂單

將訂單保存到數(shù)據(jù)庫

如果發(fā)生網(wǎng)絡(luò)抖動(dòng),將導(dǎo)致生單失敗。

e7412a1e-af6d-11ed-bfe3-dac502259ad0.png

在調(diào)用商品服務(wù)獲取商品時(shí),由于網(wǎng)絡(luò)異常,接口調(diào)用失敗

由于無法獲取商品信息,生單流程被異常中斷

由于生單流程太過重要,系統(tǒng)需盡最大努力保障用戶能夠完成下單操作,那針對(duì)網(wǎng)絡(luò)抖動(dòng)這個(gè)問題,可以通過 Retry 進(jìn)行修復(fù)。

e770aa32-af6d-11ed-bfe3-dac502259ad0.png

在第一次獲取商品信息時(shí),由于網(wǎng)絡(luò)問題導(dǎo)致獲取失敗

系統(tǒng)不會(huì)直接拋出異常,而是在等待一段時(shí)間后,重新發(fā)起第二次請(qǐng)求,也就是 Retry 操作

網(wǎng)絡(luò)恢復(fù),第二次請(qǐng)求成功獲取商品信息

流程繼續(xù)運(yùn)行,最終完成用戶生單

Retry 機(jī)制非常適合服務(wù)短時(shí)間不可用,或某個(gè)服務(wù)節(jié)點(diǎn)異常 這類場(chǎng)景。

1.1.2. Fallback

一個(gè)生單驗(yàn)證接口,主流程如下:

e7990478-af6d-11ed-bfe3-dac502259ad0.png

調(diào)用商品服務(wù)的接口獲取商品信息

根據(jù)商品和用戶信息判斷用戶是否能夠購買該商品

同樣,假設(shè)在訪問商品服務(wù)時(shí)出現(xiàn)網(wǎng)絡(luò)異常:

e7bda256-af6d-11ed-bfe3-dac502259ad0.png

由于無法獲取商品信息,從而導(dǎo)致整個(gè)驗(yàn)證流程被異常中斷,用戶操作被迫終止。

聰明的你估計(jì)會(huì)說那就使用 Retry 呀,是的:

e7e7c716-af6d-11ed-bfe3-dac502259ad0.png

如果是短時(shí)不可用,通過 Retry 機(jī)制便可以恢復(fù)流程。

但,如果是商品服務(wù)壓力過大,響應(yīng)時(shí)間過長(zhǎng)呢?比如,商品服務(wù)流量激增,導(dǎo)致 DB CPU 飆升,出現(xiàn)大量的慢 SQL,這時(shí)觸發(fā)了系統(tǒng)的 Retry 會(huì)是怎樣?

e8136e84-af6d-11ed-bfe3-dac502259ad0.png

在獲取商品失敗后,系統(tǒng)自動(dòng)觸發(fā) Retry 機(jī)制

由于是商品服務(wù)本身出了問題,第二次請(qǐng)求仍舊失敗

服務(wù)又觸發(fā)了第三次請(qǐng)求,仍未獲取結(jié)果

達(dá)到最大重試次數(shù),仍舊無法獲取商品,只能通過異常中斷用戶請(qǐng)求

通過 Retry 機(jī)制未能將流程從異常中恢復(fù)過來,也給下游的 商品服務(wù) 造成了巨大傷害。

商品服務(wù)壓力大,響應(yīng)時(shí)間長(zhǎng)

上游系統(tǒng)由于超時(shí)觸發(fā)自動(dòng)重試

自動(dòng)重試增大了對(duì)商品服務(wù)的調(diào)用

商品服務(wù)請(qǐng)求量更大,更難以從故障中恢復(fù)

這就是常說的“讀放大”,假設(shè)用戶驗(yàn)證是否能夠購買請(qǐng)求的請(qǐng)求量為 n,那極端情況下 商品服務(wù)的請(qǐng)求量為 3n (其中 2n 是由 Retry 機(jī)制造成)

此時(shí),Retry 就不是一個(gè)好的方案。我們先退回業(yè)務(wù)場(chǎng)景進(jìn)行思考,如果無法獲取商品,驗(yàn)證接口是否可以直接放行,先讓用戶完成購買?

如果,這個(gè)業(yè)務(wù)假設(shè)能夠接受的話,那就到了 Fallback 上場(chǎng)的時(shí)候了。

e838af8c-af6d-11ed-bfe3-dac502259ad0.png

調(diào)用商品服務(wù)獲取商品信息失敗

系統(tǒng)不會(huì)進(jìn)行重試,而是觸發(fā) fallback 機(jī)制

fallback 會(huì)調(diào)用指定的一個(gè)方法,并將返回值作為遠(yuǎn)程接口的返回值

接下來的流程使用 fallback 方法的返回值完成業(yè)務(wù)邏輯

1.1.3. 場(chǎng)景思考

同樣是對(duì)商品服務(wù)接口(同一個(gè)接口)的調(diào)用,在不同的場(chǎng)景需要使用不同的策略用以恢復(fù)業(yè)務(wù)流程,通常情況下:

Command 場(chǎng)景優(yōu)先使用 Retry

這種流量即為重要,最好能保障流程的完整性

通常寫流量比較小,小范圍 Retry 不會(huì)對(duì)下游系統(tǒng)造成巨大影響

Query 場(chǎng)景優(yōu)選使用 Fallabck

大多數(shù)展示場(chǎng)景,哪怕部分信息沒有獲取到對(duì)整體的影響也比較小

通常讀場(chǎng)景流量較高,Retry 對(duì)下游系統(tǒng)的傷害不容忽視

那面對(duì)一個(gè)遠(yuǎn)程接口被多個(gè)場(chǎng)景使用,我們?cè)撛趺刺幚砟兀?/p>

提供兩組接口,一個(gè)具有 Retry 能力,一個(gè)具有 Fallback 能力,由使用方根據(jù)業(yè)務(wù)場(chǎng)景進(jìn)行選擇?

還是…

1.2. 目標(biāo)

遠(yuǎn)程接口具備 Retry 和 Fallback 能力

能夠根據(jù)上下文不同場(chǎng)景,在發(fā)生調(diào)用異常時(shí)動(dòng)態(tài)選擇 Retry 或 Fallback 進(jìn)行流程恢復(fù)

2. 快速入門

2.1. 準(zhǔn)備環(huán)境

項(xiàng)目主要依賴 spring retry 和 lego starter首先,引入 spring-retry 依賴


org.springframework.retry
spring-retry

此次,引入 lego-starter 依賴


com.geekhalo.lego
lego-starter
0.1.17

最后新建 RetryConfiguration 以開啟 Retry 能力

@EnableRetry
@Configuration
publicclassRetryConfiguration{
}

2.2. 構(gòu)建 ActionTypeProvider

在完成基本配置后,需要準(zhǔn)備一個(gè) ActionTypeProvider 用以提供上下文信息。ActionTypeProvider 接口定義如下:

publicinterfaceActionTypeProvider{
ActionTypeget();
}

publicenumActionType{
COMMAND,QUERY
}

通常情況下,我們會(huì)使用 ThreadLocal 組件將 ActionType 存儲(chǔ)于線程上下文,在使用時(shí)從上下中獲取相關(guān)信息。

publicclassActionContext{
privatestaticfinalThreadLocalACTION_TYPE_THREAD_LOCAL=newThreadLocal<>();

publicstaticvoidset(ActionTypeactionType){
ACTION_TYPE_THREAD_LOCAL.set(actionType);
}

publicstaticActionTypeget(){
returnACTION_TYPE_THREAD_LOCAL.get();
}

publicstaticvoidclear(){
ACTION_TYPE_THREAD_LOCAL.remove();
}
}

有了上下文之后,ActionBasedActionTypeProvider 直接從 Context 中獲取 ActionType 具體如下

@Component
publicclassActionBasedActionTypeProviderimplementsActionTypeProvider{
@Override
publicActionTypeget(){
returnActionContext.get();
}
}

上下文中的 ActionType 又是怎么進(jìn)行管理的呢,包括信息綁定和信息清理?最常用的方式便是:

提供一個(gè)注解,在方法上添加注解用于對(duì) ActionType 的配置;

提供一個(gè)攔截器,對(duì)方法調(diào)用進(jìn)行攔截。方法調(diào)用前,從注解中獲取配置信息并綁定到上下文;方法調(diào)用后,主動(dòng)清理上下文信息;

核心實(shí)現(xiàn)為:

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public@interfaceAction{
ActionTypetype();
}


@Aspect
@Component
@Order(Integer.MIN_VALUE)
publicclassActionAspect{
@Pointcut("@annotation(com.geekhalo.lego.faultrecovery.smart.Action)")
publicvoidpointcut(){
}

@Around(value="pointcut()")
publicObjectaction(ProceedingJoinPointjoinPoint)throwsThrowable{
MethodSignaturemethodSignature=(MethodSignature)joinPoint.getSignature();
Actionannotation=methodSignature.getMethod().getAnnotation(Action.class);
ActionContext.set(annotation.type());
try{
returnjoinPoint.proceed();
}finally{
ActionContext.clear();
}
}
}

在這些組件的幫助下,我們只需在方法上基于 @Action 注解進(jìn)行標(biāo)記,便能夠?qū)?ActionType 綁定到上下文。

2.3. 使用 @SmartFault

在將 ActionType 綁定到上下文之后,接下來要做的便是對(duì) 遠(yuǎn)程接口 進(jìn)行配置。遠(yuǎn)程接口的配置工作主要由 @SmartFault 來完成。其核心配置項(xiàng)包括:

配置項(xiàng) 含義 默認(rèn)配置
recover fallback 方法名稱
maxRetry 最大重試次數(shù) 3
include 觸發(fā)重試的異常類型
exclude 不需要重新的異常類型

接下來,看一個(gè) demo

@Service
@Slf4j
@Getter
publicclassRetryService3{
privateintcount=0;

privateintretryCount=0;
privateintfallbackCount=0;
privateintrecoverCount=0;

publicvoidclean(){
this.retryCount=0;
this.fallbackCount=0;
this.recoverCount=0;
}

/**
*Command請(qǐng)求,啟動(dòng)重試機(jī)制
*/
@Action(type=ActionType.COMMAND)
@SmartFault(recover="recover")
publicLongretry(Longinput)throwsThrowable{
this.retryCount++;
returndoSomething(input);
}

/**
*Query請(qǐng)求,啟動(dòng)Fallback機(jī)制
*/
@Action(type=ActionType.QUERY)
@SmartFault(recover="recover")
publicLongfallback(Longinput)throwsThrowable{
this.fallbackCount++;
returndoSomething(input);
}

@Recover
publicLongrecover(Throwablee,Longinput){
this.recoverCount++;
log.info("recover-{}",input);
returninput;
}

privateLongdoSomething(Longinput){
//偶數(shù)拋出異常
if(count++%2==0){
log.info("Error-{}",input);
thrownewRuntimeException();
}
log.info("Success-{}",input);
returninput;
}
}

測(cè)試代碼如下:

@SpringBootTest(classes=DemoApplication.class)
publicclassRetryService3Test{
@Autowired
privateRetryService3retryService;

@BeforeEach
publicvoidsetup(){
retryService.clean();
}

@Test
publicvoidretry()throwsThrowable{
for(inti=0;i0);
Assertions.assertTrue(retryService.getRecoverCount()==0);
Assertions.assertTrue(retryService.getFallbackCount()==0);
}

@Test
publicvoidfallback()throwsThrowable{
for(inti=0;i0);
Assertions.assertTrue(retryService.getFallbackCount()>0);
}
}

運(yùn)行 retry 測(cè)試,日志如下:

[main]c.g.l.c.f.smart.SmartFaultExecutor:actiontypeisCOMMAND
[main]c.g.l.faultrecovery.smart.RetryService3:Error-0
[main]c.g.l.c.f.smart.SmartFaultExecutor:Retrymethodpublicjava.lang.Longcom.geekhalo.lego.faultrecovery.smart.RetryService3.retry(java.lang.Long)throwsjava.lang.Throwableuse[0]
[main]c.g.l.faultrecovery.smart.RetryService3:Success-0

可見,當(dāng) action type 為 COMMAND 時(shí):

第一次調(diào)用時(shí),觸發(fā)異常,打印: Error-0

此時(shí) SmartFaultExecutor 主動(dòng)進(jìn)行重試,打印: Retry method xxxx

方法重試成功,RetryService3 打印: Success-0

方法主動(dòng)進(jìn)行重試,流程從異常中恢復(fù),處理過程和效果符合預(yù)期。

運(yùn)行 fallback 測(cè)試,日志如下:

[main]c.g.l.c.f.smart.SmartFaultExecutor:actiontypeisQUERY
[main]c.g.l.faultrecovery.smart.RetryService3:Error-0
[main]c.g.l.c.f.smart.SmartFaultExecutor:recoverFromERRORformethodReflectiveMethodInvocation:publicjava.lang.Longcom.geekhalo.lego.faultrecovery.smart.RetryService3.fallback(java.lang.Long)throwsjava.lang.Throwable;targetisofclass[com.geekhalo.lego.faultrecovery.smart.RetryService3]
[main]c.g.l.faultrecovery.smart.RetryService3:recover-0

可見,當(dāng) action type 為 QUERY 時(shí):

第一次調(diào)用時(shí),觸發(fā)異常,打印: Error-0

SmartFaultExecutor 執(zhí)行 Fallback 策略,打印:recover From ERROR for method xxxx

調(diào)用RetryService3的 recover 方法,獲取最終返回值。RetryService3 打印:recover-0

異常后自動(dòng)執(zhí)行 fallback,將流程從異常中恢復(fù)過來,處理過程和效果符合預(yù)期。

3. 設(shè)計(jì)&擴(kuò)展

3.1 核心設(shè)計(jì)

e85d76fa-af6d-11ed-bfe3-dac502259ad0.png

整體流程如下:

ActionAspect 從 @Action 中讀取配置信息,將請(qǐng)求類型綁定到線程上下文

然后執(zhí)行正常業(yè)務(wù)邏輯

當(dāng)調(diào)用 @SmartFault 注解的方法時(shí),會(huì)被 SmartFaultMethodInterceptor 攔截器攔截

攔截器通過 ActionTypeProvider 獲取當(dāng)前的 ActionType

根據(jù) ActionType 對(duì)請(qǐng)求進(jìn)行路由

如果是 COMMAND 操作,將使用 RetryTemplate 執(zhí)行請(qǐng)求,在發(fā)生異常時(shí),通過重試配置進(jìn)行請(qǐng)求重發(fā),從而最大限度的獲得遠(yuǎn)程結(jié)果

如果是 QUERY 操作,將使用 FallbackTemplate(重試次數(shù)為0的 RetryTemplate)執(zhí)行請(qǐng)求,當(dāng)發(fā)生異常時(shí),調(diào)用 fallback 方法,執(zhí)行配置的 recover 方法,直接使用返回結(jié)果

獲取遠(yuǎn)程結(jié)果后,執(zhí)行后續(xù)的業(yè)務(wù)邏輯

最后,ActionAspect 將 ActionType 從線程上下文中移除。








審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • cpu
    cpu
    +關(guān)注

    關(guān)注

    68

    文章

    11038

    瀏覽量

    216030
  • SQL
    SQL
    +關(guān)注

    關(guān)注

    1

    文章

    780

    瀏覽量

    44814
  • 數(shù)據(jù)庫
    +關(guān)注

    關(guān)注

    7

    文章

    3901

    瀏覽量

    65783

原文標(biāo)題:容災(zāi)方案:Retry 和 Fallback 該怎么抉擇?

文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    usb fallback這個(gè)是主要什么作用?

    usb fallback 這個(gè)是主要什么作用
    發(fā)表于 07-04 07:21

    FPGA,如何抉擇

    方面的) 對(duì)C語言熟悉,但VHDL又和C語言半毛錢關(guān)系沒有。 現(xiàn)在都不知道是否要繼續(xù)下去了,現(xiàn)在的困惑是要不要繼續(xù)下去呢 。現(xiàn)在想是應(yīng)該重新去找個(gè)用得著C語言的和硬件又有關(guān)聯(lián)的(比如嵌入式)的工作,還是把這FPGA繼續(xù)學(xué)下去? 搞FPGA有前途嗎? 望論壇里的前輩能給點(diǎn)建議嗎? 先謝謝各位了!
    發(fā)表于 07-06 21:29

    為什么activate_retry_interval的值不等于3?

    各位高手,小弟正在基于慶科micokit-3165開發(fā)板和MICO操作系統(tǒng)開發(fā)應(yīng)用。正在調(diào)試micokit_enjoy工程。運(yùn)行完成“uint32_t activate_retry
    發(fā)表于 10-09 00:07

    Uboot更新固件報(bào)錯(cuò)ARP retry count exceeded如何解決?

    Uboot 更新固件報(bào)錯(cuò)ARP retry count exceeded,請(qǐng)問這個(gè)怎么解決?
    發(fā)表于 09-12 08:26

    本本發(fā)熱導(dǎo)致“發(fā)燒” 那怎么辦

    本本發(fā)熱導(dǎo)致“發(fā)燒” 那怎么辦? 焦點(diǎn):怎樣讓我們可愛的本本保持正常的“體溫”?   你是否曾經(jīng)聽說過,瑞典的
    發(fā)表于 01-26 11:40 ?1644次閱讀

    榮耀9、小米6對(duì)比評(píng)測(cè):這對(duì)難兄難弟,外觀、價(jià)格也都差不多如何抉擇

    要說,今年的手機(jī)新品讓我都心動(dòng),但是總不能都買吧!雖然我用的是魅族,但是pro7真的讓我提不起興趣,所以在此問問各位網(wǎng)友們?在榮耀9和小米6之間,我應(yīng)該怎么抉擇?望各位上車的朋友們分析分析,讓我在這個(gè)周把手機(jī)這個(gè)難題解決了?
    發(fā)表于 10-11 09:42 ?841次閱讀

    華為P20Pro和iPhone 8Plus如何抉擇

    采用了雙玻璃設(shè)計(jì),也算創(chuàng)新了一回,不過大多數(shù)人認(rèn)為其是在向喬布斯的iPhone 4致敬。所以如何抉擇,首先要看你對(duì)外觀上的要求怎樣,是喜歡經(jīng)典還是喜歡時(shí)尚主流
    發(fā)表于 11-07 18:34 ?1600次閱讀

    地鐵二維碼改造是如何實(shí)現(xiàn)的?傳統(tǒng)地鐵閘機(jī)廠商又該如何抉擇

    地鐵全面進(jìn)入刷碼乘車“新時(shí)代”!那么,地鐵二維碼改造是如何實(shí)現(xiàn)的?傳統(tǒng)地鐵閘機(jī)廠商又該如何抉擇
    的頭像 發(fā)表于 06-01 16:24 ?1.3w次閱讀

    中國移動(dòng)攜手華為打通了首個(gè)5G EPS Fallback語音視頻通話

    在5G網(wǎng)絡(luò)語音業(yè)務(wù)中,EPS fallback方案允許5G終端駐留在5G網(wǎng)絡(luò),但在4G網(wǎng)絡(luò)上提供語音業(yè)務(wù)。當(dāng)終端發(fā)起語音呼叫時(shí),網(wǎng)絡(luò)通過EPS Fallback流程將終端切換到4G網(wǎng)絡(luò)上,通過
    發(fā)表于 06-14 10:19 ?1344次閱讀

    四案例EPS Fallback問題解決資料下載

    電子發(fā)燒友網(wǎng)為你提供四案例EPS Fallback問題解決資料下載的電子資料下載,更有其他相關(guān)的電路圖、源代碼、課件教程、中文資料、英文資料、參考設(shè)計(jì)、用戶指南、解決方案等資料,希望可以幫助到廣大的電子工程師們。
    發(fā)表于 03-27 08:44 ?13次下載
    四案例EPS <b class='flag-5'>Fallback</b>問題解決資料下載

    SA EPS FallBack重要信令節(jié)點(diǎn)資料下載

    電子發(fā)燒友網(wǎng)為你提供SA EPS FallBack重要信令節(jié)點(diǎn)資料下載的電子資料下載,更有其他相關(guān)的電路圖、源代碼、課件教程、中文資料、英文資料、參考設(shè)計(jì)、用戶指南、解決方案等資料,希望可以幫助到廣大的電子工程師們。
    發(fā)表于 04-14 08:55 ?4次下載
    SA EPS <b class='flag-5'>FallBack</b>重要信令節(jié)點(diǎn)資料下載

    MOS管如何抉擇

    MOS管是電子制造的基本元件,但面對(duì)不同封裝、不同特性、不同品牌的MOS管時(shí),如何抉擇?有沒有省心、省力的遴選方法?
    的頭像 發(fā)表于 08-25 08:56 ?1909次閱讀

    縮短MultiBoot流程中的回跳 (Fallback)時(shí)間

    MultiBoot 是 FPGA 遠(yuǎn)程更新配置文件時(shí)一種非常普遍的應(yīng)用--為了確保安全,我們通常需要安排一個(gè) Golden Image,升級(jí)失敗后 FPGA 能回跳 (Fallback) 到此配置,從而使 FPGA 始終處于可被檢測(cè)的工作狀態(tài)。
    的頭像 發(fā)表于 12-09 09:50 ?1731次閱讀

    5G EPS Fallback語音方案流程總結(jié)

    選擇EPS Fallback作為5G SA的語音方案,是因?yàn)榭紤]到目前5G SA建網(wǎng)初期,5G信號(hào)覆蓋還處于初期階段,沒有大規(guī)模的覆蓋,而4G的覆蓋已經(jīng)進(jìn)入成熟期。
    的頭像 發(fā)表于 04-20 11:11 ?2.5w次閱讀

    如何抉擇PLC和DCS系統(tǒng)

    在可編程邏輯控制器(PLC)和分散式控制系統(tǒng)(DCS)之間如何抉擇,要具體情況具體分析,因?yàn)閼?yīng)用場(chǎng)合不同,對(duì)控制系統(tǒng)的要求也各不相同。
    發(fā)表于 06-25 10:40 ?605次閱讀
    如何<b class='flag-5'>抉擇</b>PLC和DCS系統(tǒng)
    主站蜘蛛池模板: 男人女人真曰批视频播放 | 国产成人亚洲精品77 | 欧美人成网站免费大全 | 五月婷婷俺也去开心 | 四虎免费永久观看 | 手机在线看 | 日本免费网站观看 | 依人成人 | 四虎国产精品免费久久影院 | 色色色色色色色色色色色色 | 亚洲人成电影在线观看网 | 欧美日本俄罗斯一级毛片 | 国产毛片农村妇女aa板 | 又色又爽又黄视频 | 综合色视频 | 亚洲第一区在线 | 同性同男小说肉黄 | 视频一区二区在线 | 日本免费网站观看 | 在线成人精品国产区免费 | 老色批在线播放视频网站免费 | 久久久久毛片成人精品 | 丁香狠狠| 国产午夜视频高清 | 国产精品资源在线播放 | 曰本女人色黄网站 | 乱色伦短篇小说 | 岛国一级毛片 | 羞羞答答91麻豆网站入口 | 国产在线视欧美亚综合 | 奇米777狠狠 | 日韩综合色 | 欧美一卡二卡科技有限公司 | aa视频在线| 午夜视频日本 | 五月天婷婷网亚洲综合在线 | 欧美色影视| 日本免费人成黄页在线观看视频 | 色六月丁香| 五月天婷婷免费视频 | 天天免费视频 |