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

震撼!通過雙重異步,Excel 10萬行數據導入從191秒優化到2秒!

開發 前端
在處理高并發、大數據導入等場景時,異步編程和線程池技術提供了一種極具效率的解決方案。通過合理配置線程池的核心線程數、最大線程數、隊列長度等參數,能夠在確保系統穩定性的前提下,大幅提升并發處理能力。

在現代的企業級應用開發中,海量數據的處理效率和并發性能優化是一個非常重要的課題。無論是大規模數據導入、文件解析,還是在分布式系統中處理高并發任務,如何提升系統的處理速度、合理利用計算資源、減少線程上下文切換的開銷,這些都是開發者必須面對的問題。在這一背景下,線程池技術以及異步編程逐漸成為提升系統性能的利器。

本文將深入探討如何通過合理設計線程池和利用異步編程模型,有效優化大規模數據的處理性能。我們將結合 Spring Boot 框架中的 @Async 注解、自定義線程池、以及通過使用 EasyExcel 進行大數據量的 Excel 解析和異步寫入數據庫的場景,詳細說明如何通過分而治之的策略,減少系統的響應時間、提高并發處理能力。同時,還將分析如何基于 CPU 和 IO 密集型任務的特性,來合理設置線程池的核心線程數、最大線程數等參數,以便在實際項目中能夠充分發揮硬件資源的性能。

通常我是這樣做的:

  1. 使用POI讀取需要導入的Excel文件;
  2. 將文件名作為表名,列標題作為列名,并將數據拼接成SQL語句;
  3. 通過JDBC或Mybatis插入到數據庫。

圖片圖片

在操作中,如果文件數量多且數據量大,處理過程可能會非常緩慢。

訪問后,感覺程序沒有響應,但實際上,它正在讀取并插入數據,只是速度很慢。

讀取包含10萬行的Excel文件竟然耗時191秒!

我以為程序卡住了!

private void readXls(String filePath, String filename) throws Exception {
    @SuppressWarnings("resource")
    XSSFWorkbook xssfWorkbook = new XSSFWorkbook(new FileInputStream(filePath));
    // 讀取第一個工作表
    XSSFSheet sheet = xssfWorkbook.getSheetAt(0);
    // 獲取總行數
    int maxRow = sheet.getLastRowNum();

    StringBuilder insertBuilder = new StringBuilder();

    insertBuilder.append("insert into ").append(filename).append(" ( UUID,");

    XSSFRow row = sheet.getRow(0);
    for (int i = 0; i < row.getPhysicalNumberOfCells(); i++) {
        insertBuilder.append(row.getCell(i)).append(",");
    }

    insertBuilder.deleteCharAt(insertBuilder.length() - 1);
    insertBuilder.append(" ) values ( ");

    StringBuilder stringBuilder = new StringBuilder();
    for (int i = 1; i <= maxRow; i++) {
        XSSFRow xssfRow = sheet.getRow(i);
        String id = "";
        String name = "";
        for (int j = 0; j < row.getPhysicalNumberOfCells(); j++) {
            if (j == 0) {
                id = xssfRow.getCell(j) + "";
            } else if (j == 1) {
                name = xssfRow.getCell(j) + "";
            }
        }

        boolean flag = isExisted(id, name);
        if (!flag) {
            stringBuilder.append(insertBuilder);
            stringBuilder.append('\'').append(uuid()).append('\'').append(",");
            for (int j = 0; j < row.getPhysicalNumberOfCells(); j++) {
                stringBuilder.append('\'').append(value).append('\'').append(",");
            }
            stringBuilder.deleteCharAt(stringBuilder.length() - 1);
            stringBuilder.append(" )").append("\n");
        }
    }

    List<String> collect = Arrays.stream(stringBuilder.toString().split("\n")).collect(Collectors.toList());
    int sum = JdbcUtil.executeDML(collect);
}

private static boolean isExisted(String id, String name) {
    String sql = "select count(1) as num from " + static_TABLE + " where ID = '" + id + "' and NAME = '" + name + "'";
    String num = JdbcUtil.executeSelect(sql, "num");
    return Integer.valueOf(num) > 0;
}

private static String uuid() {
    return UUID.randomUUID().toString().replace("-", "");
}

