精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

日本黄区免费视频观看| 亚洲 高清 成人 动漫| 国产av无码专区亚洲a∨毛片| 女人香蕉久久**毛片精品| 日韩欧美久久一区| 九一国产精品视频| 国产香蕉视频在线看| 麻豆精品一区二区综合av| 色综合视频一区中文字幕| 亚洲一区二区三区综合| 久久久人成影片一区二区三区在哪下载| 欧美—级在线免费片| 91国产丝袜在线放| 少妇高潮av久久久久久| 99久久综合狠狠综合久久aⅴ| 精品免费国产一区二区三区四区| 国产精品333| 老司机99精品99| 99久久综合精品| 国产女人精品视频| 国产无精乱码一区二区三区| 第一会所sis001亚洲| 精品国产91洋老外米糕| 国产精彩免费视频| 麻豆福利在线观看| 国产精品视频看| 国产在线一区二区三区播放| 一起草av在线| 毛片一区二区| 欧美激情手机在线视频| 男女全黄做爰文章| 一区二区美女| 精品国产伦一区二区三区免费| 日本黄大片一区二区三区| 欧美日韩在线观看首页| 一区二区三区毛片| 99热这里只有精品7| 国外av在线| 99re视频精品| 国产91色在线|亚洲| 91久久精品国产91性色69| 久久亚洲不卡| 奇米4444一区二区三区| 国产一级特黄毛片| 欧美成人高清| 久久精品91久久香蕉加勒比| 99re久久精品国产| 久久综合五月婷婷| 精品日韩一区二区| 国产成人av免费观看| 日本亚洲欧洲无免费码在线| 欧洲视频一区二区| 日本精品www| 欧美另类老肥妇| 天天色天天操综合| 国产3p露脸普通话对白| av中文字幕电影在线看| 亚洲综合一区二区| 国产a级黄色大片| av片在线观看| 亚洲美女视频在线观看| 日韩av一区二区三区美女毛片| 免费福利在线观看| 国产欧美日韩综合| 婷婷久久青草热一区二区| 国产理论电影在线观看| 国产精品水嫩水嫩| 中文字幕中文字幕在线中一区高清| 成人高清在线| 国产精品丝袜91| 艳母动漫在线免费观看| av免费看在线| 亚洲国产精品一区二区www| 成年人看的毛片| 国产乱码午夜在线视频| 欧美色视频日本高清在线观看| aaaaaa亚洲| 国产成人精品一区二三区在线观看| 色系网站成人免费| 亚洲一级片网站| 久久久精品区| 欧美精品一区二区三区很污很色的| 在线观看成人动漫| 杨幂一区二区三区免费看视频| 一本一本久久a久久精品综合小说| 精品无码在线观看| 91久久电影| 欧美激情一区二区三区在线视频观看| 日韩欧美中文字幕一区二区| 久久国产精品久久久久久电车 | 久久国产欧美精品| 你懂的视频在线免费| 国产精品久久三区| 丁香婷婷综合激情| 神马电影网我不卡| 在线综合亚洲欧美在线视频| 色哟哟无码精品一区二区三区| 亚洲动漫在线观看| 久久精品久久精品亚洲人| 久久免费黄色网址| 日韩电影免费在线看| 亚洲精品免费av| 亚洲AV成人无码一二三区在线| 欧美激情在线看| 97在线免费视频观看| av资源亚洲| 欧美一区二区三区播放老司机| 欧美大喷水吹潮合集在线观看| 国产欧美日韩视频在线| 久久伊人免费视频| av毛片在线免费观看| 国产精品一区二区果冻传媒| 国产主播一区二区三区四区| 视频免费一区| 黑人欧美xxxx| 手机av在线免费| 日韩成人av在线资源| 久久久国产精彩视频美女艺术照福利| 日韩av黄色片| 国产自产视频一区二区三区| 欧美精品一区二区三区在线四季 | 日韩免费av网站| 国产老妇另类xxxxx| 欧美性大战久久久久| 久久国产精品黑丝| 欧美精品v日韩精品v韩国精品v| 国产精品一区二区入口九绯色| 欧美 日韩 国产 一区| 国产精品十八以下禁看| 少妇性bbb搡bbb爽爽爽欧美| 一区二区三区四区精品在线视频| 污片在线免费看| 亚洲人成网www| 欧美黑人国产人伦爽爽爽| ,一级淫片a看免费| 国产免费久久精品| 日本中文字幕片| 视频福利一区| 91tv亚洲精品香蕉国产一区7ujn| www.色视频| 亚洲人成电影网站色mp4| 亚洲无吗一区二区三区| 国产91久久精品一区二区| 97久久精品视频| 午夜久久久久久噜噜噜噜| 亚洲三级在线免费| 日本一二区免费| 久久香蕉国产| 国产精品视频专区| av黄色在线观看| 在线观看视频欧美| 国产成人精品无码免费看夜聊软件| 一区精品久久| 国产私拍一区| av在线中出| 日韩av在线免费看| 懂色av.com| 91在线观看免费视频| 日韩伦理在线免费观看| 久久精品福利| 18性欧美xxxⅹ性满足| 青青草视频在线观看| 欧美特级www| a级片在线观看| 日本不卡一区二区三区高清视频| 欧美中文娱乐网| 国产精品久久久久久妇女| 一本色道久久综合狠狠躁篇怎么玩 | 911美女片黄在线观看游戏| 中文字幕巨乱亚洲| 思思久久精品视频| 欧美精品麻豆| 国产日韩一区二区| 成人免费直播| 中文字幕亚洲一区在线观看 | 999精品视频在线观看播放 | 男人网站在线观看| 国产精品一二| 日韩精品无码一区二区三区| 成人全视频免费观看在线看| 久久久国产精彩视频美女艺术照福利| www.av导航| 亚洲aaa精品| 国产人妻大战黑人20p| 久久99久久久欧美国产| 欧美做受777cos| 奇米777国产一区国产二区| 国产成人综合久久| 国产鲁鲁视频在线观看特色| 亚洲福利视频网| 性高潮视频在线观看| 亚洲精品视频自拍| 亚洲蜜桃精久久久久久久久久久久| 视频一区二区不卡| 99亚洲国产精品| 免费成人av| 亚洲一区国产精品| 毛片无码国产| 欧美精品videossex88| 美女做暖暖视频免费在线观看全部网址91 | 日韩精品一区二区三区在线播放| 香蕉免费毛片视频| 国产精品三级av在线播放| 在线观看免费视频黄| 美国十次了思思久久精品导航| 国产在线视频在线| 成人av国产| 国产精品手机视频| 开心久久婷婷综合中文字幕| 97视频com| 黄色av网站在线播放| 精品性高朝久久久久久久| 国产视频在线观看视频| 欧美最猛黑人xxxxx猛交| 麻豆亚洲av熟女国产一区二| 亚洲国产精品成人久久综合一区 | 91麻豆精品在线| 亚洲综合av网| 亚洲女人毛茸茸高潮| 91在线国内视频| 欧美熟妇精品一区二区| 奇米色一区二区三区四区| 欧美三级在线观看视频| 欧美在线观看天堂一区二区三区| 亚洲v日韩v欧美v综合| 欧美激情影院| 国产精品国产一区二区| **欧美日韩在线| 国产精品国产自产拍高清av水多 | 91av在线播放视频| 欧美巨大xxxx做受沙滩| www.日韩视频| seseavlu视频在线| 亚洲美女在线观看| 天天干天天爽天天操| 日韩欧美在线观看一区二区三区| 亚洲国产无线乱码在线观看| 欧美日韩国产中文精品字幕自在自线| 欧美老熟妇一区二区三区| 国产精品久久看| 亚洲色图第四色| 久久网这里都是精品| 日本一卡二卡在线| 成人精品亚洲人成在线| xxx中文字幕| 精品一区二区三区在线观看| 中文字幕 日韩 欧美| 免费观看一级特黄欧美大片| 9久久婷婷国产综合精品性色 | 成人性做爰aaa片免费看不忠| 国产午夜精品一区二区三区欧美 | 97超碰在线资源| 91片在线免费观看| 三级电影在线看| 国产亚洲一本大道中文在线| 免费看污黄网站在线观看| 久久亚洲一级片| 亚洲熟妇无码av| 久久久久久久综合色一本| 欧美黄色一级生活片| 中文字幕欧美日韩一区| 国产精品www爽爽爽| 1024成人网| 91九色丨porny丨极品女神| 亚洲男同1069视频| 国产亚洲色婷婷久久99精品| 亚洲一区二区成人在线观看| 国产精久久久久久| 欧美日韩亚洲高清| 成人一二三四区| 欧美浪妇xxxx高跟鞋交| av高清一区二区| 亚洲国产高潮在线观看| 色资源在线观看| 中文字幕精品av| 国产原厂视频在线观看| 欧美激情一二三| 亚洲精品mv| 国产精品欧美日韩久久| 欧美中文高清| 蜜桃91精品入口| 日韩在线观看一区 | 69堂成人精品视频免费| 成人性生交大片免费看96| 久久爱av电影| 不卡日本视频| 4444亚洲人成无码网在线观看| 自拍偷拍欧美专区| www.com毛片| 美腿丝袜在线亚洲一区| 男人女人拔萝卜视频| 久久久噜噜噜久噜久久综合| 色婷婷粉嫩av| 亚洲第一狼人社区| 中文字幕一区二区久久人妻| 欧美成人精品1314www| 国产在线视频网址| 欧美大奶子在线| 日韩欧美一区二区三区在线观看| 成人网址在线观看| 任你躁在线精品免费| 在线观看免费91| 国产精品视区| 波多野结衣网页| 久久久精品tv| 久久伊人成人网| 欧美视频完全免费看| 日本免费网站在线观看| 亚洲视频在线观看| 国产极品人妖在线观看| 国产一区二区在线免费视频| 欧美人妖在线观看| 色哺乳xxxxhd奶水米仓惠香| 丝瓜av网站精品一区二区| 中文字幕永久免费| 国产精品每日更新在线播放网址| 国语对白一区二区| 欧美剧情电影在线观看完整版免费励志电影| 秋霞视频一区二区| 精品国产一区久久久| 向日葵视频成人app网址| 国产伦理一区二区三区| 最新精品国产| 久久婷五月综合| 久久色中文字幕| 久久国产精品波多野结衣av| 欧美日本一区二区三区四区| 看电影就来5566av视频在线播放| 欧美激情精品久久久久| 精品视频在线播放一区二区三区| 三级三级久久三级久久18| 99热免费精品在线观看| 国产情侣久久久久aⅴ免费| 亚洲欧美综合另类在线卡通| 国产成人精品一区二区色戒| 亚洲一区二区国产| 色戒汤唯在线| 精品视频一区在线| 精品999成人| 白嫩情侣偷拍呻吟刺激| 亚洲一区视频在线| www.xxxx国产| 久久99久久99精品中文字幕| 美女精品久久| 激情五月六月婷婷| 国产一区二三区| 成人免费视频国产免费观看| 欧美精品欧美精品系列| 老司机午夜在线视频| 国产精品视频永久免费播放| 日本精品黄色| 九九热99视频| 成人免费一区二区三区视频 | 性色国产成人久久久精品| 欧美性猛片xxxx免费看久爱| 国产一区电影| 国产精品吊钟奶在线| 欧美精品尤物在线观看| 另类小说第一页| 国产精品的网站| 国产精品玖玖玖| 欧美理论电影在线观看| 91麻豆精品国产91久久久久推荐资源| 国产 国语对白 露脸| 成人av电影在线| 黄色在线视频网址| 一本色道久久综合狠狠躁篇怎么玩 | 国产精品美女久久久久久久久| 亚洲字幕av一区二区三区四区| 色系列之999| 久久在线观看| 成年人午夜视频在线观看| 91蝌蚪porny九色| 欧美日韩a v| 久久久精品视频成人| 91精品国产自产精品男人的天堂| 成人性生活视频免费看| 久久免费电影网| 一级黄色片视频| 欧美极品少妇全裸体| 色婷婷精品视频| 午夜免费一区二区| 亚洲男人的天堂在线aⅴ视频| 午夜精品久久久久久久96蜜桃| 91精品国产电影| sdde在线播放一区二区| 色哟哟在线观看视频| 黄色一区二区在线观看| a√资源在线| 91在线精品观看| 久久www成人_看片免费不卡| 夫妻性生活毛片| 亚洲国产精品va| 国产欧美在线观看免费| www.夜夜爱| 国产精品美女www爽爽爽| 国模私拍视频在线| 国产精品视频1区| 99成人在线| 乱h高h女3p含苞待放|