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

33張圖探秘OpenFeign核心架構原理

開發 架構
當調用動態代理方法的時候,Feign就會將上述解析出來的Http請求基本參數和方法入參組裝成一個Http請求,然后發送Http請求,獲取響應,再根據響應的內容的類型將響應體的內容轉換成對應的類型‘’這就是Feign的大致原理。

大家好,我是三友~~

在很久之前,我寫過兩篇關于OpenFeign和Ribbon這兩個SpringCloud核心組件架構原理的文章

但是說實話,從我現在的角度來看,這兩篇文章的結構和內容其實還可以更加完善

剛好我最近打算整個SpringCloud各個組件架構原理的小冊子

所以趁著這個機會,我就來重新寫一下這兩篇文章,彌補之前文章的不足

這一篇文章就先來講一講OpenFeign的核心架構原理

整篇文章大致分為以下四個部分的內容:

第一部分,脫離于SpringCloud,原始的Feign是什么樣的?

第二部分,Feign的核心組件有哪些,整個執行鏈路是什么樣的?

第三部分,SpringCloud是如何把Feign融入到自己的生態的?

第四部分,OpenFeign有幾種配置方式,各種配置方式的優先級是什么樣的?

好了,話不多說,接下來就直接進入主題,來探秘OpenFeign核心架構原理

原始Feign是什么樣的?

在日常開發中,使用Feign很簡單,就三步

第一步:引入依賴

<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-openfeign</artifactId>
     <version>2.2.5.RELEASE</version>
</dependency>

第二步:在啟動引導類加上@EnableFeignClients注解

@SpringBootApplication
@EnableFeignClients
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

}

第三步:寫個FeignClient接口

@FeignClient(name = "order")
@RequestMapping("/order")
public interface OrderApiClient {

    @GetMapping
    Order queryOrder(@RequestParam("orderId") Long orderId);

}

之后當我們要使用時,只需要注入OrderApiClient對象就可以了

雖然使用方便,但這并不是Feign最原始的使用方式,而是SpringCloud整合Feign之后的使用方式

Feign最開始是由Netflix開源的

后來SpringCloud就將Feign進行了一層封裝,整合到自己的生態,讓Feign使用起來更加簡單

并同時也給它起了一個更高級的名字,OpenFeign

接下來文章表述有時可能并沒有嚴格區分Feign和OpenFeign的含義,你知道是這么個意思就行了。

Feign本身有自己的使用方式,也有類似Spring MVC相關的注解,如下所示:

public interface OrderApiClient {

    @RequestLine("GET /order/{orderId}")
    Order queryOrder(@Param("orderId") Long orderId);

}

OrderApiClient對象需要手動通過Feign.builder()來創建

public class FeignDemo {

    public static void main(String[] args) {
        OrderApiClient orderApiClient = Feign.builder()
                .target(OrderApiClient.class, "http://localhost:8088");
        orderApiClient.queryOrder(9527L);
    }

}

Feign的本質:動態代理 + 七大核心組件

相信稍微了解Feign的小伙伴都知道,Feign底層其實是基于JDK動態代理來的

所以Feign.builder()最終構造的是一個代理對象

Feign在構建動態代理的時候,會去解析方法上的注解和參數

獲取Http請求需要用到基本參數以及和這些參數和方法參數的對應關系

比如Http請求的url、請求體是方法中的第幾個參數、請求頭是方法中的第幾個參數等等

之后在構建Http請求時,就知道請求路徑以及方法的第幾個參數對應是Http請求的哪部分數據

當調用動態代理方法的時候,Feign就會將上述解析出來的Http請求基本參數和方法入參組裝成一個Http請求

然后發送Http請求,獲取響應,再根據響應的內容的類型將響應體的內容轉換成對應的類型

這就是Feign的大致原理

圖片圖片

在整個Feign動態代理生成和調用過程中,需要依靠Feign的一些核心組件來協調完成

如下圖所示是Feign的一些核心組件

這些核心組件可以通過Feign.builder()進行替換

由于組件很多,這里我挑幾個重要的跟大家講一講

1、Contract

圖片圖片