如何優化?

優化1:首先,查詢所有數據,將其緩存到map中,然后在插入前做決策。這樣可以大大提高速度。

優化2:如果單個Excel文件太大,可以考慮使用異步和多線程,分批讀取多行并插入數據庫。

圖片圖片

優化3:如果文件太多,可以為每個Excel文件使用一個異步進程,實現雙重異步讀取和插入。

圖片圖片

使用雙重異步處理后,從191秒優化到了2秒,你能相信嗎?

以下是異步讀取Excel文件和批量讀取大Excel文件的關鍵代碼。

異步讀取緩存的Excel Controller類

@RequestMapping(value = "/readExcelCacheAsync", method = RequestMethod.POST)
@ResponseBody
public String readExcelCacheAsync() {
    String path = "G:\\Test\\data\\";
    try {
        // 讀取Excel之前,緩存所有數據
        USER_INFO_SET = getUserInfo();

        File file = new File(path);
        String[] xlsxArr = file.list();
        for (int i = 0; i < xlsxArr.length; i++) {
            File fileTemp = new File(path + "\\" + xlsxArr[i]);
            String filename = fileTemp.getName().replace(".xlsx", "");
            readExcelCacheAsyncService.readXls(path + filename + ".xlsx", filename);
        }
    } catch (Exception e) {
        logger.error("|#ReadDBCsv|#Exception: ", e);
        return "error";
    }
    return "success";
}

批量讀取超大Excel文件

@Async("async-executor")
public void readXls(String filePath, String filename) throws Exception {
    @SuppressWarnings("resource")
    XSSFWorkbook xssfWorkbook = new XSSFWorkbook(new FileInputStream(filePath));
    // 讀取第一個工作表
    XSSFSheet sheet = xssfWorkbook.getSheetAt(0);
    // 總行數
    int maxRow = sheet.getLastRowNum();
    logger.info(filename + ".xlsx,共 " + maxRow + " 行數據!");
    StringBuilder insertBuilder = new StringBuilder();

    insertBuilder.append("insert into ").append(filename).append(" ( UUID,");

    XSSFRow row = sheet.getRow(0);
    for (int i = 0; i < row.getPhysicalNumberOfCells(); i++) {
        insertBuilder.append(row.getCell(i)).append(",");
    }

    insertBuilder.deleteCharAt(insertBuilder.length() - 1);
    insertBuilder.append(" ) values ( ");

    int times = maxRow / STEP + 1;
    for (int time = 0; time < times; time++) {
        int start = STEP * time + 1;
        int end = STEP * time + STEP;

        if (time == times - 1) {
            end = maxRow;
        }

        if (end + 1 - start > 0) {
            readExcelDataAsyncService.readXlsCacheAsyncMybatis(sheet, row, start, end, insertBuilder);
        }
    }
}

異步批量插入數據庫

@Async("async-executor")
public void readXlsCacheAsync(XSSFSheet sheet, XSSFRow row, int start, int end, StringBuilder insertBuilder) {
    StringBuilder stringBuilder = new StringBuilder();
    for (int i = start; i <= end; i++) {
        XSSFRow xssfRow = sheet.getRow(i);
        String id = "";
        String name = "";
        for (int j = 0; j < row.getPhysicalNumberOfCells(); j++) {
            if (j == 0) {
                id = xssfRow.getCell(j) + "";
            } else if (j == 1) {
                name = xssfRow.getCell(j) + "";
            }
        }

        // 在讀取Excel之前,先緩存所有數據,然后做決策
        boolean flag = isExisted(id, name);
        if (!flag) {
            stringBuilder.append(insertBuilder);
            stringBuilder.append('\'').append(uuid()).append('\'').append(",");
            for (int j = 0; j < row.getPhysicalNumberOfCells(); j++) {
                stringBuilder.append('\'').append(value).append('\'').append(",");
            }
            stringBuilder.deleteCharAt(stringBuilder.length() - 1);
            stringBuilder.append(" )").append("\n");
        }
    }

    List<String> collect = Arrays.stream(stringBuilder.toString().split("\n")).collect(Collectors.toList());
    if (collect != null && collect.size() > 0) {
        int sum = JdbcUtil.executeDML(collect);
    }
}

