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

簡化本地Feign調用,老手教你這么玩

開發 前端
本文提供了一個在本地開發過程中簡化Feign調用的思路,相比之前需要麻煩的修改FeignClient中的url而言,能夠節省不少的無效勞動,并且通過這個過程,也可以幫助大家了解我們平常使用的這些組件是怎么與spring結合在一起的,熟悉spring的擴展點。

哈嘍大家好啊,我是Hydra。

在平常的工作中,OpenFeign作為微服務間的調用組件使用的非常普遍,接口配合注解的調用方式突出一個簡便,讓我們能無需關注內部細節就能實現服務間的接口調用。

但是工作中用久了,發現Feign也有些使用起來麻煩的地方,下面先來看一個問題,再看看我們在工作中是如何解決,以達到簡化Feign使用的目的。

先看問題

在一個項目開發的過程中,我們通常會區分開發環境、測試環境和生產環境,如果有的項目要求更高的話,可能還會有個預生產環境。

開發環境作為和前端開發聯調的環境,一般使用起來都比較隨意,而我們在進行本地開發的時候,有時候也會將本地啟動的微服務注冊到注冊中心nacos上,方便進行調試。

這樣,注冊中心的一個微服務可能就會擁有多個服務實例,就像下面這樣:

圖片

眼尖的小伙伴肯定發現了,這兩個實例的ip地址有一點不同。

線上環境現在一般使用容器化部署,通常都是由流水線工具打成鏡像然后扔到docker中運行,因此我們去看一下服務在docker容器內的ip:

可以看到,這就是注冊到nacos上的服務地址之一,而列表中192開頭的另一個ip,則是我們本地啟動的服務的局域網地址。看一下下面這張圖,就能對整個流程一目了然了。

總結一下:

  • 兩個service都是通過宿主機的ip和port,把自己的信息注冊到nacos上
  • 線上環境的service注冊時使用docker內部ip地址
  • 本地的service注冊時使用本地局域網地址

那么這時候問題就來了,當我本地再啟動一個serviceB,通過FeignClient來調用serviceA中的接口時,因為Feign本身的負載均衡,就可能把請求負載均衡到兩個不同的serviceA實例。

如果這個調用請求被負載均衡到本地serviceA的話,那么沒什么問題,兩個服務都在同一個192.168網段內,可以正常訪問。但是如果負載均衡請求到運行在docker內的serviceA的話,那么問題來了,因為網絡不通,所以會請求失敗:

說白了,就是本地的192.168和docker內的虛擬網段172.17屬于純二層的兩個不同網段,不能互訪,所以無法直接調用。

那么,如果想在調試時把請求穩定打到本地服務的話,有一個辦法,就是指定在FeignClient中添加url參數,指定調用的地址:

@FeignClient(value = "serviceA",url = "http://127.0.0.1:8088/")
public interface ClientA {
    @GetMapping("/test/get")
    String get();
}

但是這么一來也會帶來點問題:

  • 代碼上線時需要再把注解中的url刪掉,還要再次修改代碼,如果忘了的話會引起線上問題。
  • 如果測試的FeignClient很多的話,每個都需要配置url,修改起來很麻煩

那么,有什么辦法進行改進呢?為了解決這個問題,我們還是得從Feign的原理說起。。

Feign原理

Feign的實現和工作原理,我以前寫過一篇簡單的源碼分析,大家可以簡單花個幾分鐘先鋪墊一下,Feign核心源碼解析。明白了原理,后面理解起來更方便一些。

簡單來說,就是項目中加的@EnableFeignClients這個注解,實現時有一行很重要的代碼:

@Import(FeignClientsRegistrar.class)

這個類實現了ImportBeanDefinitionRegistrar接口,在這個接口的registerBeanDefinitions方法中,可以手動創建BeanDefinition并注冊,之后spring會根據BeanDefinition實例化生成bean,并放入容器中。