前面在說Feign在構建動態代理的時候,會去解析方法上的注解和參數,獲取Http請求需要用到基本參數

而這個Contract接口的作用就是用來干解析這件事的

Contract的默認實現是解析Feign自己原生注解的

圖片圖片

解析時,會為每個方法生成一個MethodMetadata對象

圖片圖片

MethodMetadata就封裝了Http請求需要用到基本參數以及這些參數和方法參數的對應關系

SpringCloud在整合Feign的時候,為了讓Feign能夠識別Spring MVC的注解,所以就自己實現了Contract接口

2、Encoder

通過名字也可以看出來,這個其實用來編碼的

具體的作用就是將請求體對應的方法參數序列化成字節數組

Feign默認的Encoder實現只支持請求體對應的方法參數類型為String和字節數組

圖片圖片

如果是其它類型,比如說請求體對應的方法參數類型為AddOrderRequest.class類型,此時就無法對AddOrderRequest對象進行序列化

這就導致默認情況下,這個Encoder的實現很難用

于是乎,Spring就實現了Encoder接口

圖片圖片

可以將任意請求體對應的方法參數類型對象序列化成字節數組

3、Decoder

Decoder的作用恰恰是跟Encoder相反

Encoder是將請求體對應的方法參數序列化成字節數組

而Decoder其實就是將響應體由字節流反序列化成方法返回值類型的對象

Decoder默認情況下跟Encoder的默認情況是一樣的,只支持反序列化成字節數組或者是String

所以,Spring也同樣實現了Decoder,擴展它的功能

圖片圖片

可以將響應體對應的字節流反序列化成任意返回值類型對象

4、Client

圖片

從接口方法的參數和返回值其實可以看出,這其實就是動態代理對象最終用來執行Http請求的組件

默認實現就是通過JDK提供的HttpURLConnection來的

除了這個默認的,Feign還提供了基于HttpClient和OkHttp實現的

在項目中,要想替換默認的實現,只需要引入相應的依賴,在構建Feign.builder()時設置一下就行了

SpringCloud環境底下會根據引入的依賴自動進行設置

除了上述的三個實現,最最重要的當然是屬于它基于負載均衡的實現

如下是OpenFeign用來整合Ribbon的核心實現

圖片圖片

這個Client會根據服務名,從Ribbon中獲取一個服務實例的信息,也就是ip和端口

之后會通過ip和端口向服務實例發送Http請求

5、InvocationHandlerFactory

InvocationHandler我相信大家應該都不陌生

對于JDK動態代理來說,必須得實現InvocationHandler才能創建動態代理

InvocationHandler的invoke方法實現就是動態代理走的核心邏輯

而InvocationHandlerFactory其實就是創建InvocationHandler的工廠

所以,這里就可以猜到,通過InvocationHandlerFactory創建的InvocationHandler應該就是Feign動態代理執行的核心邏輯

InvocationHandlerFactory默認實現是下面這個

SpringCloud環境下默認也是使用它的這個默認實現

所以,我們直接去看看InvocationHandler的實現類FeignInvocationHandler

圖片圖片

從實現可以看出,除了Object類的一些方法,最終會調用方法對應的MethodHandler的invoke方法

所以注意注意,這個MethodHandler就封裝了Feign執行Http調用的核心邏輯,很重要,后面還會提到

圖片圖片

雖然說默認情況下SpringCloud使用是默認實現,最終使用FeignInvocationHandler

但是當其它框架整合SpringCloud生態的時候,為了適配OpenFeign,有時會自己實現InvocationHandler

比如常見的限流熔斷框架Hystrix和Sentinel都實現了自己的InvocationHandler

這樣就可以對MethodHandler執行前后,也就是Http接口調用前后進行限流降級等操作。

6、RequestInterceptor

圖片圖片

RequestInterceptor它其實是一個在發送請求前的一個攔截接口

通過這個接口,在發送Http請求之前再對Http請求的內容進行修改

比如我們可以設置一些接口需要的公共參數,如鑒權token之類的

@Component
public class TokenRequestInterceptor implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate template) {
        template.header("token", "token值");
    }

}

7、Retryer

