如何理解SpringCloud網(wǎng)關(guān)服務(wù)zuul

本篇內(nèi)容介紹了“如何理解Spring Cloud網(wǎng)關(guān)服務(wù)zuul ”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

十余年的望江網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開(kāi)發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。成都營(yíng)銷網(wǎng)站建設(shè)的優(yōu)勢(shì)是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整望江建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無(wú)論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)從事“望江網(wǎng)站設(shè)計(jì)”,“望江網(wǎng)站推廣”以來(lái),每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。

如何理解Spring Cloud網(wǎng)關(guān)服務(wù)zuul 可以看到服務(wù)端口和注冊(cè)中心都在配置文件中配置化

屬性信息

上一篇我們講了如何搭建網(wǎng)關(guān)zuul 服務(wù)。實(shí)現(xiàn)了基本的轉(zhuǎn)發(fā)功能。這篇文章我們要講述zuul過(guò)濾器的使用。和三個(gè)參數(shù)的使用

sensitiveHeaders 屬性關(guān)鍵字聲明:Spring Cloud微服務(wù)實(shí)戰(zhàn) 書(shū)中意思為放行字段。而小編在官方文檔查看到是忽略不放行的意思。請(qǐng)注意此處,看過(guò)Spring Cloud微服務(wù)實(shí)戰(zhàn)同學(xué)可以用小編實(shí)例代碼印證
  • ribbon-isolation-strategy

    • 信號(hào)量模式 在該模式下,接收請(qǐng)求和執(zhí)行下游依賴在同一個(gè)線程內(nèi)完成,不存在線程上下文切換所帶來(lái)的性能開(kāi)銷。默認(rèn)信號(hào)量模式

    • 線程池 在該模式下,用戶請(qǐng)求會(huì)被提交到各自的線程池中執(zhí)行,把執(zhí)行每個(gè)下游服務(wù)的線程分離,從而達(dá)到資源隔離的作用。當(dāng)線程池來(lái)不及處理并且請(qǐng)求隊(duì)列塞滿時(shí),新進(jìn)來(lái)的請(qǐng)求將快速失敗,可以避免依賴問(wèn)題擴(kuò)散。

    • 隔離機(jī)制 Spring Cloud 默認(rèn)的隔離機(jī)制hystrix 去做限流、熔斷、隔離。一個(gè)是基于信號(hào)量。一個(gè)是基于線程池去完成

  • ignored-services

    • 忽略指定的服務(wù)

  • ignored—patterns

    • 忽略指定的url 路徑

  • ignored-headers

    • 忽略指定的header 頭部信息

  • sensitiveHeaders

    • 字段比較敏感,不希望傳遞給下游微服務(wù)。 設(shè)置空沒(méi)有要忽略的敏感字段。全部傳給下游服務(wù)

在上面ignored-headers 和 sensitiveHeaders 職責(zé)是有重疊的部分。其實(shí)他們是有著關(guān)系存在的。sensitiveHeaders的內(nèi)容會(huì)最終合并到ignored-headers內(nèi)。

驗(yàn)證一下 sensitiveHeaders 字段設(shè)置全區(qū)忽略 X-ABC

消費(fèi)者服務(wù) sensitiveHeaders 指定忽略 X-ABC,Authorization

服務(wù)提供者轉(zhuǎn)發(fā)不做任何調(diào)整 在服務(wù)提供者 和 服務(wù)消費(fèi)者 服務(wù)上。都創(chuàng)建一個(gè) UrlFilter 攔截器 先設(shè)置一下 zuul的yml文件