private boolean isExisted(String id, String name) {
    return ReadExcelCacheAsyncController.USER_INFO_SET.contains(id + "," + name);
}

異步線程池工具類

@Async 的目的是異步處理任務。

  1. 在方法上添加 @Async 表明該方法是異步的。
  2. 在類上添加 @Async 表示該類中的所有方法都是異步的。
  3. 使用此注解的類必須由 Spring 管理。
  4. 必須在啟動類或配置類中添加 @EnableAsync 注解,@Async 才能生效。

在使用 @Async 時,如果不指定線程池的名稱,即不自定義線程池,默認會使用一個線程池。這個默認線程池是 Spring 的 SimpleAsyncTaskExecutor。

默認線程池的默認配置如下:

  1. 默認核心線程數:8。
  2. 最大線程數:Integer.MAX_VALUE。
  3. 隊列類型:LinkedBlockingQueue。
  4. 容量:Integer.MAX_VALUE。
  5. 空閑線程保留時間:60秒。
  6. 線程池拒絕策略:AbortPolicy。

從最大線程數可以看出,在并發情況下,線程會無限制地創建。

你也可以通過 yml 文件重新配置:

spring:
  task:
    execution:
      pool:
        max-size: 10
        core-size: 5
        keep-alive: 3s
        queue-capacity: 1000
        thread-name-prefix: my-executor

你也可以自定義線程池。以下是使用 @Async 自定義線程池的簡單代碼實現:

@EnableAsync // 支持異步操作
@Configuration
public class AsyncTaskConfig {

    /**
     * 來自 com.google.guava 的線程池
     * @return
     */
    @Bean("my-executor")
    public Executor firstExecutor() {
        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("my-executor").build();
        // 獲取 CPU 處理器數量
        int curSystemThreads = Runtime.getRuntime().availableProcessors() * 2;
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(curSystemThreads, 100,
                200, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(), threadFactory);
        threadPool.allowsCoreThreadTimeOut();
        return threadPool;
    }

    /**
     * Spring 的線程池
     * @return
     */
    @Bean("async-executor")
    public Executor asyncExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        // 核心線程數
        taskExecutor.setCorePoolSize(24);
        // 線程池維護的最大線程數,超出核心線程數的線程僅當緩沖隊列滿時才會創建
        taskExecutor.setMaxPoolSize(200);
        // 緩沖隊列
        taskExecutor.setQueueCapacity(50);
        // 超出核心線程數的線程空閑時間,超時后將被銷毀
        taskExecutor.setKeepAliveSeconds(200);
        // 異步方法內部線程名
        taskExecutor.setThreadNamePrefix("async-executor-");

        /**
         * 當線程池的任務緩存隊列已滿,且線程池中的線程數量已達到最大值時,如果還有任務到來,將采用任務拒絕策略。
         * 通常有以下四種策略:
         * ThreadPoolExecutor.AbortPolicy:拋棄任務并拋出 RejectedExecutionException 異常。
         * ThreadPoolExecutor.DiscardPolicy:拋棄任務,但不拋出異常。
         * ThreadPoolExecutor.DiscardOldestPolicy:拋棄隊列最前面的任務,然后嘗試執行當前任務(重復此過程)。
         * ThreadPoolExecutor.CallerRunsPolicy:重試添加當前任務,自動調用執行方法,直到成功。
         */
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        taskExecutor.initialize();
        return taskExecutor;
    }
}

異步失效的原因

  1. 被 @Async 注解的方法不是 public 的;
  2. 被 @Async 注解的方法的返回值類型只能是 void 或 Future;
  3. 被 @Async 注解的方法如果是靜態的也會失效;
  4. 未添加 @EnableAsync 注解;
  5. 調用者和被 @Async 注解的方法不能在同一個類中;
  6. 對異步方法使用 @Transactional 是無效的,但對異步方法內調用的方法加上 @Transactional 是有效的。

線程池中設置核心線程數的問題

我尚未有時間詳細探討:在線程池中設置 CorePoolSize 和 MaxPoolSize 的最適宜和最高效的數量是多少。

借此機會進行了一些測試。