這是一個重試的組件,默認實現如下

默認情況下,最大重試5次

在SpringCloud下,并沒有使用上面那個實現,而使用的是下面這個實現

圖片圖片

所以,SpringCloud下默認是不會進行重試

小總結

這一節主要是介紹了7個Feign的核心組件以及Spring對應的擴展實現

為了方便你查看,我整理了如下表格

接口

作用

Feign默認實現

Spring實現

Contract

解析方法注解和參數,將Http請求參數和方法參數對應

Contract.Default

SpringMvcContract

Encoder

將請求體對應的方法參數序列化成字節數組

Encoder.Default

SpringEncoder

Decoder

將響應體的字節流反序列化成方法返回值類型對象

Decoder.Default

SpringDecoder

Client

發送Http請求

Client.Default

LoadBalancerFeignClient

InvocationHandlerFactory

InvocationHandler工廠,動態代理核心邏輯

InvocationHandlerFactory.Default

RequestInterceptor

在發送Http請求之前,再對Http請求的內容進行攔截修改

Retryer

重試組件

Retryer.Default

除了這些之外,還有一些其它組件這里就沒有說了

比如日志級別Logger.Level,日志輸出Logger,有興趣的可以自己查看

Feign核心運行原理分析

上一節說了Feign核心組件,這一節我們來講一講Feign核心運行原理,主要分為兩部分內容:

  • 動態代理生成原理
  • 一次Feign的Http調用執行過程

1、動態代理生成原理

這里我先把上面的Feign原始使用方式的Demo代碼再拿過來

public class FeignDemo {

    public static void main(String[] args) {
        OrderApiClient orderApiClient = Feign.builder()
                .target(OrderApiClient.class, "http://localhost:8088");
        orderApiClient.queryOrder(9527L);
    }

}

通過Demo可以看出,最后是通過Feign.builder().target(xx)獲取到動態代理的

而上述代碼執行邏輯如下所示:

圖片圖片

最終會調用ReflectiveFeign的newInstance方法來創建動態代理對象

而ReflectiveFeign內部設置了前面提到的一些核心組件

接下我們來看看newInstance方法

這個方法主要就干兩件事:

第一件事首先解析接口,構建每個方法對應的MethodHandler

MethodHandler在前面講InvocationHandlerFactory特地提醒過

動態代理(FeignInvocationHandler)最終會調用MethodHandler來處理Feign的一次Http調用

在解析接口的時候,就會用到前面提到的Contract來解析方法參數和注解,生成MethodMetadata,這里我代碼我就不貼了

第二件事通過InvocationHandlerFactory創建InvocationHandler

然后再構建出接口的動態代理對象

ok,到這其實就走完了動態代理的生成過程

所以動態代理生成邏輯很簡單,總共也沒幾行代碼,畫個圖來總結一下

圖片圖片

2、一次Feign的Http調用執行過程

前面說了,調用接口動態代理的方式時,通過InvocationHandler(FeignInvocationHandler),最終交給MethodHandler的invoke方法來執行

MethodHandler是一個接口,最終會走到它的實現類SynchronousMethodHandler的invoke方法實現

SynchronousMethodHandler中的屬性就是我們前面提到的一些組件

由于整個代碼調用執行鏈路比較長,這里我就不截代碼了,有興趣的可以自己翻翻

不過這里我畫了一張圖,可以通過這張圖來大致分析整個Feign一次Http調用的過程

圖片圖片

  • 首先就是前面說的,進入FeignInvocationHandler,找到方法對應的SynchronousMethodHandler,調用invoke方法實現
  • 之后根據MethodMetadata和方法的入參,構造出一個RequestTemplate,RequestTemplate封裝了Http請求的參數,在這個過程中,如果有請求體,那么會通過Encoder序列化
  • 然后調用RequestInterceptor,通過RequestInterceptor對RequestTemplate進行攔截擴展,可以對請求數據再進行修改
  • 再然后將RequestTemplate轉換成Request,Request其實跟RequestTemplate差不多,也是封裝了Http請求的參數
  • 接下來通過Client去根據Request中封裝的Http請求參數,發送Http請求,得到響應Response
  • 最后根據Decoder,將響應體反序列化成方法返回值類型對象,返回