Feign就是通過這種方式,掃描添加了@FeignClient注解的接口,然后一步步生成代理對象,具體流程可以看一下下面這張圖:

圖片

后續在請求時,通過代理對象的FeignInvocationHandler進行攔截,并根據對應方法進行處理器的分發,完成后續的http請求操作。

ImportBeanDefinitionRegistrar

上面提到的ImportBeanDefinitionRegistrar,在整個創建FeignClient的代理過程中非常重要, 所以我們先寫一個簡單的例子看一下它的用法。先定義一個實體類:

@Data
@AllArgsConstructor
public class User {
    Long id;
    String name;
}

通過BeanDefinitionBuilder,向這個實體類的構造方法中傳入具體值,最后生成一個BeanDefinition:

public class MyBeanDefinitionRegistrar
        implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
                                        BeanDefinitionRegistry registry) {
        BeanDefinitionBuilder builder
                = BeanDefinitionBuilder.genericBeanDefinition(User.class);
        builder.addConstructorArgValue(1L);
        builder.addConstructorArgValue("Hydra");

        AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
        registry.registerBeanDefinition(User.class.getSimpleName(),beanDefinition);
    }
}

registerBeanDefinitions方法的具體調用時間是在之后的ConfigurationClassPostProcessor執行postProcessBeanDefinitionRegistry方法時,而registerBeanDefinition方法則會將BeanDefinition放進一個map中,后續根據它實例化bean。

在配置類上通過@Import將其引入:

@Configuration
@Import(MyBeanDefinitionRegistrar.class)
public class MyConfiguration {
}

注入這個User測試:

@Service
@RequiredArgsConstructor
public class UserService {
    private final User user;

    public void getUser(){
        System.out.println(user.toString());
    }
}

結果打印,說明我們通過自定義BeanDefinition的方式成功手動創建了一個bean并放入了spring容器中:

User(id=1, name=Hydra)

好了,準備工作鋪墊到這結束,下面開始正式的改造工作。

改造

到這里先總結一下,我們糾結的點就是本地環境需要FeignClient中配置url,但線上環境不需要,并且我們又不想來回修改代碼。

除了像源碼中那樣生成動態代理以及攔截方法,官方文檔中還給我們提供了一個手動創建FeignClient的方法。

https://docs.spring.io/spring-cloud-openfeign/docs/2.2.9.RELEASE/reference/html/#creating-feign-clients-manually

簡單來說,就是我們可以像下面這樣,通過Feign的Builder API來手動創建一個Feign客戶端。

簡單看一下,這個過程中還需要配置Client、Encoder、Decoder、Contract、RequestInterceptor等內容。

  • Client:實際http請求的發起者,如果不涉及負載均衡可以使用簡單的Client.Default,用到負載均衡則可以使用LoadBalancerFeignClient,前面也說了,LoadBalancerFeignClient中的delegate其實使用的也是Client.Default。
  • Encoder和Decoder:Feign的編解碼器,在spring項目中使用對應的SpringEncoder和ResponseEntityDecoder,這個過程中我們借用GsonHttpMessageConverter作為消息轉換器來解析json。
  • RequestInterceptor:Feign的攔截器,一般業務用途比較多,比如添加修改header信息等,這里用不到可以不配。
  • Contract:字面意思是合約,它的作用是將我們傳入的接口進行解析驗證,看注解的使用是否符合規范,然后將關于http的元數據抽取成結果并返回。如果我們使用RequestMapping、PostMapping、GetMapping之類注解的話,那么對應使用的是SpringMvcContract。

其實這里剛需的就只有Contract這一個,其他都是可選的配置項。我們寫一個配置類,把這些需要的東西都注入進去:

@Slf4j
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties({LocalFeignProperties.class})
@Import({LocalFeignClientRegistrar.class})
@ConditionalOnProperty(value = "feign.local.enable", havingValue = "true")
public class FeignAutoConfiguration {
    static {
        log.info("feign local route started");
    }

