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

項目自從用了接口請求合并,效率直接加倍!

開發 項目管理
請求合并,批量的辦法能大幅節省被調用系統的連接資源,本例是以數據庫為例,其他RPC調用也是類似的道理。缺點就是請求的時間在執行實際的邏輯之前增加了等待時間,不適合低并發的場景。

大家好,我是不才陳某~

請求合并到底有什么意義呢?我們來看下圖。

圖片

假設我們3個用戶(用戶id分別是1、2、3),現在他們都要查詢自己的基本信息,請求到服務器,服務器端請求數據庫,發出3次請求。我們都知道數據庫連接資源是相當寶貴的,那么我們怎么盡可能節省連接資源呢?

這里把數據庫換成被調用的遠程服務,也是同樣的道理。

我們改變下思路,如下圖所示。

圖片

我們在服務器端把請求合并,只發出一條SQL查詢數據庫,數據庫返回后,服務器端處理返回數據,根據一個唯一請求ID,把數據分組,返回給對應用戶。

技術手段

  • LinkedBlockQueue 阻塞隊列
  • ScheduledThreadPoolExecutor 定時任務線程池
  • CompleteableFuture future 阻塞機制(Java 8 的 CompletableFuture 并沒有 timeout 機制,后面優化,使用了隊列替代)

代碼實現

查詢用戶的代碼

public interface UserService {

Map<String, Users> queryUserByIdBatch(List<UserWrapBatchService.Request> userReqs);
}
@Service
public class UserServiceImpl implements UserService {

@Resource
private UsersMapper usersMapper;

@Override
public Map<String, Users> queryUserByIdBatch(List<UserWrapBatchService.Request> userReqs) {
// 全部參數
List<Long> userIds = userReqs.stream().map(UserWrapBatchService.Request::getUserId).collect(Collectors.toList());
QueryWrapper<Users> queryWrapper = new QueryWrapper<>();
// 用in語句合并成一條SQL,避免多次請求數據庫的IO
queryWrapper.in("id", userIds);
List<Users> users = usersMapper.selectList(queryWrapper);
Map<Long, List<Users>> userGroup = users.stream().collect(Collectors.groupingBy(Users::getId));
HashMap<String, Users> result = new HashMap<>();
userReqs.forEach(val -> {
List<Users> usersList = userGroup.get(val.getUserId());
if (!CollectionUtils.isEmpty(usersList)) {
result.put(val.getRequestId(), usersList.get(0));
} else {
// 表示沒數據
result.put(val.getRequestId(), null);
}
});
return result;
}
}

合并請求的實現

package com.springboot.sample.service.impl;

import com.springboot.sample.bean.Users;
import com.springboot.sample.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.*;