這就是Feign一次Http調用的執行過程

如果有設置重試,那么也是在這個階段生效的

SpringCloud是如何整合Feign的?

SpringCloud在整合Feign的時候,主要是分為兩部分

  • 核心組件重新實現,支持更多SpringCloud生態相關的功能
  • 將接口動態代理對象注入到Spring容器中

第一部分核心組件重新實現前面已經都說過了,這里就不再重復了

至于第二部分我們就來好好講一講,Spring是如何將接口動態代理對象注入到Spring容器中的

1、將FeignClient接口注冊到Spring中

使用OpenFeign時,必須加上@EnableFeignClients

這個注解就是OpenFeign的發動機

圖片圖片

@EnableFeignClients最后通過@Import注解導入了一個FeignClientsRegistrar

圖片圖片

FeignClientsRegistrar實現了ImportBeanDefinitionRegistrar

所以最終Spring在啟動的時候會調用registerBeanDefinitions方法實現

之所以會調用registerBeanDefinitions方法,是@Import注解的作用,不清楚的同學可以看一下扒一扒Bean注入到Spring的那些姿勢,你會幾種?

圖片圖片

最終會走到registerFeignClients這個方法

這個方法雖然比較長,主要是干了下面這個2件事:

第一件事,掃描@EnableFeignClients所在類的包及其子包(如果有指定包就掃指定包),找出所有加了@FeignClient注解的接口,生成一堆BeanDefinition

這個BeanDefinition包含了這個接口的信息等信息

第二件事,將掃描到的這些接口注冊到Spring容器中

圖片圖片

在注冊的時候,并非直接注冊接口類型,而是FeignClientFactoryBean類型

圖片圖片

好了,到這整個@EnableFeignClients啟動過程就結束了

雖然上面寫的很長,但是整個@EnableFeignClients其實也就只干了一件核心的事

掃描到所有的加了@FeignClient注解的接口

然后為每個接口生成一個Bean類型為FeignClientFactoryBean的BeanDefinition

最終注冊到Spring容器中

圖片圖片

2、FeignClientFactoryBean的秘密

上一節說到,每個接口都對應一個class類型為FeignClientFactoryBean的BeanDefinition

圖片圖片

如上所示,FeignClientFactoryBean是一個FactoryBean

并且FeignClientFactoryBean的這些屬性,是在生成BeanDefinition的時候設置的

圖片圖片

并且這個type屬性就是代表的接口類型

由于實現了FactoryBean,所以Spring啟動過程中,一定為會調用getObject方法獲取真正的Bean對象

FactoryBean的作用就不說了,不清楚的小伙伴還是可以看看扒一扒Bean注入到Spring的那些姿勢,你會幾種?這篇文章

getObject最終會走到getTarget()方法

圖片圖片

從如上代碼其實可以看出來,最終還是會通過Feign.builder()來創建動態代理對象

只不過不同的是,SpringCloud會替換Feign默認的組件,改成自己實現的

總的來說,Spring是通過FactoryBean的這種方式,將Feign動態代理對象添加到Spring容器中

OpenFeign的各種配置方式以及對應優先級

既然Feign核心組件可以替換,那么在SpringCloud環境下,我們該如何去配置自己的組件呢?

不過在說配置之前,先說一下FeignClient配置隔離操作

在SpringCloud環境下,為了讓每個不同的FeignClient接口配置相互隔離

在應用啟動的時候,會為每個FeignClient接口創建一個Spring容器,接下來我就把這個容器稱為FeignClient容器

這些FeignClient的Spring容器有一個相同的父容器,那就是項目啟動時創建的容器

圖片圖片

SpringCloud會給每個FeignClient容器添加一個默認的配置類FeignClientsConfiguration配置類

圖片圖片

這個配置類就聲明了各種Feign的組件

圖片圖片

所以,默認情況下,OpenFeign就使用這些配置的組件構建代理對象

知道配置隔離之后,接下來看看具體的幾種方式配置以及它們之間的優先級關系

1、通過@EnableFeignClients注解的defaultConfiguration屬性配置

