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

SpringBoot整合RabbitMQ實現郵件異步發送

開發 架構
本文主要以實現郵件自動推送這個業務場景為例,通過 Springboot 整合 rabbitMQ 技術來實現高可用的效果。

本篇文章將介紹另一種高可用的服務架構,以便實現郵件 100% 被投遞成功。類似的短信推送等服務,實現邏輯也大體類似。

01、先來一張流程圖

圖片圖片

本文內容主要圍繞這個流程圖展開,利用 RabbitMQ 消息隊列來實現郵件 100% 被投遞,內容涵蓋了 RabbitMQ 很多知識點,如:

  • 生產者和消費者模型
  • 消息發送機制
  • 消費確認機制
  • 消息的重新投遞
  • 消息消費失敗的處理方案

02、實現思路

  • 1.準備一臺電腦,并安裝 RabbitMQ 服務
  • 2.開放 QQ 郵箱或者其它郵箱授權碼,用于發送郵件
  • 3.創建郵件發送項目并編寫代碼
  • 4.發送郵件測試
  • 5.消息消費失敗的處理介紹

03、環境準備

3.1、安裝 RabbitMQ 服務

安裝 RabbitMQ 服務,這一步比較簡單,可以訪問下面的官方地址,下載軟件包并依次按照步驟進行安裝即可。

https://rabbitmq.org.cn/docs/download

安裝成功之后,登陸 RabbitMQ 控制臺,可以看到類似于如下界面。

圖片圖片

3.1.1、創建交換器

點擊“Exchanges”菜單,進入“交換器”管理界面。

圖片圖片

進入之后,點擊最下方“Add a new exchange”按鈕,創建一個類型為topic,名稱叫mail.exchange的交換器,并提交。

圖片圖片

3.1.2、創建消息隊列

接著,點擊“Queues”菜單,進入消息隊列管理界面。

圖片圖片

同樣的,點擊最下方“Add a new queue”按鈕,創建一個名稱叫mq.mail.ack的消息隊列,并提交。

圖片圖片

保存之后,在列表中可以看到剛剛創建的消息隊列,然后點擊進入詳情。

圖片圖片

在詳情中,將當前消息隊列與上文創建的交換器進行綁定,便于后續通過交換器來發送消息到隊列,操作如下。

圖片圖片

對于topic類型的交換器,通常不直接與消息隊列進行交互,而是通過一個路由鍵,將消息路由到目標消息隊列,這樣設計的目的是讓消息投遞更加靈活。路由鍵,可以簡單理解為類似于路由器,對數據進行路由分發處理。

3.2、配置郵箱發送服務器

為了實現郵件自動發送功能,我們還需要準備一個郵箱發送服務器,這一步在之前的文章中已經詳細的介紹過,在此,我們簡單的再介紹一下。

以 QQ 郵箱為例,登陸進去之后,在設置里面開啟 POP3/SMTP 服務,并獲取授權碼記錄下來。

圖片圖片

圖片圖片

該授權碼,就是下文配置文件中spring.mail.password需要的密碼!

04、方案實踐

4.1、構建項目

在 IDEA 下創建一個名稱為smail的 Spring Boot 項目,pom文件中加入amqp和mail相關依賴包,示例如下:

<!--mail 支持-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<!--amqp 支持-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

4.2、添加相關配置

在application.properties中添加 rabbitmq、郵箱相關配置,示例如下:

# 配置郵件發送主機地址
spring.mail.host=smtp.exmail.qq.com
# 配置郵件發送服務端口號
spring.mail.port=465
# 配置郵件發送服務協議
spring.mail.protocol=smtp
# 配置郵件發送者用戶名或者賬戶
spring.mail.username=xxxx
# 配置郵件發送者密碼或者授權碼
spring.mail.password=xxxx
# 配置郵件默認編碼
spring.mail.default-encoding=UTF-8
# 配置smtp相關屬性
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.ssl.enable=true
spring.mail.properties.mail.smtp.ssl.required=true