/***
* zzq
* 包裝成批量執行的地方
* */
@Service
public class UserWrapBatchService {
@Resource
private UserService userService;

/**
* 最大任務數
**/
public static int MAX_TASK_NUM = 100;


/**
* 請求類,code為查詢的共同特征,例如查詢商品,通過不同id的來區分
* CompletableFuture將處理結果返回
*/
public class Request {
// 請求id 唯一
String requestId;
// 參數
Long userId;
//TODO Java 8 的 CompletableFuture 并沒有 timeout 機制
CompletableFuture<Users> completableFuture;

public String getRequestId() {
return requestId;
}

public void setRequestId(String requestId) {
this.requestId = requestId;
}

public Long getUserId() {
return userId;
}

public void setUserId(Long userId) {
this.userId = userId;
}

public CompletableFuture getCompletableFuture() {
return completableFuture;
}

public void setCompletableFuture(CompletableFuture completableFuture) {
this.completableFuture = completableFuture;
}
}

/*
LinkedBlockingQueue是一個阻塞的隊列,內部采用鏈表的結果,通過兩個ReenTrantLock來保證線程安全
LinkedBlockingQueue與ArrayBlockingQueue的區別
ArrayBlockingQueue默認指定了長度,而LinkedBlockingQueue的默認長度是Integer.MAX_VALUE,也就是無界隊列,在移除的速度小于添加的速度時,容易造成OOM。
ArrayBlockingQueue的存儲容器是數組,而LinkedBlockingQueue是存儲容器是鏈表
兩者的實現隊列添加或移除的鎖不一樣,ArrayBlockingQueue實現的隊列中的鎖是沒有分離的,即添加操作和移除操作采用的同一個ReenterLock鎖,
而LinkedBlockingQueue實現的隊列中的鎖是分離的,其添加采用的是putLock,移除采用的則是takeLock,這樣能大大提高隊列的吞吐量,
也意味著在高并發的情況下生產者和消費者可以并行地操作隊列中的數據,以此來提高整個隊列的并發性能。
*/
private final Queue<Request> queue = new LinkedBlockingQueue();

@PostConstruct
public void init() {
//定時任務線程池,創建一個支持定時、周期性或延時任務的限定線程數目(這里傳入的是1)的線程池
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);

scheduledExecutorService.scheduleAtFixedRate(() -> {
int size = queue.size();
//如果隊列沒數據,表示這段時間沒有請求,直接返回
if (size == 0) {
return;
}
List<Request> list = new ArrayList<>();
System.out.println("合并了 [" + size + "] 個請求");
//將隊列的請求消費到一個集合保存
for (int i = 0; i < size; i++) {
// 后面的SQL語句是有長度限制的,所以還要做限制每次批量的數量,超過最大任務數,等下次執行
if (i < MAX_TASK_NUM) {
list.add(queue.poll());
}
}
//拿到我們需要去數據庫查詢的特征,保存為集合
List<Request> userReqs = new ArrayList<>();
for (Request request : list) {
userReqs.add(request);
}
//將參數傳入service處理, 這里是本地服務,也可以把userService 看成RPC之類的遠程調用
Map<String, Users> response = userService.queryUserByIdBatch(userReqs);
//將處理結果返回各自的請求
for (Request request : list) {
Users result = response.get(request.requestId);
request.completableFuture.complete(result); //completableFuture.complete方法完成賦值,這一步執行完畢,下面future.get()阻塞的請求可以繼續執行了
}
}, 100, 10, TimeUnit.MILLISECONDS);
//scheduleAtFixedRate是周期性執行 schedule是延遲執行 initialDelay是初始延遲 period是周期間隔 后面是單位
//這里我寫的是 初始化后100毫秒后執行,周期性執行10毫秒執行一次
}

public Users queryUser(Long userId) {
Request request = new Request();
// 這里用UUID做請求id
request.requestId = UUID.randomUUID().toString().replace("-", "");
request.userId = userId;
CompletableFuture<Users> future = new CompletableFuture<>();
request.completableFuture = future;
//將對象傳入隊列
queue.offer(request);
//如果這時候沒完成賦值,那么就會阻塞,直到能夠拿到值
try {
return future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return null;
}
}

控制層調用

/***
* 請求合并
* */
@RequestMapping("/merge")
public Callable<Users> merge(Long userId) {
return new Callable<Users>() {
@Override
public Users call() throws Exception {
return userBatchService.queryUser(userId);
}
};
}

Callable是什么可以參考:

??https://blog.csdn.net/baidu_19473529/article/details/123596792??

模擬高并發查詢的代碼

package com.springboot.sample;

import org.springframework.web.client.RestTemplate;

import java.util.Random;
import java.util.concurrent.CountDownLatch;

public class TestBatch {
private static int threadCount = 30;

private final static CountDownLatch COUNT_DOWN_LATCH = new CountDownLatch(threadCount); //為保證30個線程同時并發運行

private static final RestTemplate restTemplate = new RestTemplate();

public static void main(String[] args) {


for (int i = 0; i < threadCount; i++) {//循環開30個線程
new Thread(new Runnable() {
public void run() {
COUNT_DOWN_LATCH.countDown();//每次減一
try {
COUNT_DOWN_LATCH.await(); //此處等待狀態,為了讓30個線程同時進行
} catch (InterruptedException e) {
e.printStackTrace();
}

for (int j = 1; j <= 3; j++) {
int param = new Random().nextInt(4);
if (param <=0){
param++;
}
String responseBody = restTemplate.getForObject("http://localhost:8080/asyncAndMerge/merge?userId=" + param, String.class);
System.out.println(Thread.currentThread().getName() + "參數 " + param + " 返回值 " + responseBody);
}
}
}).start();

}
}
}