舉個例子,比如我自己手動聲明一個Contract對象,類型為MyContract

public class FeignConfiguration {
    
    @Bean
    public Contract contract(){
        return new MyContract();
    }
    
}

注意注意,這里FeignConfiguration我沒加@Configuration注解,原因后面再說

此時配置如下所示:

@EnableFeignClients(defaultConfiguration = FeignConfiguration.class)

之后這個配置類會被加到每個FeignClient容器中,所以這個配置是對所有的FeignClient生效

并且優先級大于默認配置的優先級

比如這個例子就會使得FeignClient使用我聲明的MyContract,而不是FeignClientsConfiguration中聲明的SpringMvcContract

2、通過@FeignClient注解的configuration屬性配置

還以上面的FeignConfiguration配置類舉例,可以通過@FeignClient注解配置

@FeignClient(name = "order", configuration = FeignConfiguration.class)

此時這個配置類會被加到自己FeignClient容器中,注意是自己FeignClient容器

所以這種配置的作用范圍是自己的這個FeignClient

并且這種配置的優先級是大于@EnableFeignClients注解配置的優先級

3、在項目啟動的容器中配置

前面提到,由于所有的FeignClient容器的父容器都是項目啟動的容器

所以可以將配置放在這個項目啟動的容器中

還以FeignConfiguration為例,加上@Configuration注解,讓項目啟動的容器的掃描到就成功配置了

這種配置的優先級大于前面提到的所有配置優先級

并且是對所有的FeignClient生效

所以,這就是為什么使用注解配置時為什么配置類不能加@Configuration注解的原因,因為一旦被項目啟動的容器掃描到,這個配置就會作用于所有的FeignClient,并且優先級是最高的,就會導致你其它的配置失效,當然你也可以加@Configuration注解,但是一定不能被項目啟動的容器掃到

4、配置文件

除了上面3種編碼方式配置,OpenFeign也是支持通過配置文件的方式進行配置

并且也同時支持對所有FeignClient生效和對單獨某個FeignClient生效

對所有FeignClient生效配置:

feign:
  client:
    config:
      default: # default 代表對全局生效
        contract: com.sanyou.feign.MyContract

對單獨某個FeignClient生效配置:

feign:
  client:
    config:
      order: # 具體的服務名
        contract: com.sanyou.feign.MyContract

在默認情況下,這種配置文件方式優先級最高

但是如果你在配置文件中將配置項feign.client.default-to-properties設置成false的話,配置文件的方式優先級就是最低了

feign:
  client:
    default-to-properties: false

小總結

這一節,總共總結了4種配置OpenFeign的方式以及它們優先級和作用范圍

畫張圖來總結一下

圖片圖片

如果你在具體使用的時候,還是遇到了一些優先級的問題,可以debug這部分源碼,看看到底生效的是哪個配置


圖片圖片

圖片

責任編輯:武曉燕 來源: 三友的java日記
相關推薦

2023-10-16 22:07:20

Spring配置中心Bean

2024-01-02 22:47:47

Nacos注冊中心節點

2023-11-30 22:06:43

2024-07-08 23:03:13

2022-01-14 12:28:18

架構OpenFeign遠程

2010-08-18 10:13:55

IntentAndroid

2009-06-15 15:57:21

Spring工作原理

2020-12-04 06:37:19

HTTPS原理安全

2009-08-25 13:48:01

Java EE架構企業級應用

2025-01-10 09:47:43

blockSDKiOS

2024-02-26 00:00:00

Nginx服務器HTTP

2023-12-05 17:44:24

reactor網絡

2010-01-27 17:38:58

Windows Emb

2010-03-12 17:09:18

2019-12-12 10:56:00

微服務微服務架構架構

2023-06-07 15:25:19

Kafka版本日志

2025-02-08 08:10:00

2024-01-05 07:55:39

Linux虛擬內存

2022-01-05 14:30:44

容器Linux網絡

2024-08-07 08:19:13

點贊
收藏

51CTO技術棧公眾號