    @Bean
    @Primary
    public Contract contract(){
        return new SpringMvcContract();
    }

    @Bean(name = "defaultClient")
    public Client defaultClient(){
        return new Client.Default(null,null);
    }

    @Bean(name = "ribbonClient")
    public Client ribbonClient(CachingSpringLoadBalancerFactory cachingFactory,
                               SpringClientFactory clientFactory){
        return new LoadBalancerFeignClient(defaultClient(), cachingFactory,
                clientFactory);
    }

    @Bean
    public Decoder decoder(){
        HttpMessageConverter httpMessageCnotallow=new GsonHttpMessageConverter();
        ObjectFactory<HttpMessageConverters> messageCnotallow= () -> new HttpMessageConverters(httpMessageConverter);
        SpringDecoder springDecoder = new SpringDecoder(messageConverters);
        return new ResponseEntityDecoder(springDecoder);
    }

    @Bean
    public Encoder encoder(){
        HttpMessageConverter httpMessageCnotallow=new GsonHttpMessageConverter();
        ObjectFactory<HttpMessageConverters> messageCnotallow= () -> new HttpMessageConverters(httpMessageConverter);
        return new SpringEncoder(messageConverters);
    }
}

在這個配置類上,還有三行注解,我們一點點解釋。

首先是引入的配置類LocalFeignProperties,里面有三個屬性,分別是是否開啟本地路由的開關、掃描FeignClient接口的包名,以及我們要做的本地路由映射關系,addressMapping中存的是服務名和對應的url地址:

@Data
@Component
@ConfigurationProperties(prefix = "feign.local")
public class LocalFeignProperties {
    // 是否開啟本地路由
    private String enable;

    //掃描FeignClient的包名
    private String basePackage;

    //路由地址映射
    private Map<String,String> addressMapping;
}

下面這行注解則表示只有當配置文件中feign.local.enable這個屬性為true時,才使當前配置文件生效:

@ConditionalOnProperty(value = "feign.local.enable", havingValue = "true")

最后,就是我們重中之重的LocalFeignClientRegistrar了,我們還是按照官方通過ImportBeanDefinitionRegistrar接口構建BeanDefinition然后注冊的思路來實現。

并且,FeignClientsRegistrar的源碼中已經實現好了很多基礎的功能,比如掃掃描包、獲取FeignClient的name、contextId、url等等,所以需要改動的地方非常少,可以放心的大抄特超它的代碼。

先創建LocalFeignClientRegistrar,并注入需要用到的ResourceLoader、BeanFactory、Environment。

@Slf4j
public class LocalFeignClientRegistrar implements
        ImportBeanDefinitionRegistrar, ResourceLoaderAware,
        EnvironmentAware, BeanFactoryAware{

    private ResourceLoader resourceLoader;
    private BeanFactory beanFactory;
    private Environment environment;

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader=resourceLoader;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.envirnotallow=environment;
    }
 
 //先省略具體功能代碼...
}

然后看一下創建BeanDefinition前的工作,這一部分主要完成了包的掃描和檢測@FeignClient注解是否被添加在接口上的測試。下面這段代碼基本上是照搬源碼,除了改動一下掃描包的路徑,使用我們自己在配置文件中配置的包名。

@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    ClassPathScanningCandidateComponentProvider scanner = ComponentScanner.getScanner(environment);
    scanner.setResourceLoader(resourceLoader);
    AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(FeignClient.class);
    scanner.addIncludeFilter(annotationTypeFilter);

    String basePackage =environment.getProperty("feign.local.basePackage");
    log.info("begin to scan {}",basePackage);

    Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents(basePackage);

    for (BeanDefinition candidateComponent : candidateComponents) {
        if (candidateComponent instanceof AnnotatedBeanDefinition) {
            log.info(candidateComponent.getBeanClassName());

            // verify annotated class is an interface
            AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent;
            AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
            Assert.isTrue(annotationMetadata.isInterface(),
                    "@FeignClient can only be specified on an interface");

            Map<String, Object> attributes = annotationMetadata
                    .getAnnotationAttributes(FeignClient.class.getCanonicalName());

            String name = FeignCommonUtil.getClientName(attributes);
            registerFeignClient(registry, annotationMetadata, attributes);
        }
    }
}