測試效果

圖片

圖片

要注意的問題

  • Java 8 的 CompletableFuture 并沒有 timeout 機制
  • 后面的SQL語句是有長度限制的,所以還要做限制每次批量的數量,超過最大任務數,等下次執行(本例中加了MAX_TASK_NUM判斷)

使用隊列的超時解決Java 8 的 CompletableFuture 并沒有 timeout 機制

核心代碼

package com.springboot.sample.service.impl;

import com.springboot.sample.bean.Users;
import com.springboot.sample.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.*;

/***
* zzq
* 包裝成批量執行的地方,使用queue解決超時問題
* */
@Service
public class UserWrapBatchQueueService {
@Resource
private UserService userService;

/**
* 最大任務數
**/
public static int MAX_TASK_NUM = 100;


/**
* 請求類,code為查詢的共同特征,例如查詢商品,通過不同id的來區分
* CompletableFuture將處理結果返回
*/
public class Request {
// 請求id
String requestId;

// 參數
Long userId;
// 隊列,這個有超時機制
LinkedBlockingQueue<Users> usersQueue;


public String getRequestId() {
return requestId;
}

public void setRequestId(String requestId) {
this.requestId = requestId;
}

public Long getUserId() {
return userId;
}

public void setUserId(Long userId) {
this.userId = userId;
}

public LinkedBlockingQueue<Users> getUsersQueue() {
return usersQueue;
}

public void setUsersQueue(LinkedBlockingQueue<Users> usersQueue) {
this.usersQueue = usersQueue;
}
}

/*
LinkedBlockingQueue是一個阻塞的隊列,內部采用鏈表的結果,通過兩個ReenTrantLock來保證線程安全
LinkedBlockingQueue與ArrayBlockingQueue的區別
ArrayBlockingQueue默認指定了長度,而LinkedBlockingQueue的默認長度是Integer.MAX_VALUE,也就是無界隊列,在移除的速度小于添加的速度時,容易造成OOM。
ArrayBlockingQueue的存儲容器是數組,而LinkedBlockingQueue是存儲容器是鏈表
兩者的實現隊列添加或移除的鎖不一樣,ArrayBlockingQueue實現的隊列中的鎖是沒有分離的,即添加操作和移除操作采用的同一個ReenterLock鎖,
而LinkedBlockingQueue實現的隊列中的鎖是分離的,其添加采用的是putLock,移除采用的則是takeLock,這樣能大大提高隊列的吞吐量,
也意味著在高并發的情況下生產者和消費者可以并行地操作隊列中的數據,以此來提高整個隊列的并發性能。
*/
private final Queue<Request> queue = new LinkedBlockingQueue();

@PostConstruct
public void init() {
//定時任務線程池,創建一個支持定時、周期性或延時任務的限定線程數目(這里傳入的是1)的線程池
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);

scheduledExecutorService.scheduleAtFixedRate(() -> {
int size = queue.size();
//如果隊列沒數據,表示這段時間沒有請求,直接返回
if (size == 0) {
return;
}
List<Request> list = new ArrayList<>();
System.out.println("合并了 [" + size + "] 個請求");
//將隊列的請求消費到一個集合保存
for (int i = 0; i < size; i++) {
// 后面的SQL語句是有長度限制的,所以還要做限制每次批量的數量,超過最大任務數,等下次執行
if (i < MAX_TASK_NUM) {
list.add(queue.poll());
}
}
//拿到我們需要去數據庫查詢的特征,保存為集合
List<Request> userReqs = new ArrayList<>();
for (Request request : list) {
userReqs.add(request);
}
//將參數傳入service處理, 這里是本地服務,也可以把userService 看成RPC之類的遠程調用
Map<String, Users> response = userService.queryUserByIdBatchQueue(userReqs);
for (Request userReq : userReqs) {
// 這里再把結果放到隊列里
Users users = response.get(userReq.getRequestId());
userReq.usersQueue.offer(users);
}

}, 100, 10, TimeUnit.MILLISECONDS);
//scheduleAtFixedRate是周期性執行 schedule是延遲執行 initialDelay是初始延遲 period是周期間隔 后面是單位
//這里我寫的是 初始化后100毫秒后執行,周期性執行10毫秒執行一次
}