欧美日韩精品亚洲精品| 国产乱子夫妻xx黑人xyx真爽| 国产精品美女一区| 激情综合在线| 国产一区二区三区网站| 国产精品久久久久久亚洲调教| 中文字幕国产专区| 国产精品亚洲欧美一级在线| 无码av免费一区二区三区试看| 日日夜夜精品网站| 亚洲国产精品久久久久久6q| 老司机精品视频网站| 不卡中文字幕av| 中日韩精品一区二区三区| 精品国产亚洲一区二区在线观看| 精品久久香蕉国产线看观看亚洲| 一区二区精品在线观看| 天天综合网在线| 激情小说亚洲一区| 日韩av免费一区| 久久久综合久久| 日韩免费高清| 日韩精品久久久久| 欧美午夜精品一区二区| 国产精品亲子伦av一区二区三区| 亚洲国产综合视频在线观看| 亚洲巨乳在线观看| 四虎国产精品永远| 国产在线精品一区二区不卡了 | 亚洲最大的av网站| 日韩电影在线观看一区二区| 在线不卡视频| 欧美精品一本久久男人的天堂| 永久免费av无码网站性色av| 欧美激情15p| 精品国产乱码久久久久久久久| 在线观看免费的av| 成人免费福利| 色综合天天在线| 国产精品50p| 欧产日产国产精品视频 | 伊人伊人伊人久久| 在线免费观看黄色小视频| 综合成人在线| 日韩一区二区在线观看| 日韩成人av免费| 欧美日韩卡一| 欧美日韩成人综合| 久久久精品高清| а√天堂资源国产精品| 91九色最新地址| 久久久精品在线视频| 久久男人av资源站| 天天色天天操综合| 免费看国产曰批40分钟| av手机免费在线观看| 一区av在线播放| 亚洲精品蜜桃久久久久久| 青青草原av在线| 亚洲国产欧美在线人成| 国产a级片网站| 在线看的毛片| 色8久久人人97超碰香蕉987| 日韩在线第三页| 黄色精品视频| 欧美精选午夜久久久乱码6080| 免费网站在线观看黄| 亚洲va欧美va人人爽成人影院| 日韩一二三四区| 中国一级特黄录像播放| 日韩精品福利一区二区三区| 亚洲欧美精品一区| 在线看片中文字幕| 欧美激情第二页| 97超碰色婷婷| 亚洲无码精品在线播放| 国产剧情一区二区| 久久涩涩网站| av在线电影播放| 一区二区三区四区视频精品免费 | 欧美午夜视频在线| 91啦中文在线| 一区二区三区在线免费| 777av视频| 88xx成人免费观看视频库| 欧美日韩高清一区| 男男一级淫片免费播放| 沈樵精品国产成av片| 自拍偷拍亚洲一区| 日韩 国产 在线| 免费高清成人在线| 成人永久免费| 成人高清网站| 亚洲电影中文字幕在线观看| 久久人妻精品白浆国产 | 日韩精品一级二级| 亚洲一区二区三区视频| 日韩a在线观看| 1024亚洲合集| 成人羞羞国产免费网站| 久久久久久爱| 在线精品国产成人综合| 欧美色图亚洲视频| 日韩avvvv在线播放| 国产超碰91| 成人高清网站| 天天影视色香欲综合网老头| 亚洲精品mv在线观看| 偷拍亚洲色图| 欧美另类高清videos| 懂色av蜜臀av粉嫩av分享吧最新章节| 国产精品996| 日韩精品久久久毛片一区二区| 电影k8一区二区三区久久| 欧美日本不卡视频| 精品无码人妻一区二区免费蜜桃| 欧美午夜一区| 91亚洲精品一区二区| 蜜芽tv福利在线视频| 亚洲一二三四在线观看| 日本77777| 精品久久91| 欧美亚洲第一页| 国产激情视频在线播放| 国产精品毛片久久久久久久| 女性女同性aⅴ免费观女性恋| 二区三区精品| 精品久久国产精品| 人妻中文字幕一区二区三区| 久久婷婷一区二区三区| 蜜臀av无码一区二区三区| 国产一区 二区| 日韩亚洲成人av在线| 国产成人无码专区| www国产亚洲精品久久麻豆| 蜜臀精品一区二区| 99久久香蕉| 欧美疯狂xxxx大交乱88av| 国产精品区在线观看| 久久亚洲一级片| 超碰97人人射妻| 最近国产精品视频| 青草青草久热精品视频在线网站 | 欧美激情中文字幕乱码免费| 99精品视频在线播放免费| 亚洲丝袜自拍清纯另类| 亚洲色图偷拍视频| 伊人情人综合网| 91精品视频在线播放| 免费a级在线播放| 4438x成人网最大色成网站| 免费成人深夜夜行网站| 狠狠色狠狠色综合| 8x8x华人在线| 99re热精品视频| 午夜精品一区二区三区在线| 欧美一区二区三区激情| 狠狠干狠狠久久| 亚洲国产无码精品| 肉肉av福利一精品导航| 亚洲天堂电影网| 亚洲欧美久久精品| 久久五月天综合| 国内爆初菊对白视频| 亚洲成人av一区二区| 日本黄色特级片| 秋霞午夜鲁丝一区二区老狼| www.午夜色| 视频一区日韩精品| 欧美亚洲视频在线看网址| 麻豆导航在线观看| 欧美日韩精品一区二区三区蜜桃 | 中文字幕av亚洲精品一部二部| 亚洲综合精品伊人久久| 国产盗摄一区二区| 亚洲色图美腿丝袜| 亚洲中文一区二区三区| 亚洲国产美女搞黄色| 最近中文字幕免费| 国内成人免费视频| 久久久999免费视频| 日韩在线观看一区 | 国产二区视频在线观看| 欧美二区乱c少妇| 国语对白一区二区| 久久久.com| wwwxxxx在线观看| 国产一区二区三区久久| 亚洲国产精品影视| 日韩精品欧美大片| 91理论片午午论夜理片久久| 国产精品电影| 日韩中文综合网| 天天影院图片亚洲| 日韩三级精品电影久久久| 久久久午夜影院| 自拍偷自拍亚洲精品播放| 欧美 变态 另类 人妖| 国内精品第一页| aaa毛片在线观看| 欧美日一区二区在线观看 | 91色中文字幕| 综合另类专区| 欧美国产视频一区二区| 国产高清视频在线观看| 亚洲精品一区二区三区香蕉| 伊人免费在线观看高清版| 亚洲国产日韩在线一区模特| 国产aaaaaaaaa| 久久欧美中文字幕| 极品白嫩的小少妇| 国内久久精品视频| 免费看国产黄色片| 美女久久一区| 免费不卡av在线| 综合激情婷婷| 在线免费观看成人| 欧洲三级视频| 麻豆成人av| 国产香蕉精品| 99电影网电视剧在线观看| 黄色成人小视频| 国产极品精品在线观看| 小h片在线观看| 性欧美xxxx视频在线观看| a视频在线观看免费| 日韩中文av在线| av网页在线| 亚洲日本成人网| 欧美777四色影视在线| 亚洲精品99999| 日本黄色三级视频| 精品久久久久久久久久久久久久久久久 | 国产精品夜夜嗨| 黄色aaaaaa| 久久99蜜桃精品| 玖玖爱视频在线| 久久精品国产一区二区三区免费看| 国产最新免费视频| 新67194成人永久网站| 激情综合在线观看| 亚洲在线一区| 国产亚洲天堂网| 久久狠狠一本精品综合网| 免费在线观看的毛片| 在线一区免费观看| 欧美视频第一区| 老司机精品久久| 欧美一级黄色影院| 美女视频黄 久久| 中文字幕 日韩 欧美| 蜜桃视频一区二区三区 | 欧美视频免费看| 91久久国产精品91久久性色| 99精品美女视频在线观看热舞| 成人在线视频网站| 中文字幕av一区二区三区四区| 粉嫩高清一区二区三区精品视频| 一区二区三区高清在线观看| y111111国产精品久久婷婷| 国产乱人伦精品一区| 精品网站在线看| 蜜桃国内精品久久久久软件9| 青青成人在线| 91久久电影| 国产免费一区二区视频| 国产精品日韩精品欧美精品| 亚洲精品一二三四五区| 六月婷婷色综合| 中文字幕无人区二| 99精品欧美一区二区三区小说| 国产一二三四五区| 国产精品久久久久久久久免费丝袜 | 久久精品老司机| 国产精品网站在线| 91aaa在线观看| 欧美日韩免费网站| 最近日韩免费视频| 日韩精品一区二区三区视频在线观看| 手机av免费在线观看| 亚洲视屏在线播放| 中文国产字幕在线观看| 国色天香2019中文字幕在线观看| 欧美xxxx做受欧美护士| 亚洲aaa激情| 国产成人调教视频在线观看 | 天堂资源在线视频| 亚洲精品国产一区二区精华液| 日韩女同强女同hd| 欧美日韩在线不卡| 黑人乱码一区二区三区av| 一区二区中文字幕| 欧美xxxx黑人又粗又长| 国产精品视频在线观看| 成人在线视频你懂的| 香蕉久久夜色| av成人毛片| 人妻换人妻仑乱| 日本一区二区不卡视频| 国产在线观看免费av| 欧美日韩在线电影| 视频二区在线| 欧美日本亚洲视频| 久久人体av| 久久精品国产一区二区三区不卡| 正在播放日韩欧美一页| 日本老熟妇毛茸茸| av一区二区久久| 日本老熟俱乐部h0930| 欧美中文字幕亚洲一区二区va在线 | 国产精品嫩草影院av蜜臀| 国产福利久久久| 这里只有精品99re| 91在线免费看| 日本精品性网站在线观看| 精品欧美午夜寂寞影院| av电影一区二区三区| 蜜臀91精品一区二区三区| 久久av无码精品人妻系列试探| 亚洲成人一区二区在线观看| 国产精品伦一区二区三区| 一个色综合导航| 美女100%一区| 久久涩涩网站| 国产亚洲精品久久久久婷婷瑜伽| 男人女人拔萝卜视频| 最新中文字幕一区二区三区| 青青艹在线观看| 亚洲视频在线观看网站| 日本久久免费| 欧洲一区二区日韩在线视频观看免费| 99国产精品久久久久久久| 黄色国产在线视频| 一区二区三区成人在线视频| 国产欧美综合视频| 超碰91人人草人人干| 国产高清视频一区二区| 国产对白在线播放| 精品一区二区三区av| 永久免费看mv网站入口| 这里是久久伊人| 在线网址91| 福利视频一区二区三区| 好吊日精品视频| 中文字幕在线永久| 欧美日韩黄色大片| 午夜视频www| 国产91色在线免费| 沈樵精品国产成av片| xxx国产在线观看| 国产精品成人在线观看| 国产精品日韩无码| 久国内精品在线| 精品少妇一区| 国产乱子夫妻xx黑人xyx真爽| 久久久www免费人成精品| 国产精品sm调教免费专区| 最近中文字幕2019免费| 电影91久久久| av免费观看大全| 久久久影视传媒| 国产女优在线播放| 精品视频9999| 欧美aaaaa级| 四季av一区二区| 一区二区三区在线播放| 天堂91在线| 国产精品久久久久久久久久东京| 国产精品久久久久久| 日韩成人av影院| 黑人巨大精品欧美一区二区免费 | 91精品国产91久久久久久| 国产毛片一区二区三区| 91亚洲一区二区| 黑人巨大精品欧美一区免费视频 | 亚洲欧美日韩系列| 欧美一级免费片| 国产成人福利网站| 亚洲成人一区| 少妇按摩一区二区三区| 555夜色666亚洲国产免| 91破解版在线观看| 天堂√在线观看一区二区| 国产精品一区二区久激情瑜伽| av中文在线播放| 色妞久久福利网| 欧美日韩精品一区二区三区在线观看| 中文字幕永久视频| 亚洲影院在线观看| 国产福利电影在线| 国产精品久久久久久久久久直播 | 韩国av免费观看| 日韩三级成人av网| 天堂99x99es久久精品免费| 亚洲第一天堂久久| 欧美日韩国产中字| 污视频网站免费在线观看| 欧美日韩日本网| 丁香另类激情小说| 一区二区www|