#rabbitmq配置
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.virtual-host=/
spring.rabbitmq.username=test
spring.rabbitmq.password=test
# 開啟confirms回調 P -> Exchange
spring.rabbitmq.publisher-cnotallow=true
# 開啟returnedMessage回調 Exchange -> Queue
spring.rabbitmq.publisher-returns=true
# 設置手動確認(ack) Queue -> C
spring.rabbitmq.listener.simple.acknowledge-mode=manual
spring.rabbitmq.listener.simple.prefetch=100

其中,spring.mail.username和spring.mail.password指的就是上文中創建的郵箱賬號和授權碼,將其配置進去即可。

4.3、編寫 RabbitMQ 配置類

編寫一個 RabbitMQ 配置類,用于監聽消息的發送情況,示例如下。

@Configuration
public class RabbitConfig {

    private static final Logger LOGGER = LoggerFactory.getLogger(RabbitConfig.class);


    @Autowired
    private CachingConnectionFactory connectionFactory;

    @Bean
    public RabbitTemplate rabbitTemplate() {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        // 設置消息轉換器為json格式
        rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());

        // 消息是否成功發送到Exchange
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                LOGGER.info("消息發送到Exchange成功,{}", correlationData);
            } else {
                LOGGER.error("消息發送到Exchange失敗, {}, cause: {}", correlationData, cause);
            }
        });

        // 觸發setReturnCallback回調必須設置mandatory=true, 否則Exchange沒有找到Queue就會丟棄掉消息, 而不會觸發回調
        rabbitTemplate.setMandatory(true);

        // 消息是否從Exchange路由到Queue, 注意: 這是一個失敗回調, 只有消息從Exchange路由到Queue失敗才會回調這個方法
        rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
            LOGGER.error("消息從Exchange路由到Queue失敗: exchange: {}, route: {}, replyCode: {}, replyText: {}, message: {}", exchange, routingKey, replyCode, replyText, message);
        });

        return rabbitTemplate;
    }
}

4.4、編寫生產者服務

在 Spring Boot 中,我們可以利用RabbitTemplate工具,將數據通過交換器發送到目標消息隊列,示例如下。

@Service
public class ProduceService {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 發送消息
     * @param mail
     * @return
     */
    public boolean sendByAck(Mail mail) {
        // 創建uuid
        String msgId = UUID.randomUUID().toString().replaceAll("-", "");
        mail.setMsgId(msgId);

        // 發送消息到mq服務器中(附帶消息ID)
        CorrelationData correlationData = new CorrelationData(msgId);
        rabbitTemplate.convertAndSend("mail.exchange", "route.mail.ack", MessageHelper.objToMsg(mail), correlationData);
        return true;
    }
}

4.5、編寫消費者服務

在 Spring Boot 中,我們可以利用@RabbitListener注解,監聽指定的消息隊列,如果隊列中有消息會第一時間收到回調,示例如下。

@Component
public class ConsumerService {

    private static final Logger LOGGER = LoggerFactory.getLogger(ConsumerService.class);

    @Autowired
    private SendMailService sendMailService;

    /**
     * 監聽消息隊列,手動確認模式,必須手動調用ack或者nack方法
     * 配置參數:spring.rabbitmq.listener.simple.acknowledge-mode=manual
     * @param message
     * @param channel
     * @throws IOException
     */
    @RabbitListener(queues = {"mq.mail.ack"})
    public void consumeFromAck(Message message, Channel channel) throws IOException {
        LOGGER.info("收到消息:{}", message.toString());
        //將消息轉化為對象
        Mail mail = MessageHelper.msgToObj(message, Mail.class);

        // 手動確認模式
        long tag = message.getMessageProperties().getDeliveryTag();
        boolean success = sendMailService.send(mail);
        if (success) {
            // 消費成功,消息會被刪除
            channel.basicAck(tag, false);
        } else {
            // 消費失敗,重新返回隊列
            channel.basicNack(tag, false, true);
        }
    }
}