zuul:
  host:
    # 目標(biāo)主機(jī)的最大連接數(shù),默認(rèn)值為200
    max-total-connections: 500
    # 每個(gè)主機(jī)的初始連接數(shù),默認(rèn)值為20
    max-per-route-connections: 100
  routes:
    discovery-server:
      path: /server/**
      serviceId: cloud-discovery-server
    client-common:
      path: /client/**
      serviceId: cloud-discovery-client
      sensitiveHeaders: X-ABC,X-Foo
  # 所有路由的默認(rèn)Hystrix隔離模式(ExecutionIsolationStrategy)為SEMAPHORE。如果此隔離模式是首選,則zuul.ribbonIsolationStrategy可以更改為THREAD
  ribbon-isolation-strategy: thread
  # 這個(gè)屬性意思,* 忽略未指定的服務(wù)列表 有具體服務(wù)名稱 忽略指定的服務(wù)
  ignored-services: "*"
  # 忽略指定的url 路徑
  ignored—patterns:
  # 忽略指定的header 頭部信息
  ignored-headers: Authorization
  # 字段比較敏感,不希望傳遞給下游微服務(wù)。 設(shè)置空沒(méi)有要忽略的敏感字段。全部傳給下游服務(wù)
  sensitive-headers: X-ABC
  ribbon:
    eager-load:
      # 強(qiáng)制加載,不設(shè)置會(huì)進(jìn)行懶加載。spring 第一次請(qǐng)求會(huì)非常慢
      enabled: true
package com.xian.cloud.filter;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Enumeration;

/**
 * <Description>
 *
 * @author xianliru@100tal.com
 * @version 1.0
 * @createDate 2019/10/29 13:57
 */
@WebFilter(filterName = "test",urlPatterns = "/*")
@Slf4j
public class UrlFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.warn("UrlFilter init.......");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        Enumeration<String> attributeNames = servletRequest.getAttributeNames();
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        String requestURI = req.getRequestURI();
        String header = req.getHeader("X-Foo");
        String abc = req.getHeader("X-ABC");
        String authorization = req.getHeader("Authorization");
        String tom = req.getParameter("tom");
        String mike = req.getParameter("mike");
        log.warn("過(guò)濾器:請(qǐng)求地址"+requestURI);
        log.warn("uuid:{}",header);
        log.warn("abc uuid:{}",abc);
        log.warn("authorization :{}",authorization);
        log.warn("tom :{}",tom);
        log.warn("mike :{}",mike);
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {
        log.warn(" 過(guò)濾器被銷毀");
    }
}

啟動(dòng)類上添加 @ServletComponentScan 用于掃描 過(guò)濾器 @WebFilter注解

package com.xian.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

/**
 * @Author: xlr
 * @Date: Created in 2:44 PM 2019/10/27
 */
@EnableDiscoveryClient
@SpringBootApplication
//新增注解
@ServletComponentScan
public class DiscoveryServerApplication {


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

使用postman 請(qǐng)求服務(wù) 服務(wù)端打印日志

2019-10-30 11:10:35.822  WARN 48882 --- [nio-9012-exec-8] com.xian.cloud.filter.UrlFilter          : 過(guò)濾器:請(qǐng)求地址/server/hello
2019-10-30 11:10:35.826  WARN 48882 --- [nio-9012-exec-8] com.xian.cloud.filter.UrlFilter          : uuid:x-foo
2019-10-30 11:10:35.826  WARN 48882 --- [nio-9012-exec-8] com.xian.cloud.filter.UrlFilter          : abc uuid:null
2019-10-30 11:10:35.827  WARN 48882 --- [nio-9012-exec-8] com.xian.cloud.filter.UrlFilter          : authorization :null
2019-10-30 11:10:35.827  WARN 48882 --- [nio-9012-exec-8] com.xian.cloud.filter.UrlFilter          : tom :null
2019-10-30 11:10:35.828  WARN 48882 --- [nio-9012-exec-8] com.xian.cloud.filter.UrlFilter          : mike :null
2019-10-30 11:10:35.852  INFO 48882 --- [nio-9012-exec-8] c.x.cloud.controller.DiscoverCotroller   : invoked name = xian age = 20

sensitive-headers、ignored-headers (abc、authorization都在zuul被過(guò)濾掉)全局設(shè)置生效。

我們?cè)俅握?qǐng)求client 服務(wù)接口

在看一下 客戶端打印日志

2019-10-30 11:17:05.813  WARN 50223 --- [nio-9011-exec-3] com.xian.cloud.filter.UrlFilter          : 過(guò)濾器:請(qǐng)求地址/client/test
2019-10-30 11:17:05.813  WARN 50223 --- [nio-9011-exec-3] com.xian.cloud.filter.UrlFilter          : uuid:null
2019-10-30 11:17:05.813  WARN 50223 --- [nio-9011-exec-3] com.xian.cloud.filter.UrlFilter          : abc uuid:null
2019-10-30 11:17:05.813  WARN 50223 --- [nio-9011-exec-3] com.xian.cloud.filter.UrlFilter          : authorization :null
2019-10-30 11:17:05.813  WARN 50223 --- [nio-9011-exec-3] com.xian.cloud.filter.UrlFilter          : tom :null
2019-10-30 11:17:05.813  WARN 50223 --- [nio-9011-exec-3] com.xian.cloud.filter.UrlFilter          : mike :null