接下來創建BeanDefinition并注冊,Feign的源碼中是使用的FeignClientFactoryBean創建代理對象,這里我們就不需要了,直接替換成使用Feign.builder創建。

private void registerFeignClient(BeanDefinitionRegistry registry,
                                 AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
    String className = annotationMetadata.getClassName();
    Class clazz = ClassUtils.resolveClassName(className, null);
    ConfigurableBeanFactory beanFactory = registry instanceof ConfigurableBeanFactory
            ? (ConfigurableBeanFactory) registry : null;
    String contextId = FeignCommonUtil.getContextId(beanFactory, attributes,environment);
    String name = FeignCommonUtil.getName(attributes,environment);

    BeanDefinitionBuilder definition = BeanDefinitionBuilder
            .genericBeanDefinition(clazz, () -> {
                Contract contract = beanFactory.getBean(Contract.class);
                Client defaultClient = (Client) beanFactory.getBean("defaultClient");
                Client ribbonClient = (Client) beanFactory.getBean("ribbonClient");
                Encoder encoder = beanFactory.getBean(Encoder.class);
                Decoder decoder = beanFactory.getBean(Decoder.class);

                LocalFeignProperties properties = beanFactory.getBean(LocalFeignProperties.class);
                Map<String, String> addressMapping = properties.getAddressMapping();

                Feign.Builder builder = Feign.builder()
                        .encoder(encoder)
                        .decoder(decoder)
                        .contract(contract);

                String serviceUrl = addressMapping.get(name);
                String originUrl = FeignCommonUtil.getUrl(beanFactory, attributes, environment);

                Object target;
                if (StringUtils.hasText(serviceUrl)){
                    target = builder.client(defaultClient)
                            .target(clazz, serviceUrl);
                }else if (StringUtils.hasText(originUrl)){
                    target = builder.client(defaultClient)
                            .target(clazz,originUrl);
                }else {
                    target = builder.client(ribbonClient)
                            .target(clazz,"http://"+name);
                }

                return target;
            });

    definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
    definition.setLazyInit(true);
    FeignCommonUtil.validate(attributes);

    AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
    beanDefinition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, className);

    // has a default, won't be null
    boolean primary = (Boolean) attributes.get("primary");
    beanDefinition.setPrimary(primary);

    String[] qualifiers = FeignCommonUtil.getQualifiers(attributes);
    if (ObjectUtils.isEmpty(qualifiers)) {
        qualifiers = new String[] { contextId + "FeignClient" };
    }

    BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className,
            qualifiers);
    BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
}

在這個過程中主要做了這么幾件事:

  • 通過beanFactory拿到了我們在前面創建的Client、Encoder、Decoder、Contract,用來構建Feign.Builder。
  • 通過注入配置類,通過addressMapping拿到配置文件中服務對應的調用url。
  • 通過target方法替換要請求的url,如果配置文件中存在則優先使用配置文件中url,否則使用@FeignClient注解中配置的url,如果都沒有則使用服務名通過LoadBalancerFeignClient訪問。

在resources/META-INF目錄下創建spring.factories文件,通過spi注冊我們的自動配置類:

org.springframework.boot.autoconfigure.EnableAutoCnotallow=\
  com.feign.local.config.FeignAutoConfiguration

最后,本地打包即可:

mvn clean install

測試

引入我們在上面打好的包,由于包中已經包含了spring-cloud-starter-openfeign,所以就不需要再額外引feign的包了:

<dependency>
    <groupId>com.cn.hydra</groupId>
    <artifactId>feign-local-enhancer</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

在配置文件中添加配置信息,啟用組件:

feign:
  local:
    enable: true
    basePackage: com.service
    addressMapping:
      hydra-service: http://127.0.0.1:8088
      trunks-service: http://127.0.0.1:8099

創建一個FeignClient接口,注解的url中我們可以隨便寫一個地址,可以用來測試之后是否會被配置文件中的服務地址覆蓋:

@FeignClient(value = "hydra-service",
 contextId = "hydra-serviceA",
 url = "http://127.0.0.1:8099/")
public interface ClientA {
    @GetMapping("/test/get")
    String get();

    @GetMapping("/test/user")
    User getUser();
}

啟動服務,過程中可以看見了執行掃描包的操作:

在替換url過程中添加一個斷點,可以看到即使在注解中配置了url,也會優先被配置文件中的服務url覆蓋:

使用接口進行測試,可以看到使用上面的代理對象進行了訪問并成功返回了結果:

如果項目需要發布正式環境,只需要將配置feign.local.enable改為false或刪掉,并在項目中添加Feign原始的@EnableFeignClients即可。

總結

本文提供了一個在本地開發過程中簡化Feign調用的思路,相比之前需要麻煩的修改FeignClient中的url而言,能夠節省不少的無效勞動,并且通過這個過程,也可以幫助大家了解我們平常使用的這些組件是怎么與spring結合在一起的,熟悉spring的擴展點。

組件代碼已提交到我的github,有需要的小伙伴們可以自取。

https://github.com/trunks2008/feign-local-enhancer。

責任編輯:姜華 來源: 碼農參上
相關推薦

2025-08-13 01:11:00

2022-10-31 08:47:21

人臉識別按鍵鍵盤

2021-02-26 10:21:35

比特幣投資金融

2020-05-09 16:45:56

ping命令Linux

2022-12-06 17:30:04

2024-10-28 07:10:00

scroll標記前端網格布局

2024-03-25 08:03:32

技術面試ShowMeBug協同編程

2022-05-16 09:36:34

微軟WindowsWindows 11

2021-06-21 05:23:21

Excel消除Excel表格密碼技巧

2018-10-28 17:54:00

分布式事務數據

2014-08-26 11:03:54

2025-08-18 07:35:40

2018-01-12 14:46:01

沖頂大會答題代碼

2021-02-07 08:13:18

@DateTimeFo@NumberFormSpring

2020-08-14 08:19:25

Shell命令行數據

2021-04-01 05:40:53

分庫分表數據庫MySQL

2022-01-04 08:00:48

前端技術Esbuild

2017-11-27 12:24:02

命令行代碼指令

2017-03-07 09:49:18

存儲

2025-02-12 08:21:55

OllamaChatboxDeepSeek
點贊
收藏

51CTO技術棧公眾號