我記得有個關于 CPU 處理器數量的說法

將 CorePoolSize 設置為 CPU 處理器的數量時,效率最高嗎?

// 獲取 CPU 處理器數量
int curSystemThreads = Runtime.getRuntime().availableProcessors() * 2;

Runtime.getRuntime().availableProcessors() 會獲取 CPU 核心線程數,代表計算資源。

  • 對于 CPU 密集型任務,線程池的大小設置為 N,與 CPU 線程數一致,這可以最大限度地減少線程間的上下文切換。但在實際開發中,一般設置為 N+1,以防止線程由于不可預見的情況而阻塞。如果發生阻塞,多出來的線程可以繼續執行任務,保證 CPU 的高效利用。
  • 對于 IO 密集型任務,線程池的大小設置為 2N。這個數值是根據業務壓力測試得出的,或者在不涉及業務時使用推薦值。

實際中,線程池的具體大小需要根據壓力測試以及機器的當前狀態進行調整。

如果線程池過大,會導致 CPU 持續切換,系統整體性能并不會有顯著提高,反而可能會變慢。

我電腦的 CPU 處理器數量為 24。

那么一次讀取多少行效率最高呢?

測試中,Excel 文件包含 10 萬行數據。10 萬 / 24 = 4166,因此我設置為 4200。這是最有效的設置嗎?

測試過程中似乎的確如此。

我記得大家習慣性地將核心線程數(CorePoolSize)和最大線程數(MaxPoolSize)設置為相同的數值,通常是 200。

這只是隨機選擇,還是基于經驗的?

測試發現,當 CorePoolSize 和 MaxPoolSize 都設置為 200 時,最初同時開啟了 150 個線程工作。

為什么會這樣呢?

經過數十次測試后

  1. 發現核心線程數并沒有太大區別;
  2. 關鍵是每次讀取和存儲的行數,不能太多,存儲速度會逐漸減慢;
  3. 也不能太少,如果少于 150 個線程,會導致線程阻塞,反而減慢進程。

IV.使用 EasyExcel 讀取并插入數據庫

我不會寫 EasyExcel 的雙異步優化。大家要記住避免掉進低級勤奮的陷阱。

ReadEasyExcelController

@RequestMapping(value = "/readEasyExcel", method = RequestMethod.POST)
@ResponseBody
public String readEasyExcel() {
    try {
        String path = "G:\\Test\\data\\";
        String[] xlsxArr = new File(path).list();
        for (int i = 0; i < xlsxArr.length; i++) {
            String filePath = path + xlsxArr[i];
            File fileTemp = new File(path + xlsxArr[i]);
            String fileName = fileTemp.getName().replace(".xlsx", "");
            List<UserInfo> list = new ArrayList<>();
            EasyExcel.read(filePath, UserInfo.class, new ReadEasyExeclAsyncListener(readEasyExeclService, fileName, batchCount, list)).sheet().doRead();
        }
    }catch (Exception e){
        logger.error("readEasyExcel Exception:",e);
        return "error";
    }
    return "success";
}

ReadEasyExeclAsyncListener

public ReadEasyExeclService readEasyExeclService;
// 表名
public String TABLE_NAME;
// 批量插入閾值
private int BATCH_COUNT;
// 數據收集
private List<UserInfo> LIST;

public ReadEasyExeclAsyncListener(ReadEasyExeclService readEasyExeclService, String tableName, int batchCount, List<UserInfo> list) {
    this.readEasyExeclService = readEasyExeclService;
    this.TABLE_NAME = tableName;
    this.BATCH_COUNT = batchCount;
    this.LIST = list;
}

@Override
public void invoke(UserInfo data, AnalysisContext analysisContext) {
    data.setUuid(uuid());
    data.setTableName(TABLE_NAME);
    LIST.add(data);
    if (LIST.size() >= BATCH_COUNT) {
        // 批量入庫
        readEasyExeclService.saveDataBatch(LIST);
    }
}

@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    if (LIST.size() > 0) {
        // 最后一批入庫
        readEasyExeclService.saveDataBatch(LIST);
    }
}

public static String uuid() {
    return UUID.randomUUID().toString().replace("-", "");
}

ReadEasyExeclServiceImpl