全局設(shè)置,和單個(gè)服務(wù)定制設(shè)置 全部生效。

過(guò)濾器

spring cloud Zuul包含了對(duì)請(qǐng)求的路由和過(guò)濾2個(gè)功能。路由功能負(fù)責(zé)將請(qǐng)求轉(zhuǎn)發(fā)到具體的微服務(wù)上,而過(guò)濾器負(fù)責(zé)對(duì)請(qǐng)求的處理過(guò)程進(jìn)行干預(yù),是實(shí)現(xiàn)權(quán)限校驗(yàn)、服務(wù)聚合等功能的基礎(chǔ)。

在實(shí)際運(yùn)行時(shí),路由映射和請(qǐng)求轉(zhuǎn)發(fā)是由幾個(gè)不同的過(guò)濾器完成的。每一個(gè)進(jìn)入zuul的http請(qǐng)求都會(huì)經(jīng)過(guò)一系列的過(guò)濾器處理鏈得到請(qǐng)求響應(yīng)并返回給客戶端。

zuul1.0 對(duì)流量的路由分發(fā)和過(guò)濾倆個(gè)功能。路由讓流量分發(fā)到內(nèi)部的微服務(wù)集群上。過(guò)濾對(duì)請(qǐng)求進(jìn)行修改或者做個(gè)性化處理。實(shí)現(xiàn)鑒權(quán)、安全、監(jiān)控、日志等。

運(yùn)行過(guò)程中,流量請(qǐng)求會(huì)經(jīng)過(guò)一系列的過(guò)濾器最終轉(zhuǎn)發(fā)到對(duì)應(yīng)的服務(wù)上去。

zuul 路由器主要根絕FilterType類型分為四種類型。一個(gè)靜態(tài)響應(yīng)StaticResponseFilter

  • pre 在請(qǐng)求被路由之前調(diào)用。對(duì)應(yīng)spring boot 工程Filer 中的 doFilter 方法。

  • route 用于路由到原點(diǎn),使用http 協(xié)議調(diào)用。可以理解負(fù)責(zé)轉(zhuǎn)發(fā)請(qǐng)求到微服務(wù)

  • error 錯(cuò)誤處理,在處理請(qǐng)求發(fā)生錯(cuò)誤時(shí)被調(diào)用

  • post 用于后路由過(guò)濾,在route和error過(guò)濾器之后被調(diào)用

自定義過(guò)濾器

FilterTypeEnum 枚舉類

package com.xian.cloud.enums;

import lombok.Getter;

/**
 * <Description>
 *
 * @author xianliru@100tal.com
 * @version 1.0
 * @createDate 2019/10/29 13:01
 */
@Getter
public enum FilterTypeEnum {

    PRE("pre","前置過(guò)濾"),
    ROUTE("route","路由請(qǐng)求時(shí)被調(diào)用"),
    POST("post","后置過(guò)濾器"),
    ERROR("error","后置錯(cuò)誤處理");

    private String type;

    private String desc;

    FilterTypeEnum(String type,String desc){
        this.type = type;
        this.desc = desc;
    }
}

過(guò)濾器代碼編寫(xiě)

package com.xian.cloud.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.xian.cloud.enums.FilterTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * <Description>
 *
 * @author xianliru@100tal.com
 * @version 1.0
 * @createDate 2019/10/29 12:57
 */
@Component
@Slf4j
public class BannedAccessFilter extends ZuulFilter {

    /**
     * 路由器的類型指定
     * @return
     */
    @Override
    public String filterType() {
        return FilterTypeEnum.PRE.getType();
    }

    /**
     * 執(zhí)行順序 數(shù)值越小。執(zhí)行順序越靠前
     * @return
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * 返回一個(gè)boolean值來(lái)判斷該過(guò)濾器是否要執(zhí)行。我們可以通過(guò)此方法來(lái)指定過(guò)濾器的有效范圍。
     * @return
     */
    @Override
    public boolean shouldFilter() {
        RequestContext context = RequestContext.getCurrentContext();
        HttpServletRequest request = context.getRequest();
        String requestURI = request.getRequestURI();
        if(StringUtils.isNotBlank(requestURI) && (requestURI.contains("client") ||
            requestURI.contains("server"))){
            return true;
        }
        return false;
    }