public Users queryUser(Long userId) {
Request request = new Request();
// 這里用UUID做請求id
request.requestId = UUID.randomUUID().toString().replace("-", "");
request.userId = userId;
LinkedBlockingQueue<Users> usersQueue = new LinkedBlockingQueue<>();
request.usersQueue = usersQueue;
//將對象傳入隊列
queue.offer(request);
//取出元素時,如果隊列為空,給定阻塞多少毫秒再隊列取值,這里是3秒
try {
return usersQueue.poll(3000,TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
}
...省略..

@Override
public Map<String, Users> queryUserByIdBatchQueue(List<UserWrapBatchQueueService.Request> userReqs) {
// 全部參數
List<Long> userIds = userReqs.stream().map(UserWrapBatchQueueService.Request::getUserId).collect(Collectors.toList());
QueryWrapper<Users> queryWrapper = new QueryWrapper<>();
// 用in語句合并成一條SQL,避免多次請求數據庫的IO
queryWrapper.in("id", userIds);
List<Users> users = usersMapper.selectList(queryWrapper);
Map<Long, List<Users>> userGroup = users.stream().collect(Collectors.groupingBy(Users::getId));
HashMap<String, Users> result = new HashMap<>();
// 數據分組
userReqs.forEach(val -> {
List<Users> usersList = userGroup.get(val.getUserId());
if (!CollectionUtils.isEmpty(usersList)) {
result.put(val.getRequestId(), usersList.get(0));
} else {
// 表示沒數據 , 這里要new,不然加入隊列會空指針
result.put(val.getRequestId(), new Users());
}
});
return result;
}

...省略...

小結

請求合并,批量的辦法能大幅節省被調用系統的連接資源,本例是以數據庫為例,其他RPC調用也是類似的道理。缺點就是請求的時間在執行實際的邏輯之前增加了等待時間,不適合低并發的場景。

源碼:https://gitee.com/apple_1030907690/spring-boot-kubernetes/tree/v1.0.5

責任編輯:武曉燕 來源: 碼猿技術專欄
相關推薦

2025-06-05 00:00:00

項目接口合并

2025-10-14 09:12:49

2025-07-09 04:00:00

2023-03-27 08:25:28

技巧技術吞吐率

2022-09-22 08:42:14

接口請求合并技巧

2025-07-09 09:32:21

2021-02-02 15:38:19

Disruptor緩存Java

2022-01-05 08:29:22

監控Prometheus Post

2021-03-08 08:02:40

IDEA插件JSON

2025-05-13 09:31:27

2025-09-08 04:07:00

SpringApache工具

2025-05-26 08:10:49

2025-08-21 09:35:29

2022-02-23 11:47:57

CharlesFiddler抓包

2025-01-08 09:35:55

Spring性能監控

2025-10-27 01:55:00

Jupyter連接器nbconvert

2023-10-30 09:46:08

接口重試技巧

2021-03-26 15:18:11

代碼工具Mockoon

2025-04-09 12:48:13

模型AI數據

2025-07-23 09:34:24

點贊
收藏

51CTO技術棧公眾號

欧洲猛交xxxx乱大交3| 国产精彩免费视频| 少妇av在线播放| 日韩精品久久久久久| 久久精品国产亚洲精品| 性活交片大全免费看| 午夜日韩成人影院| 伊人开心综合网| 欧美日韩一区二 | 屁屁影院国产第一页| 国产欧美在线观看免费| 亚洲电影一区二区| 亚洲欧洲一区二区在线观看| 成人精品在线播放| 久久精品国产网站| 欧美专区第一页| 婷婷色中文字幕| av永久不卡| 亚洲精品黄网在线观看| 色婷婷一区二区三区在线观看| 黄在线观看免费网站ktv| 综合av第一页| 日韩精品不卡| 少妇高潮久久久| 国产一区二区精品久久| 国产精品丝袜久久久久久高清 | 国产综合动作在线观看| 国产又粗又猛又黄又爽无遮挡| 国产亚洲毛片| 国内精品久久影院| 久久综合亚洲色hezyo国产| 欧美综合久久| 国产亚洲人成网站在线观看| 中国黄色片视频| 亚洲成av人片在线观看www| 欧美精品丝袜久久久中文字幕| 97xxxxx| av毛片午夜不卡高**水| 亚洲综合色婷婷| 黄色录像特级片| 成a人片在线观看| 国产精品少妇自拍| 午夜一区二区三区| 成a人v在线播放| 国产午夜精品福利| 色中色综合成人| 91亚洲精选| 国产精品理伦片| 一区二区在线高清视频| 秋霞午夜在线观看| 亚洲欧洲美洲综合色网| 资源网第一页久久久| 日本精品在线| 亚洲欧美在线观看| 日韩一二区视频| 午夜dj在线观看高清视频完整版| 亚洲日穴在线视频| 青青草免费在线视频观看| 国产精品实拍| 一区二区三区成人| 亚洲人成无码网站久久99热国产| 55av亚洲| 色婷婷国产精品| 欧美精品精品一区| 日韩黄色影视| 在线观看黄av| 亚洲另类春色国产| avav在线播放| 精品众筹模特私拍视频| 亚洲自拍偷拍欧美| 欧美极品欧美精品欧美| 欧美日韩成人影院| 欧美日韩一二三区| 好吊操视频这里只有精品| 加勒比久久高清| 亚洲欧洲成视频免费观看| 特级西西www444人体聚色| 99久久这里只有精品| 欧美激情一区二区三区久久久 | 欧美午夜一区二区三区| 亚洲综合伊人久久| 福利片在线一区二区| 亚洲免费人成在线视频观看| 成人性生交大片免费看无遮挡aⅴ| 国产精品成人一区二区不卡| 欧美华人在线视频| 无码人妻aⅴ一区二区三区有奶水| 久久国产精品72免费观看| 91麻豆精品秘密入口| 深夜视频在线免费| 中文字幕一区二区三区蜜月| 亚洲 欧美 综合 另类 中字| 九九热线视频只有这里最精品| 91精品国产综合久久小美女| 99久久免费看精品国产一区| 久久精品国产99久久| 久久久中精品2020中文| 中文字幕欧美人妻精品一区蜜臀| 国产91综合网| 亚欧洲精品在线视频免费观看| 2024短剧网剧在线观看| 日韩欧美国产成人| 韩国一区二区三区四区| av一区二区高清| 久久久久久久999| 中文字幕一区二区三区波野结| 国产成人av电影免费在线观看| 欧美最大成人综合网| 免费男女羞羞的视频网站在线观看| 精品久久久久久久中文字幕 | 国产精品国产亚洲精品看不卡| 高清亚洲高清| 精品一区二区三区四区| 国产女片a归国片aa| 日韩精品久久久久久| 国产午夜精品在线| h片在线播放| 欧美色窝79yyyycom| 国产精品无码一区二区三区免费 | 久久久久亚洲无码| 欧美韩国一区| 91精品久久久久久久久久久久久 | 亚洲 日韩 国产第一| 99热精品在线播放| 国产精品国产三级国产aⅴ原创| 337p粉嫩大胆噜噜噜鲁| 亚洲一二av| 久久综合国产精品台湾中文娱乐网| 国产成人精品777777| 成人高清视频免费观看| 先锋影音男人资源| 欧美亚洲综合视频| 在线看日韩av| 亚洲熟妇av乱码在线观看| 国产网站一区二区| 国语对白做受xxxxx在线中国| 日本韩国欧美超级黄在线观看| 色综合天天狠天天透天天伊人| 一级黄色小视频| 国产精品久久久久永久免费观看| 亚洲黄色a v| 日韩最新在线| 欧洲美女免费图片一区| 亚洲AV成人无码一二三区在线| 亚洲国产成人av网| 视频免费在线观看| 中文日韩欧美| 欧美大香线蕉线伊人久久国产精品| 国产美女高潮在线| 亚洲精品国产精品久久清纯直播| 91看片在线播放| 91小视频在线| 欧美日韩在线成人| 大色综合视频网站在线播放| 国产精品视频区1| 欧美精品videos另类| 欧美一区二区私人影院日本| av激情在线观看| 成人午夜视频福利| 美女av免费在线观看| 精品国产乱码久久久久久果冻传媒| 国产精品91免费在线| 成人18在线| 欧美一级二级三级蜜桃| 91日韩中文字幕| va亚洲va日韩不卡在线观看| 日韩av一二三四区| 日本道不卡免费一区| 成人免费直播live| 成人高潮aa毛片免费| 日韩精品视频中文在线观看| 老熟妇仑乱一区二区av| 国产精品天干天干在线综合| 伊人色在线视频| 亚洲久久一区| 亚洲国产一区二区精品视频| 精品国产伦一区二区三区观看说明 | 精品欧美一区二区久久久| 老司机精品视频导航| 久久久久福利视频| 国产综合久久久| 91aaaa| 蜜桃av在线| 日韩中文字幕在线观看| 国产综合无码一区二区色蜜蜜| 色综合久久综合网欧美综合网| 狂野欧美性猛交| 成人涩涩免费视频| 欧美三级理论片| 一区在线免费| 一本一道久久a久久综合精品| 亚洲一区 二区| 国产精品美腿一区在线看| 色操视频在线| 一区二区三区日韩在线| 亚洲国产视频一区二区三区| 在线亚洲人成电影网站色www| 欧美丰满艳妇bbwbbw| 久久精品亚洲乱码伦伦中文| 在线观看视频在线观看| 久久午夜影视| 男女日批视频在线观看| 婷婷综合视频| 欧美综合77777色婷婷| 精品少妇一区| 亚洲va久久久噜噜噜| 偷拍中文亚洲欧美动漫| 高清欧美性猛交xxxx| 九义人在线观看完整免费版电视剧| 日韩精品免费一线在线观看| av网站免费大全| 欧美日韩中字一区| 日日摸天天添天天添破| 亚洲最色的网站| 手机在线免费看片| 中文字幕免费一区| 成年人免费观看视频网站| 高h视频在线| 欧美精品欧美精品系列| 免费看一级视频| 欧美日韩免费在线观看| 麻豆疯狂做受xxxx高潮视频| 国产精品你懂的| 久久久久久久久久久久久久久| 成人国产亚洲欧美成人综合网| 天天干天天曰天天操| 久久国产精品99久久久久久老狼| 国产日韩一区二区在线观看| 亚洲精品人人| 精品少妇在线视频| 狠狠入ady亚洲精品| 99热都是精品| 伊人情人综合网| 中文字幕中文字幕99| 五月激情久久久| 一区二区三区四区五区精品| 凹凸成人精品亚洲精品密奴| 欧美视频观看一区| 精品国产精品| 亚洲欧美日韩不卡一区二区三区| 国产一区日韩| 香蕉久久夜色| 91麻豆国产自产在线观看亚洲| 亚洲一区二区三区四区中文| 日本精品三区| 中文字幕日韩一区二区三区| 99免费精品| 日韩一级特黄毛片| 欧美日韩亚洲国产精品| 国产一区二区四区| 亚洲自啪免费| 能在线观看的av网站| 奇米综合一区二区三区精品视频| 日韩福利视频在线| 久久精品99久久久| 久久精品久久99| 福利一区二区在线| 亚洲一区二区在线免费| 久久女同性恋中文字幕| 欧洲美一区二区三区亚洲| 欧美高清一级片在线观看| 日本美女黄色一级片| 亚洲欧美日韩在线播放| 久久久精品99| 欧美性极品xxxx做受| 久久国产乱子伦精品| 欧美视频一区二区三区在线观看| 这里只有精品9| 精品久久久久久无| 三级在线播放| 日韩中文字幕在线| av影院在线| 国产精品久久久久久av| 福利一区三区| 久久一区二区三区av| 日韩精品一区二区三区免费观影| 伊人久久大香线蕉精品 | www成人免费| 亚洲女人av| 中国黄色片一级| 99久久免费视频.com| 国产又黄又粗的视频| 伊人色综合久久天天人手人婷| a v视频在线观看| 欧美日韩午夜在线| 免费观看a视频| 在线电影中文日韩| 黄色影院在线看| 国产精品久久久久久久9999| 日韩视频在线直播| 日本一区免费在线观看| 欧美在线91| youjizzxxxx18| www.日韩av| 老湿机69福利| 欧美视频一区二区在线观看| 丁香六月色婷婷| 久久精品福利视频| 波多野结衣亚洲| 国产99在线免费| 99精品在线| 久久婷婷国产精品| 粉嫩一区二区三区在线看| 亚洲综合欧美综合| 五月激情综合网| 国产99视频在线| 在线观看日韩av| 校园春色亚洲| 国产精品久久久对白| 91精品国产麻豆国产在线观看 | 欧美三级网址| 国产伦精品一区二区三区| 亚洲精品成人无限看| 久久黄色免费看| 91女厕偷拍女厕偷拍高清| 免费一级黄色大片| 91精品国产91综合久久蜜臀| 国产黄色免费在线观看| 青青久久av北条麻妃黑人| 久久九九热re6这里有精品| 国内自拍中文字幕| 韩国av一区二区| 久久精品在线观看视频| 欧美性猛片aaaaaaa做受| 神马精品久久| 日本高清久久天堂| 性欧美xxxx免费岛国不卡电影| 久久艹国产精品| 大桥未久av一区二区三区中文| 亚洲最大的黄色网址| 欧美久久婷婷综合色| 91大神xh98hx在线播放| 国产精品99久久久久久www| 九九精品久久| 99免费视频观看| 国产欧美精品一区| 69av视频在线观看| 尤物yw午夜国产精品视频明星| 成人性生交大片免费观看网站| 精品久久精品久久| 亚洲影院一区| 亚洲一区视频在线播放| 欧美综合在线视频| 91女主播在线观看| 91色在线视频| 欧美另类亚洲| www国产视频| 懂色av中文一区二区三区天美| 香蕉视频成人在线| 日韩av手机在线| 久久裸体网站| 久久aaaa片一区二区| 一区二区三区在线观看欧美| 国产黄色一级大片| 午夜精品99久久免费| 丝袜连裤袜欧美激情日韩| 18岁视频在线观看| 国产精品美女久久久久久久| 91在线公开视频| 久久综合免费视频| 国产欧美自拍一区| 老头吃奶性行交视频| 中文字幕亚洲区| 亚洲av永久无码国产精品久久| 国内伊人久久久久久网站视频 | 免费观看成人www动漫视频| 色欲av无码一区二区人妻| 国产日韩v精品一区二区| 在线免费观看视频网站| 欧美精品在线免费| 日韩黄色网络| 一个色综合久久| 亚洲成va人在线观看| 黄色av网址在线免费观看| 成人妇女免费播放久久久| 国产一区二区三区四区老人| 给我看免费高清在线观看| 欧美日韩一区小说| 好久没做在线观看| 日韩影视精品| 成人动漫在线一区| 中文字幕丰满人伦在线| 欧美丰满片xxx777| 国产日产精品一区二区三区四区的观看方式 | 国产片一区二区三区| 国产偷拍一区二区| 热久久99这里有精品| 一区二区三区在线电影| 自拍偷拍亚洲天堂| 日韩精品中文字幕在线不卡尤物| 亚洲精品成人图区| 成人国产一区二区三区| 久久九九久久九九| 亚洲精品一区二区三区四区| 国产精品久久久一区| 伊人精品视频| 熟女少妇a性色生活片毛片| 亚洲精品网站在线播放gif| 久久久久毛片免费观看| 91淫黄看大片|