@Service
public class ReadEasyExeclServiceImpl implements ReadEasyExeclService {

    @Resource
    private ReadEasyExeclMapper readEasyExeclMapper;

    @Override
    public void saveDataBatch(List<UserInfo> list) {
        // Insert into the database via mybatis
        readEasyExeclMapper.saveDataBatch(list);
      // Insert into the database via JDBC
        // insertByJdbc(list);
        list.clear();
    }
    
    private void insertByJdbc(List<UserInfo> list){
        List<String> sqlList = new ArrayList<>();
        for (UserInfo u : list){
            StringBuilder sqlBuilder = new StringBuilder();
            sqlBuilder.append("insert into ").append(u.getTableName()).append(" ( UUID,ID,NAME,AGE,ADDRESS,PHONE,OP_TIME ) values ( ");
            sqlBuilder.append("'").append(ReadEasyExeclAsyncListener.uuid()).append("',")
                            .append("'").append(u.getId()).append("',")
                            .append("'").append(u.getName()).append("',")
                            .append("'").append(u.getAge()).append("',")
                            .append("'").append(u.getAddress()).append("',")
                            .append("'").append(u.getPhone()).append("',")
                            .append("sysdate )");
            sqlList.add(sqlBuilder.toString());
        }

        JdbcUtil.executeDML(sqlList);
    }
}

UserInfo

@Data
public class UserInfo {

    private String tableName;

    private String uuid;

    @ExcelProperty(value = "ID")
    private String id;

    @ExcelProperty(value = "NAME")
    private String name;

    @ExcelProperty(value = "AGE")
    private String age;

    @ExcelProperty(value = "ADDRESS")
    private String address;

    @ExcelProperty(value = "PHONE")
    private String phone;
}

結語

在處理高并發、大數據導入等場景時,異步編程和線程池技術提供了一種極具效率的解決方案。通過合理配置線程池的核心線程數、最大線程數、隊列長度等參數,能夠在確保系統穩定性的前提下,大幅提升并發處理能力。而通過異步編程,我們可以有效避免線程阻塞、減少資源浪費,并讓系統在面對大量請求時依然能夠保持較高的響應速度。

本文的示例通過 Spring Boot 的 @Async 注解和自定義線程池,在實際的 EasyExcel 大數據導入場景下,驗證了這種技術組合的高效性和實用性。此外,通過對 CPU 密集型任務和 IO 密集型任務的深入分析,開發者能夠根據自身項目的特點,選擇合適的線程池配置策略,最大化資源利用率和性能表現。

在實際應用中,線程池和異步編程不僅適用于大數據導入,還可以推廣到包括文件處理、網絡請求、日志處理等各類需要并發處理的場景中。因此,掌握并靈活運用這些技術,將為我們的系統性能優化提供堅實的基礎,使我們能夠應對更復雜、更苛刻的業務需求。

責任編輯:武曉燕 來源: 路條編程
相關推薦

2024-12-19 07:50:00

2019-01-30 09:34:56

ElasticSearLogstashKibana

2022-09-26 09:41:25

MySQL數據庫

2023-12-25 08:24:03

雙異步數據庫Excel

2025-03-27 00:14:10

2019-08-21 14:35:18

壓縮文件優化過程Java

2025-06-27 09:05:47

2020-11-12 18:51:43

Java編程語言

2019-09-27 17:24:26

數據庫優化sql

2009-07-21 08:44:14

微軟Linux內核開源操作系統

2025-06-25 09:30:14

2013-11-11 11:17:45

AngularJS性能優化

2021-03-02 13:56:24

Linux 5.12代碼驅動

2025-06-04 02:20:00

SQL優化儀表盤

2017-12-25 11:15:06

JavaArray數組

2022-09-01 08:42:36

SQL數據項目

2020-08-17 17:10:54

機器學習聚類開發

2024-02-05 13:28:00

Excel優化服務器

2023-06-29 08:22:43

數據Excel模板

2021-08-26 22:26:55

性能優化技術
點贊
收藏

51CTO技術棧公眾號