    /**
     * 核心業(yè)務(wù)處理
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
        RequestContext context = RequestContext.getCurrentContext();
        HttpServletResponse servletResponse = context.getResponse();
        String uuid = UUID.randomUUID().toString();
		//重寫(xiě) X-Foo X-ABC值
        context.addZuulRequestHeader("X-Foo", uuid);
        context.addZuulRequestHeader("X-ABC",uuid);
        log.info("X-Foo:{}",uuid);
        return null;
    }
}

run方法是核心業(yè)務(wù)處理的方法 postman 請(qǐng)求 http://127.0.0.1:9083/server/server/hello?name=1111 攜帶之前設(shè)置的header參數(shù) 如何理解Spring Cloud網(wǎng)關(guān)服務(wù)zuul

服務(wù)器打印日志

2019-10-30 14:44:44.841  WARN 48882 --- [nio-9012-exec-9] com.xian.cloud.filter.UrlFilter          : 過(guò)濾器:請(qǐng)求地址/server/hello
2019-10-30 14:44:44.842  WARN 48882 --- [nio-9012-exec-9] com.xian.cloud.filter.UrlFilter          : uuid:a65b2244-e9a5-456d-968f-eaaba45b6f49
2019-10-30 14:44:44.842  WARN 48882 --- [nio-9012-exec-9] com.xian.cloud.filter.UrlFilter          : abc uuid:null
2019-10-30 14:44:44.842  WARN 48882 --- [nio-9012-exec-9] com.xian.cloud.filter.UrlFilter          : authorization :null
2019-10-30 14:44:44.842  WARN 48882 --- [nio-9012-exec-9] com.xian.cloud.filter.UrlFilter          : tom :null
2019-10-30 14:44:44.842  WARN 48882 --- [nio-9012-exec-9] com.xian.cloud.filter.UrlFilter          : mike :null
2019-10-30 14:44:44.844  INFO 48882 --- [nio-9012-exec-9] c.x.cloud.controller.DiscoverCotroller   : invoked name = 1111 age = 20

可以看到 postman設(shè)置的X-Foo 值被 BannedAccessFilter run方法業(yè)務(wù)覆蓋掉了

攔截的請(qǐng)求對(duì)參數(shù)的修改操作都是在這里。這里單獨(dú)介紹一下 RequestContext 這個(gè)類

官方文檔描述

To pass information between filters, Zuul uses a RequestContext. Its data is held in a ThreadLocal specific to
each request. Information about where to route requests, errors and the actual HttpServletRequest and
HttpServletResponse are stored there. The RequestContext extends ConcurrentHashMap, so anything can be
stored in the context. FilterConstants contains the keys that are used by the filters installed by Spring Cloud
Netflix (more on these later).

請(qǐng)求要在過(guò)濾器之間傳遞信息,Zuul使用 RequestContext。其數(shù)據(jù)按照每個(gè)請(qǐng)求的ThreadLocal進(jìn)行。關(guān)于路由請(qǐng)求,錯(cuò)誤以及實(shí)際HttpServletRequest和HttpServletResponse的路由信息。RequestContext擴(kuò)展ConcurrentHashMap,所以任何東西都可以存儲(chǔ)在上下文中。

ThreadLocal保證了請(qǐng)求與請(qǐng)求都是獨(dú)立的,相互不影響。擴(kuò)展ConcurrentHashMap 保證內(nèi)部過(guò)濾器并發(fā)操作的安全性。

RequestContext 的特殊性。需要單獨(dú)在創(chuàng)建一個(gè)過(guò)濾器來(lái)展示RequestContext 的使用

需要注意點(diǎn) 都在代碼注釋上描述出來(lái)了。請(qǐng)根據(jù)自己的業(yè)務(wù)場(chǎng)景定制自己的過(guò)濾器。

package com.xian.cloud.filter;

import com.alibaba.fastjson.JSONObject;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.netflix.zuul.http.HttpServletRequestWrapper;
import com.netflix.zuul.http.ServletInputStreamWrapper;
import com.xian.cloud.enums.FilterTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <Description>
 *
 * @author xianliru@100tal.com
 * @version 1.0
 * @createDate 2019/10/29 16:07
 */
@Component
@Slf4j
public class UpdateParamsFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return FilterTypeEnum.PRE.getType();
    }

    @Override
    public int filterOrder() {
        return 1;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {


        // 獲取到request
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        // 獲取請(qǐng)求參數(shù)name
        String name = "";
        try {

            // 請(qǐng)求方法
            String method = request.getMethod();
            log.info(String.format("%s >>> %s", method, request.getRequestURL().toString()));
            // 獲取請(qǐng)求的輸入流
            InputStream in = request.getInputStream();
            String body = StreamUtils.copyToString(in, Charset.forName("UTF-8"));
            // 如果body為空初始化為空json
            if (StringUtils.isBlank(body)) {
                body = "{}";
            }
            log.info("body" + body);
            // 轉(zhuǎn)化成json
            JSONObject json = JSONObject.parseObject(body);
            // 關(guān)鍵步驟,一定要get一下,下面才能取到值requestQueryParams
            if ("GET".equals(method)) {
                request.getParameterMap();
                Map<String, List<String>> requestQueryParams = ctx.getRequestQueryParams();
                if (requestQueryParams == null) {
                    requestQueryParams = new HashMap<>();
                }
                //TODO  寫(xiě)業(yè)務(wù)代碼
                List<String> arrayList = new ArrayList<>();
                arrayList.add("hello mike");
                //requestQueryParams.put("mike",arrayList);
                ctx.setRequestQueryParams(requestQueryParams);
            }
            //post和put需重寫(xiě)HttpServletRequestWrapper
            if ("POST".equals(method) || "PUT".equals(method)) {
                //TODO 在這里修改或者添加內(nèi)容
                json.put("tom","hello tom");
                String newBody = json.toString();
                final byte[] reqBodyBytes = newBody.getBytes();
                // 重寫(xiě)上下文的HttpServletRequestWrapper
                ctx.setRequest(new HttpServletRequestWrapper(request) {
                    @Override
                    public ServletInputStream getInputStream() throws IOException {
                        return new ServletInputStreamWrapper(reqBodyBytes);
                    }
                    @Override
                    public int getContentLength() {
                        return reqBodyBytes.length;
                    }
                    @Override
                    public long getContentLengthLong() {
                        return reqBodyBytes.length;
                    }
                });
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

“如何理解Spring Cloud網(wǎng)關(guān)服務(wù)zuul ”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

文章名稱:如何理解SpringCloud網(wǎng)關(guān)服務(wù)zuul
網(wǎng)頁(yè)地址:http://m.kartarina.com/article8/pojpip.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供建站公司Google、動(dòng)態(tài)網(wǎng)站、ChatGPT、網(wǎng)站設(shè)計(jì)、

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

搜索引擎優(yōu)化
主站蜘蛛池模板: 免费人妻av无码专区| 亚洲AV无码成人专区片在线观看| 亚洲AV无码久久久久网站蜜桃| 久久午夜无码鲁丝片直播午夜精品| 日韩爆乳一区二区无码| 亚洲AV无码XXX麻豆艾秋| 超清纯白嫩大学生无码网站| 亚洲AV无码第一区二区三区| 久久久久成人精品无码中文字幕 | 日韩AV无码中文无码不卡电影| 亚洲色无码国产精品网站可下载| 日韩av无码国产精品| 亚洲AV无码精品色午夜果冻不卡| 亚洲人成无码网站在线观看| 夜夜添无码试看一区二区三区| 人妻丰满熟AV无码区HD| 日韩人妻无码精品久久久不卡| 精品无码成人片一区二区| AV无码久久久久不卡网站下载| 亚洲&#228;v永久无码精品天堂久久| 色偷偷一区二区无码视频| 国产成年无码久久久免费| 真人无码作爱免费视频| 久久人午夜亚洲精品无码区| 久久久亚洲精品无码| 中文人妻无码一区二区三区| 人妻无码久久精品| 97无码免费人妻超级碰碰夜夜| 精品久久久无码人妻中文字幕| 久久久久久AV无码免费网站| 免费无码又爽又刺激一高潮| 久久久国产精品无码一区二区三区 | 日韩人妻无码精品久久免费一| 精品久久久无码中文字幕天天| 亚洲a无码综合a国产av中文| 免费无码又黄又爽又刺激| 亚洲熟妇av午夜无码不卡| 亚洲精品无码中文久久字幕| 亚洲熟妇无码一区二区三区| 亚洲另类无码一区二区三区| AV无码久久久久不卡网站下载|