4.6、編寫郵件發送服務

正如之前的文章中所介紹的,在 Spring Boot 中,我們可以利用JavaMailSender工具來實現郵件的自動推送,示例如下。

@Service
public class SendMailService {

    private static final Logger LOGGER = LoggerFactory.getLogger(SendMailService.class);


    @Value("${spring.mail.username}")
    private String from;

    @Autowired
    private JavaMailSender mailSender;

    /**
     * 發送簡單郵件
     *
     * @param mail
     */
    public boolean send(Mail mail) {
        String to = mail.getTo();// 目標郵箱
        String title = mail.getTitle();// 郵件標題
        String content = mail.getContent();// 郵件正文

        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(from);
        message.setTo(to);
        message.setSubject(title);
        message.setText(content);

        try {
            mailSender.send(message);
            LOGGER.info("郵件發送成功");
            return true;
        } catch (MailException e) {
            LOGGER.error("郵件發送失敗, to: {}, title: {}", to, title, e);
            return false;
        }
    }
}

4.7、編寫 controller 接口

接著,編寫一個 controller 接口,將郵件發送服務暴露出去,示例如下:

@RestController
public class MailController {

    @Autowired
    private ProduceService produceService;

    @PostMapping("send")
    public String sendMail(Mail mail) {
        boolean result = produceService.sendByAck(mail);
        return result ? "success": "fail";
    }
}

4.8、服務測試

最后,啟動 SpringBoot 服務,用 postman 來測試一下。

圖片圖片

查看控制臺信息。

圖片圖片

查詢接受者郵件信息。

圖片圖片

可以清楚的看到,郵件發送成功!

當大批量的發送郵件,也不用擔心,因為整個郵件的發送都是異步的,不會阻塞主流程的運行。

05、消費失敗的處理方案

雖然以上的方案非常可靠,可以保證發出的消息 100% 被消費,但是其實也有弊端。

試想一下,按照上面的處理邏輯,假設其中有一條消息,因為某種原因一直發送失敗,會出現什么樣的情況?

此時,這條消息會重新返回隊列,然后一直重試,會導致其它的消息可能會無法被消費。

針對這種情況,最簡單粗暴的辦法就是,當重試失敗之后將消息丟棄,不會阻礙其它的消息被正常處理,不過會丟失數據。

那么如何正確的處理消息消費失敗的問題呢?

可以借助數據庫來記錄消費失敗的數據,針對系統無法成功處理的消息,人工進行干預。

實踐過程如下!

5.1、創建一張消息日志表

首先,在數據庫中創建一張消息日志表,用于跟蹤消息數據的狀態,示例如下:

CREATE TABLE `msg_log` (
  `msg_id` varchar(255) NOT NULL DEFAULT '' COMMENT '消息唯一標識',
  `exchange` varchar(100) NOT NULL DEFAULT '' COMMENT '交換機',
  `route_key` varchar(100) NOT NULL DEFAULT '' COMMENT '路由鍵',
  `queue_name` varchar(100) NOT NULL DEFAULT '' COMMENT '隊列名稱',
  `msg` text COMMENT '消息體, json格式化',
  `result` varchar(255) DEFAULT NULL COMMENT '處理結果',
  `status` int(11) NOT NULL DEFAULT '0' COMMENT '狀態,0:等待消費,1:消費成功,2:消費失敗,9:重試失敗',
  `try_count` int(11) NOT NULL DEFAULT '0' COMMENT '重試次數',
  `next_try_time` datetime DEFAULT NULL COMMENT '下一次重試時間',
  `create_time` datetime DEFAULT NULL COMMENT '創建時間',
  `update_time` datetime DEFAULT NULL COMMENT '更新時間',
  PRIMARY KEY (`msg_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='mq消息日志';

5.2、改寫生產者邏輯

在生產者服務類中,先將消息數據寫入數據庫,再向 rabbitMQ 服務中發消息,示例如下:

@Service
public class ProduceService {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private MsgLogService msgLogService;

    /**
     * 發送消息
     * @param mail
     * @return
     */
    public boolean sendByAuto(Mail mail) {
        String msgId = UUID.randomUUID().toString().replaceAll("-", "");
        mail.setMsgId(msgId);

        // 1.存儲要消費的數據
        msgLogService.save("mail.exchange", "route.mail.auto", "mq.mail.auto", msgId, mail);

        // 2.發送消息到mq服務器中(附帶消息ID)
        CorrelationData correlationData = new CorrelationData(msgId);
        rabbitTemplate.convertAndSend("mail.exchange", "route.mail.auto", MessageHelper.objToMsg(mail), correlationData);
        return true;
    }
}

5.3、改寫消費者邏輯

在消費者服務類中,收到消息之后,不管處理成功還是失敗,都只會修改數據庫中的消息狀態,并且消息處理失敗時,不再重新返回隊列。

@Component
public class ConsumerService {

    private static final Logger LOGGER = LoggerFactory.getLogger(ConsumerService.class);

    @Autowired
    private SendMailService sendMailService;

    @Autowired
    private MsgLogService msgLogService;

    /**
     * 監聽消息隊列,自動確認模式,無需調用ack或者nack方法,當程序執行時才刪除消息
     * 配置參數:spring.rabbitmq.listener.simple.acknowledge-mode=auto
     * @param message
     */
    @RabbitListener(queues = {"mq.mail.auto"})
    public void consumeFromAuto(Message message) {
        LOGGER.info("收到消息:{}", message.toString());
        // 獲取消息ID
        Mail mail = MessageHelper.msgToObj(message, Mail.class);

        // 消息冪等性處理,如果已經處理成功,無需重復消費
        MsgLog queryObj = msgLogService.selectByMsgId(mail.getMsgId());
        if(Objects.nonNull(queryObj) && Constant.SUCCESS.equals(queryObj.getStatus())){
            return;
        }

        // 發送郵件
        boolean success = sendMailService.send(mail);
        if(success){
            msgLogService.updateStatus(mail.getMsgId(), Constant.SUCCESS, "郵件發送成功");
        } else {
            msgLogService.updateStatus(mail.getMsgId(), Constant.FAIL, "郵件發送失敗");
        }
    }
}

因為此處采用自動確認模式,因此還需要修改application.properties中的配置參數,內容如下:

# 設置自動確認(默認此模式)
spring.rabbitmq.listener.simple.acknowledge-mode=auto

5.4、編寫定時任務對失敗消息進行補償投遞

當消息消費失敗時,會自動記錄到數據庫。

實際上,不可能每條數據都需要我們進行干預,有的可能重試一次就好了,因此可以編寫一個定時任務,將消費失敗的數據篩選出來,重新放入到消息隊列中,只有當消費次數達到設置的最大值,此時進入人工干預階段,可以節省不少的工作。

示例如下:

@Component
public class ScheduledTask {

    private static final Logger LOGGER = LoggerFactory.getLogger(ScheduledTask.class);

    /**
     * 最大投遞次數
     */
    private static final int MAX_TRY_COUNT = 3;

    @Autowired
    private MsgLogService msgLogService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 每30s拉取消費失敗的消息, 重新投遞
     */
    @Scheduled(cron = "0/30 * * * * ?")
    public void retry() {
        LOGGER.info("開始執行重新投遞消費失敗的消息!");
        // 查詢需要重新投遞的消息
        List<MsgLog> msgLogs = msgLogService.selectFailMsg();
        for (MsgLog msgLog : msgLogs) {
            if (msgLog.getTryCount() >= MAX_TRY_COUNT) {
                msgLogService.updateStatus(msgLog.getMsgId(), Constant.RETRY_FAIL, msgLog.getResult());
                LOGGER.info("超過最大重試次數, msgId: {}", msgLog.getMsgId());
                break;
            }

            // 重新投遞消息
            CorrelationData correlationData = new CorrelationData(msgLog.getMsgId());
            rabbitTemplate.convertAndSend("", msgLog.getQueueName(), MessageHelper.objToMsg(msgLog.getMsg()), correlationData);
            // 更新下次重試時間
            msgLogService.updateNextTryTime(msgLog.getMsgId(), msgLog.getTryCount());
        }
    }
}

最后別忘了,在Application類上添加@EnableScheduling,以便讓定時調度生效,示例如下:

@EnableScheduling
@SpringBootApplication
public class Application {

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

利用定時任務,對投遞失敗的消息進行補償投遞,基本可以保證消息 100% 消費成功!

06、小結

本文主要以實現郵件自動推送這個業務場景為例,通過 Springboot 整合 rabbitMQ 技術來實現高可用的效果。

當然,解決這個業務需求的技術方案還有很多,例如 Springboot 整合 rocketMQ 也可以實現這個效果,不管怎么變,底層的實現思路基本都一樣。

希望本篇的知識總結,對大家有所幫助。

最后,代碼都經過自測,想要獲取項目源碼的同學,可以點擊如下地址獲取。

示例代碼地址:

https://gitee.com/pzblogs/spring-boot-example-demo

責任編輯:武曉燕 來源: 潘志的研發筆記
相關推薦

2024-12-24 08:44:55

ActiveMQRabbitMQ交換機

2024-11-04 08:02:23

SpringRabbitMQ中間件

2024-09-02 09:14:36

SpringRabbitMQ數據

2022-09-02 15:08:02

Python郵件發送

2020-09-08 07:37:44

springBoot MQ rabbitMQ

2024-11-14 12:22:37

SpringMail郵件

2025-05-29 01:33:00

微服務架構系統

2021-11-15 14:02:27

RPCSpringBootRabbitMQ

2023-08-08 08:28:03

消息消費端Spring

2025-05-16 08:55:58

2025-03-04 08:40:28

2020-04-23 15:08:41

SpringBootMyCatJava

2023-12-07 18:02:38

RabbitMQ異步通信

2009-12-02 16:31:54

PHP發送郵件

2009-12-09 15:23:36

PHP mail()函

2023-08-10 11:39:54

RabbitMQSpring交換機

2023-03-06 08:16:04

SpringRabbitMQ

2024-08-12 12:17:03

2022-04-28 07:31:41

Springkafka數據量

2017-04-26 09:00:23

Python發送郵件腳本
點贊
收藏

51CTO技術棧公眾號

日韩欧美国产三级电影视频| 国产欧美一区二区精品久导航| 久久久精品影院| 2018国产精品| av高清一区| 亚洲品质自拍视频| 免费99视频| 国产又大又长又粗| 国产精品久久久久久模特| 综合网日日天干夜夜久久| 精品国产乱码久久久久久1区二区| 波多野结衣精品| 国产精品美女久久久久aⅴ国产馆 国产精品美女久久久久av爽李琼 国产精品美女久久久久高潮 | 国产精品一区二区三区四区| 97在线视频一区| 成人做爰视频网站| 国产毛片一区二区三区| 精品久久久久久无| www.日本一区| 中文字幕在线中文字幕在线中三区 | 春色成人在线视频| 中文字幕日本人妻久久久免费 | 国产精品久久一级| 精品国产一区二区三区四区精华| 亚洲无码精品在线观看| 国产精品日韩久久久| 欧美另类极品videosbest最新版本 | 日韩综合视频在线观看| 熟女丰满老熟女熟妇| 一区二区三区在线资源| 欧美日韩精品免费观看视频| 精品一区二区中文字幕| 超免费在线视频| 一区二区三区四区精品在线视频| 宅男在线精品国产免费观看| 成人性爱视频在线观看| 91美女片黄在线观看91美女| 成人毛片网站| 粉嫩av一区二区夜夜嗨| 国产麻豆精品theporn| 国产视频福利一区| 中文字幕在线观看第二页| 日日摸夜夜添夜夜添亚洲女人| 国模精品视频一区二区| 久久精品性爱视频| 欧美女激情福利| 久久99亚洲热视| 亚洲色图综合区| 99精品视频在线观看播放| 国产香蕉一区二区三区在线视频 | 亚洲都市激情| 亚洲精品电影久久久| 美女网站视频在线观看| 国产精品chinese在线观看| 日韩欧美国产wwwww| 成年人看片网站| 视频一区中文字幕精品| 日韩视频免费观看高清完整版| 国产精品久久久久久9999| 日韩一区中文| 日韩欧美精品三级| 99免费观看视频| 欧美电影免费网站| 国产视频在线一区二区| 最近中文字幕在线mv视频在线 | 国产成人精品三级| 电影午夜精品一区二区三区| 丰满熟女一区二区三区| 不卡在线视频中文字幕| 久久久久久九九九九| 欧美少妇另类| 中文字幕一区二区三区乱码在线| 中文字幕色一区二区| 成人三级网址| 亚洲成人自拍偷拍| 成人在线观看黄| 国精品产品一区| 538prom精品视频线放| 少妇丰满尤物大尺度写真| 国产精品2023| 中文字幕精品一区二区精品| 永久免费看mv网站入口| 亚洲日本黄色| 国产精品日韩欧美综合| www.激情五月.com| 久久综合一区二区| 成年人黄色在线观看| 182在线播放| 欧美性大战久久| 中文字幕人妻无码系列第三区| 欧美1区二区| 色一情一乱一区二区| 2021亚洲天堂| 久久这里有精品15一区二区三区| 91免费看国产| 五月天婷婷视频| 国产精品初高中害羞小美女文| 日韩欧美不卡在线| 国产乱子精品一区二区在线观看| 日韩精品一区二| 亚洲欧洲久久久| 欧美网站在线| 国产精品久久久久久网站| 亚洲va欧美va| 国产精品国产a级| 日韩av三级在线| 精品国产鲁一鲁****| 亚洲视频在线看| 国产一级中文字幕| 免费一级片91| 精品国产第一页| a级毛片免费观看在线| 色94色欧美sute亚洲线路一ni| 韩国三级丰满少妇高潮| 不卡日本视频| 欧美一级黄色网| 欧美一区,二区| 亚洲免费观看在线视频| 欧美精品一区二区三区免费播放| 在线观看视频一区二区三区| 日韩中文第一页| 久草手机在线视频| www.爱久久.com| 韩国无码av片在线观看网站| 国产亚洲欧美日韩精品一区二区三区 | 五月天激情播播| 国产毛片一区二区三区 | 丰满人妻一区二区三区53号| av有声小说一区二区三区| 亚洲第一区中文99精品| 欧美做爰爽爽爽爽爽爽| 久久国产精品一区二区| 日本公妇乱淫免费视频一区三区| 蜜桃av在线| 精品国产人成亚洲区| 国产97免费视频| 精品在线亚洲视频| 中文字幕在线亚洲精品| 亚洲香蕉久久| 另类图片亚洲另类| 国产美女主播在线观看| 国产精品二三区| 成人黄色一级大片| 婷婷综合视频| 亚洲综合国产精品| 色呦呦在线视频| 日韩欧美国产精品| 久久精品国产亚洲av麻豆色欲| 国产成人在线视频网站| 69精品丰满人妻无码视频a片| 国产一区二区三区黄网站| 久久综合久中文字幕青草| 91中文字幕在线视频| 亚洲男人的天堂在线观看| 午夜天堂在线视频| 欧美视频不卡| 精品久久久久久一区| 欧美电影网址| 中文在线不卡视频| 国产精品久久久久久久久久久久久久久久久久 | 456国产精品| 免费在线观看污视频| 在线看国产一区| 欧美肥妇bbwbbw| 国产v日产∨综合v精品视频| 日本大片免费看| 欧美一区二区三区久久| 国产精品高精视频免费| 秋霞午夜理伦电影在线观看| 日韩三级视频在线观看| 男人的天堂一区二区| 久久综合狠狠综合| 亚洲欧美日韩精品一区| 国内久久精品| 欧美激情第一页在线观看| 日本午夜精品久久久久| 欧美高清视频在线| 青春有你2免费观看完整版在线播放高清 | 一区二区国产精品视频| 国产wwwxxx| 欧美日韩一二三四五区| 中文国语毛片高清视频| 国产成人精品免费视频网站| 亚洲中文字幕无码中文字| 第四色成人网| 好吊妞www.84com只有这里才有精品| 日韩av超清在线观看| 欧美成人午夜激情| 日本免费一区二区三区最新| 91精品国产手机| aaa在线视频| 一区二区三区在线观看动漫| 亚洲成人黄色av| 国产69精品久久久久毛片| 中文字幕乱码人妻综合二区三区| 91tv官网精品成人亚洲| 欧美日本国产精品| 在线精品国产亚洲| 国产欧美精品在线播放| 日本不卡网站| 欧美大尺度激情区在线播放| 国产视频福利在线| 精品国产乱码久久久久久牛牛| 综合久久中文字幕| 五月婷婷久久丁香| 日韩在线中文字幕视频| 亚洲国产精品t66y| 国产精品无码专区| 国产精品一级黄| 亚洲免费999| 蜜桃久久av| 成人在线国产视频| 亚洲精品在线观看91| 日本一区二区三区精品视频| 国产成人福利av| 51成人做爰www免费看网站| 88xx成人网| 日韩av片免费在线观看| 嗯~啊~轻一点视频日本在线观看| 久久久精品在线| 色老头视频在线观看| 亚洲最新视频在线| 看电影就来5566av视频在线播放| 亚洲电影在线观看| 黄色av网址在线| 日韩午夜精品电影| 国产美女裸体无遮挡免费视频| 欧美偷拍一区二区| 亚洲图片在线视频| 欧美性黄网官网| 成人毛片在线播放| 色婷婷综合激情| 9i精品福利一区二区三区| 精品色蜜蜜精品视频在线观看| 麻豆亚洲av成人无码久久精品| 中文字幕色av一区二区三区| www.99re6| 中文字幕一区二区三区四区| 日韩三级久久久| 亚洲欧洲99久久| 999精品在线视频| 亚洲三级久久久| 男人的天堂久久久| 亚洲午夜国产一区99re久久| 欧美片一区二区| 亚洲成a人v欧美综合天堂| 一区二区三区免费高清视频| 亚洲国产精品久久一线不卡| 亚洲精品在线观看av| 午夜久久电影网| 天堂网一区二区三区| 日韩欧美在线国产| 中文字幕 亚洲视频| 欧美巨大另类极品videosbest | 殴美一级特黄aaaaaa| 精品国产乱码久久久久久久| 蜜桃视频在线观看www| 亚洲国产福利在线| 你懂的视频在线播放| 在线播放精品一区二区三区| 午夜在线免费观看视频| 久久在线免费视频| 俺来俺也去www色在线观看| 韩剧1988在线观看免费完整版| 瑟瑟视频在线看| 国产精品视频区1| 欧美久久亚洲| 久草一区二区| 欧美韩日一区| 国产欧美日韩小视频| 久久先锋资源| 午夜视频在线网站| 成人动漫一区二区| 欧洲av一区二区三区| 亚洲视频在线一区| 久久精品国产亚洲av麻豆色欲 | 69国产精品成人在线播放| 免费观看一级欧美片| 国产欧美一区二区白浆黑人| 欧美a在线观看| 欧美韩国日本精品一区二区三区| 欧美电影《轻佻寡妇》| 日本大片免费看| 秋霞午夜鲁丝一区二区老狼| 色综合久久久无码中文字幕波多| 久久青草欧美一区二区三区| 日本黄色免费片| 精品欧美一区二区三区| 国产一区二区三区四区视频| 亚洲国产91色在线| 秋霞午夜在线观看| 欧美一级片免费在线| 91精品国产色综合久久不卡粉嫩| 精品一区二区国产| 婷婷六月综合| 能看的毛片网站| 成人午夜大片免费观看| 欧美日韩生活片| 欧美日韩国产丝袜美女| 99精品久久久久久中文字幕| 亚洲欧美国产日韩中文字幕| 肉体视频在线| 91精品久久久久久久久久久久久久| 美女一区2区| 天天爱天天做天天操| 美女视频一区免费观看| 国内精品免费视频| 自拍偷在线精品自拍偷无码专区| 欧美一区二区三区网站| 欧美精品一区二区三区蜜臀| 超碰免费在线播放| 国产精品三级美女白浆呻吟| 网红女主播少妇精品视频| 国产内射老熟女aaaa| 麻豆成人91精品二区三区| 人妻少妇一区二区| 亚洲成在人线在线播放| 精品国产亚洲av麻豆| 日韩中文字幕免费| 巨胸喷奶水www久久久免费动漫| 欧美精品久久| 国产美女一区| 男女一区二区三区| 亚洲一二三四区不卡| 国产福利资源在线| 欧美www在线| 国产成年精品| av磁力番号网| 狠狠色综合日日| 成人自拍小视频| 666欧美在线视频| 欧美成人xxx| 91精品国产综合久久男男| 欧美亚洲国产一区| 亚洲一区二区蜜桃| 中文字幕av不卡| 中文字幕乱码无码人妻系列蜜桃| 伊人av综合网| 日本黄色一区| 一区二区不卡视频| 老司机午夜精品99久久| av黄色免费在线观看| 欧美日韩国产首页在线观看| 日韩在线免费电影| 成人在线播放av| 欧美人成在线| 国产a级黄色片| 天天操天天干天天综合网| 色欲av永久无码精品无码蜜桃| 91国自产精品中文字幕亚洲| 四虎5151久久欧美毛片| 国产精品欧美激情在线观看| 久久久久久久国产精品影院| 日本精品入口免费视频| 中文字幕av一区二区| 国产视频一区二区在线播放| 国产制服91一区二区三区制服| 国产不卡视频一区二区三区| 91porny在线| 这里只有精品在线观看| 国产成人免费视频网站视频社区 | 2021天堂中文幕一二区在线观| 久久精品日产第一区二区三区乱码 | 国产绿帽一区二区三区| 欧美精品久久久久久久久| 任我爽精品视频在线播放| 黄色av免费在线播放| 中文字幕人成不卡一区| 亚洲女同志亚洲女同女播放| 97超级碰碰人国产在线观看| 欧美日中文字幕| 可以看的av网址| 日韩欧美在线观看视频| 黄网站在线免费| 精品国产aⅴ麻豆| 久久国产三级精品| 国产午夜福利一区二区| 国产一区二区三区在线播放免费观看| 日韩电影精品| 9久久9毛片又大又硬又粗| 亚洲国产成人私人影院tom| www久久久久久| 欧美亚洲国产日本| 久久久久久久久99精品大| 丝袜熟女一区二区三区| 欧美少妇bbb| 丰满的护士2在线观看高清| 热舞福利精品大尺度视频| 国产精品综合视频| 无码人妻精品一区二区三区9厂 | 国产精品一级在线| 欧美国产成人精品一区二区三区| xvideos成人免费中文版| 日本一道高清一区二区三区| 蜜臀一区二区三区精品免费视频 | 国产精品毛片大码女人| 好吊视频一区二区三区| 成人高h视频在线| 欧美亚洲三区| 精品少妇爆乳无码av无码专区|