黄视频在线免费看| 国产乱码在线观看| 国产精品毛片久久久| 天天亚洲美女在线视频| 欧洲一区二区在线观看| 国产欧美综合视频| 欧美亚洲一区二区三区| 精品激情国产视频| 一级欧美一级日韩片| 国产精品久久乐| 亚洲男同性视频| 国产精品久久精品国产| 成年人晚上看的视频| 国产精品s色| 在线免费观看羞羞视频一区二区| 日本亚洲一区二区三区| 粉嫩一区二区三区| 亚洲国产精品自拍| 一本一本久久a久久精品综合妖精| 风流少妇一区二区三区91| 免费人成在线不卡| 5566日本婷婷色中文字幕97| 911国产在线| 蜜桃国内精品久久久久软件9| 欧美哺乳videos| xxww在线观看| 芒果视频成人app| 在线最新版中文在线| 国产不卡视频一区| 国产女人18毛片水18精品| 欧美videossex极品| 欧美激情综合色综合啪啪| 国产一区二区三区丝袜| 亚洲一区二区三区四区五区六区| 亚洲资源在线| 欧美三级电影在线观看| 欧美一级视频在线播放| 成人黄色网址| 亚洲欧洲国产日韩| 亚洲精品9999| 都市激情一区| 久久天天做天天爱综合色| 国产精品一区二区欧美黑人喷潮水| 国产美女免费视频| 久久国产精品一区二区| 国产精品爱啪在线线免费观看| 色婷婷av国产精品| 亚洲高清网站| 97国产在线观看| 国产午夜精品一区二区理论影院| 一本到12不卡视频在线dvd| 日韩在线欧美在线国产在线| 成人性生交大片免费看无遮挡aⅴ| 免费观看久久av| 亚洲精品小视频在线观看| xxxx黄色片| 天海翼亚洲一区二区三区| 亚洲国产天堂久久综合网| 折磨小男生性器羞耻的故事| 国产成人高清精品免费5388| 精品福利av导航| 亚洲自拍偷拍精品| 欧美精品国产白浆久久久久| 亚洲国产免费av| 欧美高清性xxxx| 精品高清在线| 日韩性生活视频| 成人免费视频国产免费观看| 中国成人一区| 国内外成人免费激情在线视频网站 | 日韩成人亚洲| 欧美午夜精品久久久| 亚洲精品久久久中文字幕| 亚洲黑人在线| 亚洲成人a级网| 亚洲做受高潮无遮挡| 精品一区二区三| 久久精品国产亚洲精品2020| 精国产品一区二区三区a片| 亚洲精品国产日韩| 国产成人avxxxxx在线看| 中文在线观看av| 国产精品99久久久久久有的能看| 国产久一道中文一区| 欧洲伦理片一区 二区 三区| 国产精品理伦片| 日韩a级黄色片| 成人亚洲欧美| 欧美一卡二卡三卡| 免费看黄色aaaaaa 片| 欧美一区电影| 欧美激情在线观看视频| 久久免费激情视频| 麻豆国产欧美日韩综合精品二区 | 国内露脸中年夫妇交换精品| 亚洲男人的天堂在线播放| 国产精品综合激情| 亚洲日韩成人| 成人免费直播live| 天堂v视频永久在线播放| 中文字幕av不卡| 欧美一级片免费播放| 日韩制服一区| 亚洲高清不卡av| 人人干在线观看| 国产精品久久久免费 | 6080亚洲理论片在线观看| 欧美一级欧美三级在线观看| www.国产福利| 欧美精选一区二区三区| 久久久久久久久久久亚洲| 日韩欧美国产另类| av午夜精品一区二区三区| 精品久久免费观看| 原纱央莉成人av片| 精品久久人人做人人爽| 女教师淫辱の教室蜜臀av软件| aa级大片欧美三级| 97人人模人人爽人人喊38tv| 亚洲成人影院麻豆| 色婷婷狠狠综合| 深田咏美中文字幕| 综合国产精品| 成人久久18免费网站图片| 国内av一区二区三区| 亚洲国产成人91porn| 久久精品一二三四| 久久久久久久久久久9不雅视频| 国产99久久精品一区二区永久免费| 亚洲欧美另类综合| 亚洲精品久久嫩草网站秘色| 日韩精品视频一二三| 亚洲人挤奶视频| 97超级碰碰人国产在线观看| 好吊色在线观看| 亚洲一区二区三区影院| 韩国三级在线播放| 一个色综合网| 91在线观看免费网站| √新版天堂资源在线资源| 91国产视频在线观看| 国产手机在线观看| 久久亚洲精品伦理| 久久国产精品一区二区三区| 欧美a级在线观看| 亚洲精品wwww| 日韩欧美成人一区二区三区 | 麻豆视频免费在线播放| 热久久一区二区| 四虎影院一区二区三区| 无人区在线高清完整免费版 一区二| 亚洲欧美日韩综合| 久久久久精彩视频| 国产精品人成在线观看免费| 超碰超碰在线观看| 91久久国产| 91gao视频| а√天堂中文在线资源8| 亚洲国产成人91精品| 国产免费av一区二区| 久久夜色精品一区| www.天天射.com| 国产高清欧美| 超碰97人人在线| 国产直播在线| 亚洲偷熟乱区亚洲香蕉av| 伊人久久亚洲综合| 亚洲人午夜精品天堂一二香蕉| 欧美色图校园春色| 亚洲美洲欧洲综合国产一区| 欧美日韩一区二区三| www.精品国产| 欧美老女人在线视频| 天天干天天色天天| 欧美最新大片在线看| 疯狂试爱三2浴室激情视频| 国产成人午夜精品影院观看视频| 免费看日本毛片| 精品久久美女| 99精品99久久久久久宅男| 欧美男人天堂| 久久好看免费视频| 色一情一乱一区二区三区| 在线日韩av片| 久久久精品视频在线| 久久久亚洲高清| 色婷婷综合在线观看| 国产精品嫩草99av在线| 亚洲精品欧美精品| 国产精品videossex| 国产精品高清网站| 欧洲成人综合网| 亚洲最新av网址| 成人无码一区二区三区| 欧美在线视频你懂得| 国产亚洲成人av| 国产精品女主播av| jizz日本免费| 国产精品中文字幕一区二区三区| 日本wwww视频| 午夜视频精品| 亚洲免费精品视频| 欧美1区二区| 亚洲中国色老太| 亚洲第一会所001| 久久久久久久久中文字幕| 草碰在线视频| 精品香蕉一区二区三区| 99久久久国产精品无码网爆| 91黄色在线观看| 午夜精品久久久久久久久久久久久蜜桃| 国产精品乱码妇女bbbb| 伊人网伊人影院| 成人午夜激情片| 欧美精品 - 色网| 麻豆精品视频在线观看免费| av免费中文字幕| 亚洲美女少妇无套啪啪呻吟| 激情视频小说图片| 首页国产精品| 色综合久久av| 青青草这里只有精品| 不卡视频一区二区三区| **精品中文字幕一区二区三区| 热99久久精品| 亚洲深夜视频| 97国产精品视频| www欧美xxxx| 欧美激情啊啊啊| 最爽无遮挡行房视频在线| 日韩在线小视频| 91av资源在线| 一本色道久久88综合亚洲精品ⅰ| 欧美少妇另类| 亚洲精品一区二区三区婷婷月| 午夜视频免费在线| 亚洲成人激情在线| 内射无码专区久久亚洲| 日韩午夜精品电影| 国产成人免费看一级大黄| 欧美一区二视频| av中文在线观看| 日韩欧美在线不卡| xxxx国产精品| 精品1区2区在线观看| 后入内射欧美99二区视频| 精品剧情在线观看| 色一情一乱一区二区三区| 日韩激情视频在线| 色av男人的天堂免费在线| 日韩毛片在线观看| 你懂得网站在线| 亚洲午夜精品久久久久久性色| 国产一二在线观看| 最近2019中文字幕mv免费看| 免费黄色在线看| 久久综合亚洲社区| 欧美性爽视频| 2019精品视频| 成人日韩在线| 亚洲一区二区三区成人在线视频精品| 欧美二区观看| 精品国产一区二区三区免费| 在线日本制服中文欧美| 久久国产精品99国产精| 国产精成人品免费观看| 成人免费毛片嘿嘿连载视频| 无码精品一区二区三区在线播放| 91在线porny国产在线看| 日韩人妻无码一区二区三区| 国产欧美一区二区精品性色| 亚洲天堂av中文字幕| 亚洲乱码一区二区三区在线观看| 国产在线综合网| 欧美性猛交xxxx富婆| 亚洲视频在线免费播放| 日韩欧美成人一区| 日韩精品福利| 日韩有码视频在线| 成全电影大全在线观看| 国产99视频精品免视看7| 青草综合视频| 国产一区免费视频| 精品免费一区二区| 8x8ⅹ国产精品一区二区二区| 国产手机视频一区二区| 日韩av.com| www.日本不卡| 青青操在线视频观看| 午夜视频在线观看一区二区三区| 日韩乱码一区二区三区| 欧美tickling网站挠脚心| 国产在线91| 欧美黄色三级网站| 91成人在线| 国产日韩精品推荐| 久久中文字幕av| 凹凸国产熟女精品视频| 国产麻豆视频一区二区| 日韩人妻一区二区三区| 中文字幕亚洲在| 51国产偷自视频区视频| 欧美日韩一区二区三区在线看 | 日韩久久免费视频| av免费网站在线观看| 欧美做爰性生交视频| 伊色综合久久之综合久久| 亚洲欧洲一二三| 亚洲欧美视频| 亚洲一区二区三区黄色| 亚洲欧美影音先锋| 国产一级片免费视频| 日韩黄色在线免费观看| 26uuu亚洲电影在线观看| 国产精品嫩草视频| 亚洲另类av| www.av片| 福利视频网站一区二区三区| 五月婷婷综合激情网| 欧美少妇一区二区| 青春有你2免费观看完整版在线播放高清| 九九九久久久久久| 亚洲欧美在线综合| 视频一区亚洲| 三级影片在线观看欧美日韩一区二区| 又黄又色的网站| 有码一区二区三区| 国产欧美一区二区三区视频在线观看| 中文字幕日韩欧美| 韩国精品主播一区二区在线观看| 久久亚洲国产精品日日av夜夜| 亚洲国产免费| 日批免费观看视频| 一区二区三区四区精品在线视频 | 中文字幕av久久| 男人的天堂久久精品| 国产jk精品白丝av在线观看 | 欧美激情在线视频二区| 91成人短视频| 成人一级生活片| 成人黄色a**站在线观看| 免费一级肉体全黄毛片| 日韩欧美高清dvd碟片| 毛片在线导航| 国产亚洲欧美一区二区三区| 亚洲高清毛片| 性欧美成人播放77777| 欧美日韩亚洲精品内裤| 三级视频在线| 国产成人免费av电影| 第一会所亚洲原创| jizz18女人| 亚洲日本成人在线观看| 精品人妻一区二区三区麻豆91 | www.久久久久久.com| 日韩成人精品一区二区三区| 中文字幕黄色大片| 国产精品乡下勾搭老头1| 欧美黑人一级片| 亚洲国产福利在线| 超碰一区二区| 亚洲一区精彩视频| 国产一本一道久久香蕉| 国产精品9191| 亚洲一区二区黄| 日韩免费在线电影| 91精品国产吴梦梦| jlzzjlzz亚洲日本少妇| 无码人妻精品一区二区50| 中文字幕精品久久| 国产午夜精品一区在线观看| www污在线观看| 久久久精品欧美丰满| 一级片aaaa| 国内精品模特av私拍在线观看| 色综合中文网| www.成年人| 精品成人久久av| 日韩在线免费电影| 国产精品一区二区三区免费观看| 销魂美女一区二区三区视频在线| 亚洲精品国产精品国自| 日韩精品一区二区三区老鸭窝| 中文字幕不卡三区视频| 六月婷婷激情网| 久久伊99综合婷婷久久伊| 国产又大又黄的视频| 91禁外国网站| 亚洲乱码电影| 国产精品久久久久无码av色戒| 91麻豆精品国产91久久久使用方法 | 国产精品亚洲人成在99www| 国产成年人视频网站| 亚洲sss视频在线视频| 18视频免费网址在线观看| 国产精品一区二区a| 韩国av一区二区三区| 亚洲不卡视频在线观看| 欧美成人网在线| 欧美日中文字幕|