巨大荫蒂视频欧美另类大| 日韩激情综合网| 国产一区二区三区朝在线观看| 国产欧美精品日韩区二区麻豆天美| 国产精品国语对白| 精品一区在线观看视频| 日韩精品福利一区二区三区| 欧美性三三影院| 免费看污久久久| 色呦呦网站入口| 精品欧美在线观看| 久久亚洲影院| 欧美超级免费视 在线| 国产精品久久久久久亚洲色| 日韩精品99| 亚洲成aⅴ人片久久青草影院| 在线欧美一区二区| 2022中文字幕| 国产精品久久一区二区三区不卡| 国产一区欧美日韩| 日韩免费观看av| 91成人福利视频| 精品国产精品| 亚洲国产日韩欧美综合久久 | 99久久亚洲精品蜜臀| 精品88久久久久88久久久| 在线观看av网页| 欧美freesex黑人又粗又大| 亚洲色图欧洲色图婷婷| 神马影院我不卡午夜| 无码国精品一区二区免费蜜桃| 精品一区二区三区蜜桃| 国产精品久久国产精品99gif| 黄色激情视频在线观看| 欧美1区2区视频| 日韩资源在线观看| 91麻豆精品国产91久久综合| 亚洲永久精品唐人导航网址| 日韩精品一区二区三区视频 | 中文字幕亚洲欧美日韩在线不卡| 人妻av一区二区| 视频国产精品| 91精品免费观看| caoporm在线视频| 国产私拍福利精品视频二区| 色婷婷精品大在线视频| 日韩欧美在线播放视频| 在线日韩影院| 色综合天天综合网天天狠天天 | 天天操天天操天天操天天操天天操| 成人在线电影在线观看视频| 亚洲深夜福利在线| 国产91丝袜美女在线播放| 国产成人精品免费视| 国产视频精品va久久久久久| 成人h动漫精品一区| 日本一区福利在线| 日韩精品一区二区视频| 欧美特黄一区二区三区| 天海翼亚洲一区二区三区| 日韩第一页在线| 日韩中文字幕电影| 香蕉久久99| 国产亚洲精品日韩| jizzjizz日本少妇| 一级欧洲+日本+国产| 欧美日韩爱爱视频| 亚州国产精品视频| 日韩va欧美va亚洲va久久| 国产精品亚发布| 国产精品无码久久av| 国产成人欧美日韩在线电影| 国产乱码精品一区二区三区卡 | 久久人人爽爽爽人久久久| 欧美在线激情| 香蕉视频免费在线播放| 亚洲欧美成aⅴ人在线观看| 久久久久亚洲av无码专区喷水| 四虎影院观看视频在线观看| 激情亚洲一区二区三区四区| 欧美日韩在线免费播放| 亚洲综合资源| 亚洲国产精品久久精品怡红院| 91中文字幕永久在线| 国产精品88久久久久久| 久久久亚洲福利精品午夜| 黄色片视频免费| 精品一二线国产| 精品不卡在线| 免费黄色网址在线观看| 午夜精品影院在线观看| 成人免费在线观看视频网站| xxxx日韩| 色伦专区97中文字幕| 国产网址在线观看| 麻豆国产精品777777在线| 国产九区一区在线| 四虎久久免费| 色综合久久中文字幕综合网| 国产福利在线免费| 欧美日韩一本| 欧美成人免费全部| 久久久国产免费| 日韩一区二区视频| 日本午夜精品电影| 18在线观看的| 色综合久久综合中文综合网| www激情五月| 国产不卡av一区二区| 欧美精品免费在线| 国产九色91回来了| 国产精品久久久久久久久久新婚| av免费播放网站| 国产一区美女| 成人激情在线播放| 日本电影一区二区在线观看| 亚洲视频精选在线| 成人中文字幕av| 国产精品xxxav免费视频| 日韩在线观看视频免费| 久草视频一区二区| 波多野结衣中文字幕一区二区三区 | 亚洲片av在线| 久久精品人妻一区二区三区| 久久99精品国产91久久来源| 欧美激情国产日韩| 国产剧情av在线播放| 欧美一级免费大片| 国产成人在线网址| 丝袜脚交一区二区| 激情小说综合网| 9765激情中文在线| 精品国内片67194| 极品盗摄国产盗摄合集| 久久99精品国产91久久来源| 亚洲欧洲精品一区二区三区波多野1战4| 天堂电影一区| 亚洲欧美激情在线视频| 中文字幕亚洲精品在线| 91丨porny丨蝌蚪视频| 青青草精品视频在线| 国语一区二区三区| 久久久伊人日本| 亚洲精品网站在线| 亚洲一区二区三区在线看| 丰满少妇中文字幕| 欧美日韩精品免费观看视频完整| 成人午夜激情网| 国产三区视频在线观看| 91精品国产91久久综合桃花| 久久高清内射无套| 国产成人精品一区二区三区四区 | 欧美一区二区三区在| 久久国产波多野结衣| 精品一区二区三区久久| 少妇熟女一区二区| a看欧美黄色女同性恋| 国语自产精品视频在线看抢先版图片 | 麻豆系列在线观看| 在线成人免费视频| 欧美日韩人妻精品一区二区三区| 国产精品亚洲第一| 欧美精品自拍视频| 夜夜春成人影院| 国产精品免费视频久久久| 日本在线天堂| 欧美大胆人体bbbb| 国产精品日日夜夜| 972aa.com艺术欧美| 动漫av网站免费观看| 精品国产一区探花在线观看 | 麻豆一区一区三区四区| 青青草原一区二区| 日本在线免费| 精品日韩在线观看| 欧美黑人一区二区| 国产精品久久久久久久久晋中| 亚洲热在线视频| 在线亚洲激情| 一本一道久久a久久精品综合| 蜜桃在线一区| 日本最新高清不卡中文字幕| 免费在线你懂的| 亚洲第一视频网| 国产精品第六页| 亚洲精品乱码久久久久| 少妇毛片一区二区三区| 激情文学综合插| 777av视频| 久久精品国产www456c0m| 岛国一区二区三区高清视频| 黄瓜视频成人app免费| 麻豆成人在线看| 日本天堂影院在线视频| 91精品国产日韩91久久久久久| 日韩精品在线观看免费| 亚洲色图视频网| 欧美大波大乳巨大乳| 国产高清在线精品| 午夜宅男在线视频| 国产一区成人| 8x8x华人在线| 日韩aaaa| 欧美日韩精品综合| 这里视频有精品| 国产日韩中文字幕在线| 天堂中文在线播放| 久久久久亚洲精品| 日本激情在线观看| 国产亚洲一区二区精品| 日韩在线视频观看免费| 91麻豆精品国产91久久久久久久久| 麻豆精品久久久久久久99蜜桃| 亚洲精品v日韩精品| 国产欧美小视频| 久久蜜臀中文字幕| 国产二级一片内射视频播放 | 亚洲自拍偷拍网址| 美女色狠狠久久| 日本免费在线精品| 国产亚洲成av人片在线观看| 欧美日韩成人在线观看| 免费大片在线观看www| 亚洲一级片在线看| 欧美伦理影视网| 日韩av综合网| 日批视频免费播放| 日韩你懂的在线观看| 国产一区二区在线播放视频| 欧美性受极品xxxx喷水| 中文字幕在线播| 日韩欧美成人网| 欧美日韩综合在线观看| 欧美日韩视频在线| 国产精品视频久久久久久久| 亚洲一区二区三区影院| 青青草成人免费| 亚洲一卡二卡三卡四卡| 澳门黄色一级片| 亚洲黄色尤物视频| 精品一区在线视频| 亚洲大尺度视频在线观看| 久久亚洲AV无码| 亚洲第一激情av| 日韩激情在线播放| 欧美日韩国产麻豆| 国产高潮久久久| 日韩欧美一区二区在线| 国产又大又粗又爽| 91成人看片片| 伊人成人在线观看| 制服丝袜激情欧洲亚洲| 97人妻一区二区精品免费视频 | 欧美 日韩 国产 成人 在线| 日韩精品一区二区三区蜜臀 | 最近中文字幕日韩精品| 亚洲成人三级| 欧美美最猛性xxxxxx| free性欧美| 4388成人网| 欧美性片在线观看| 成人网在线视频| 6080成人| 久热这里只精品99re8久 | 99久久婷婷国产精品综合| 欧美图片一区二区| 国产精品久久夜| 成人免费视频网站入口::| 亚洲国产另类精品专区| 免费黄色网址在线| 在线播放亚洲一区| 天天干天天做天天操| 亚洲日韩中文字幕| 国产超级va在线视频| 久久久女女女女999久久| 成人勉费视频| 91视频国产精品| 日韩激情啪啪| 中文字幕乱码一区二区三区| 黄色av成人| 国产97色在线 | 日韩| 国产精品白丝jk黑袜喷水| 精品人妻一区二区免费视频| 中文字幕高清不卡| 国产一级做a爰片在线看免费| 一本色道久久综合亚洲aⅴ蜜桃| 国产免费黄色片| 日韩h在线观看| 91最新在线视频| 日韩av免费看网站| 日韩在线亚洲| 亚洲精品乱码久久久久久蜜桃91| 午夜精品久久| 精品精品国产三级a∨在线| 日韩美女视频免费看| 欧美网站免费| 激情小说综合区| 香蕉av一区二区| av7777777| 国产自产视频一区二区三区| 波多野结衣福利| 亚洲美腿欧美偷拍| 无码一区二区三区| 涩视频在线观看| 国产欧美在线观看一区| 青青草精品在线视频| 色悠悠久久综合| 亚洲黄色在线观看视频| 日韩网站免费观看| 日本在线视频免费| 欧美日韩大陆在线| 免费在线视频一级不卡| 欧美第一黄网免费网站| 欧美日韩视频免费看| 久热这里只精品99re8久| 欧美不卡高清| 国内av一区二区| 欧美国产成人在线| 国产又爽又黄又嫩又猛又粗| 狠狠综合久久av一区二区小说| 国产日本精品视频| 国产亚洲人成网站在线观看| 咪咪网在线视频| 国产精品推荐精品| 国内精品久久久久国产盗摄免费观看完整版| 日韩一级理论片| 久久久久国产成人精品亚洲午夜| 精品无码av在线| 欧美一区二区高清| 国产激情在线视频| 国产一区视频在线播放| 欧美精品一二| 欧美婷婷精品激情| 国产婷婷色一区二区三区| 中文字幕免费高清网站| 亚洲男人第一网站| 成人欧美大片| 欧美亚洲一级二级| 男人的天堂亚洲| 国精产品一区一区三区免费视频| 欧美日韩一区二区在线| 天堂在线一二区| 欧美在线一级va免费观看| 午夜精品福利影院| 日韩一级在线免费观看| 国产三级精品视频| 中文字幕在线视频免费| 日韩一区二区三区国产| 国产va免费精品观看精品| 日韩视频一二三| 成人性生交大片免费看视频在线 | 亚洲mv大片欧洲mv大片| 一级淫片在线观看| 亚洲黄色免费电影| 人妻中文字幕一区| 欧美亚洲国产视频小说| 国产欧美日韩视频在线| 欧美一级特黄a| 亚洲视频 欧洲视频| 国产综合无码一区二区色蜜蜜| 久久久久久久香蕉网| 五月天亚洲色图| 亚洲一二三区av| 亚洲欧美一区二区三区久本道91| 国产suv一区二区| 91超碰caoporn97人人| 国产毛片一区二区三区| 污污的视频免费| 亚洲高清中文字幕| 国产资源在线播放| 成人a级免费视频| 亚洲成色精品| 久久久久久成人网| 日韩三级高清在线| 久久男人av资源站| 亚洲巨乳在线观看| 国产.精品.日韩.另类.中文.在线.播放| 日韩精品人妻中文字幕| 尤物tv国产一区| 日本精品国产| 日本在线观看a| 自拍偷拍亚洲欧美日韩| 色婷婷中文字幕| 国产精自产拍久久久久久蜜| 欧美日韩国内| 你懂得视频在线观看| 精品久久久久久综合日本欧美| av资源亚洲| 8x8x华人在线| 中文字幕欧美激情| 亚洲黄色在线播放| 国产日韩在线看片| 香蕉久久国产| 免费一级全黄少妇性色生活片| 亚洲天堂色网站| 国产色噜噜噜91在线精品| 久久人人爽av| 欧美性感美女h网站在线观看免费| 国产1区在线| 欧美一区激情视频在线观看|