99精品久久精品一区二区-亚洲熟妇无码?v在线播放-日本国产精品无码字幕在线观看-久久久亚洲永夜AV-亚洲一级无码一区二区一-免费国产成高清人在线视频-中文字幕乱码免费观看-国产毛片精品妇女久久久

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線實(shí)戰(zhàn)洞察。

JMS與ActiveMQ實(shí)戰(zhàn)筆記:從消息模型到可靠消息機(jī)制

JMS與ActiveMQ實(shí)戰(zhàn)筆記:從消息模型到可靠消息機(jī)制 我第一次正兒八經(jīng)看 JMS 和 ActiveMQ并不是因?yàn)橐嬖嚤嘲斯啥琼?xiàng)目里兩個(gè)服務(wù)之間的同步調(diào)用把數(shù)據(jù)庫連接池打爆了。上游接口一個(gè)超時(shí)下游跟著雪崩運(yùn)維的告警群半夜響成一片。翻來覆去折騰了幾天之后同事丟給我一句話“用消息中間件把調(diào)用拆開吧先看看 JMS 和 ActiveMQ?!碑?dāng)時(shí)我連 JMS 和 MQ 的關(guān)系都說不清楚硬著頭皮把那套消息模型啃了一遍才有了這篇“JMS、ActiveMQ 學(xué)習(xí)一則”。這篇筆記適合兩類人一是剛開始接觸消息中間件、被一堆 JMS API 術(shù)語搞暈的開發(fā)者二是能把 Demo 跑通但不清楚 Queue、Topic、ACK、持久化到底意味著什么的人。我會(huì)把規(guī)范、代碼、踩坑都放在一起講盡量還原當(dāng)時(shí)的學(xué)習(xí)路徑也把網(wǎng)絡(luò)上那些講得含糊的地方補(bǔ)完整。1. 為什么我先啃 JMS 而不是直接學(xué)某個(gè) MQ 客戶端1.1 消息中間件解決的核心問題把“同步等待”變成“異步解耦”先說我當(dāng)時(shí)的場(chǎng)景。有個(gè)訂單創(chuàng)建服務(wù)處理完訂單之后要通知庫存服務(wù)扣庫存、通知積分服務(wù)加積分、通知短信服務(wù)發(fā)通知。最開始寫的代碼很“樸素”——A 服務(wù)直接用 HTTP 調(diào)用 B 服務(wù)同步等返回??雌饋磉壿嫼苤卑椎粔簻y(cè)就出問題任何一個(gè)下游服務(wù)變慢訂單接口的響應(yīng)時(shí)間立刻被拖垮下游服務(wù)一重啟上游的調(diào)用直接報(bào)超時(shí)訂單雖然建成功了但庫存、積分、短信全部沒執(zhí)行數(shù)據(jù)就錯(cuò)亂了。消息中間件解決的就是這種“你完成你的我完成我的然后把變化告訴別人”的通信問題。訂單服務(wù)把“訂單已創(chuàng)建”這個(gè)事實(shí)寫到消息隊(duì)列里訂單服務(wù)的接口直接返回成功庫存、積分、短信服務(wù)各自從隊(duì)列里取消息按自己的節(jié)奏處理。這樣三個(gè)下游服務(wù)誰慢、誰掛都不影響訂單主流程。這個(gè)模型里有幾個(gè)術(shù)語你得先建立直覺Broker是中間件服務(wù)器負(fù)責(zé)消息的存儲(chǔ)和轉(zhuǎn)發(fā)Producer是消息的生產(chǎn)者Consumer是消息的消費(fèi)者。消息不是直接給某個(gè)消費(fèi)者的而是先放到 Broker 的某個(gè)“容器”里消費(fèi)者自己來取。這個(gè)“容器”就是后來的 Queue 或 Topic。1.2 JMS 是規(guī)范ActiveMQ 是實(shí)現(xiàn)先理解這對(duì)關(guān)系JMSJava Message Service是 Java 平臺(tái)制定的一套消息服務(wù)接口規(guī)范它規(guī)定了 Java 程序怎么創(chuàng)建連接、怎么發(fā)消息、怎么收消息但 JMS 自己不干活真正干活的是符合這套規(guī)范的 provider比如 Apache ActiveMQ、開源的 OpenMQ 等。這個(gè)關(guān)系有點(diǎn)像 JDBC 和 MySQL 驅(qū)動(dòng)的關(guān)系——JDBC 規(guī)定了你用什么方法連接數(shù)據(jù)庫MySQL 驅(qū)動(dòng)負(fù)責(zé)把這些方法翻譯成 MySQL 能懂的協(xié)議。這就解釋了為什么學(xué)習(xí)的時(shí)候要先看 JMS 再看 ActiveMQ如果你只對(duì)著 ActiveMQ 的 API 抄一遍換個(gè) MQ 你就廢了如果你把 JMS 的核心模型理解了接觸任何一個(gè)兼容 JMS 的中間件都能很快上手。我當(dāng)初踩過一個(gè)認(rèn)知誤區(qū)以為 ActiveMQ 提供了比 JMS 多得多的高級(jí)功能所以直接按 ActiveMQ 的文檔寫就行。實(shí)際上 ActiveMQ 對(duì) JMS 規(guī)范做了很完整的實(shí)現(xiàn)它的核心 API 就是 JMS API你寫代碼時(shí) import 的主要是javax.jms.*這個(gè)包而不是org.apache.activemq.*。后者只在構(gòu)造連接工廠時(shí)才會(huì)用到。1.3 什么場(chǎng)景才需要引入消息中間件先潑盆冷水消息中間件不是銀彈學(xué)習(xí)過程中我也遇到過濫用它的團(tuán)隊(duì)。一個(gè)內(nèi)部查詢接口沒有任何瞬時(shí)流量壓力硬是套一層消息隊(duì)列結(jié)果多了一個(gè)運(yùn)維節(jié)點(diǎn)、多了一段延遲、多了一堆消息亂序問題。什么時(shí)候才值得引入我的判斷標(biāo)準(zhǔn)有三條一是上下游節(jié)奏不一致下游來不及同步處理需要用隊(duì)列做緩沖二是下游故障不應(yīng)該影響上游主流程需要隔離故障三是同一份業(yè)務(wù)事件需要被多個(gè)系統(tǒng)各自消費(fèi)比如訂單創(chuàng)建之后庫存、積分、日志都要處理。反過來說如果只是簡(jiǎn)單的 A 調(diào) B響應(yīng)時(shí)間敏感且 B 很少故障那直接 HTTP 調(diào)用反而更合適。這部分認(rèn)知雖然當(dāng)時(shí)不成熟但后來回看幫我在選型時(shí)規(guī)避了不少坑。2. JMS 核心模型五個(gè)抽象角色串起全部消息邏輯JMS 1.1 里抽象出的角色其實(shí)就五個(gè)ConnectionFactory、Connection、Session、Destination、MessageProducer/MessageConsumer。剩下的概念比如 Message、AcknowledgeMode 都是在這五者之上附加的。把這五個(gè)角色串成一個(gè)故事你就能看懂 90% 的 JMS 代碼。2.1 ConnectionFactory創(chuàng)建連接的唯一入口ConnectionFactory 是一個(gè)連接工廠接口它封裝了與某個(gè) Broker 建立連接所需的參數(shù)。在 ActiveMQ 中最常見的是ActiveMQConnectionFactory構(gòu)造時(shí)傳入 Broker 的地址典型格式是tcp://127.0.0.1:61616。ActiveMQConnectionFactory factory new ActiveMQConnectionFactory(tcp://127.0.0.1:61616);這個(gè)對(duì)象通常是重量級(jí)對(duì)象創(chuàng)建成本高所以應(yīng)該復(fù)用不要每次發(fā)消息都 new 一個(gè)。我看到不少剛?cè)腴T的同學(xué)把ActiveMQConnectionFactory寫在方法內(nèi)部短時(shí)間大量請(qǐng)求一來連接資源就爆炸了。正確做法是使用連接池或至少是單例持有。2.2 Connection 與 Session消息通信的骨架從工廠拿到Connection之后需要顯式調(diào)用connection.start()這時(shí)候連接才真正建立。然后從 Connection 創(chuàng)建 Session。Session 是一個(gè)非常重要的中間層消息的生產(chǎn)和消費(fèi)都是基于 Session 的Session 的創(chuàng)建方式?jīng)Q定了本次會(huì)話的確認(rèn)模式和事務(wù)邊界。Connection connection factory.createConnection(); connection.start(); Session session connection.createSession(false, Session.AUTO_ACKNOWLEDGE);createSession的第一個(gè)參數(shù)是事務(wù)標(biāo)志第二參數(shù)是確認(rèn)模式。在 JMS 1.1 中如果第一個(gè)參數(shù)傳 true第二個(gè)參數(shù)會(huì)被忽略因?yàn)槭聞?wù)模式下發(fā)送和接收都通過commit和rollback控制。剛開始不用懵理解成“Session 是一段通信上下文凡是這次會(huì)話內(nèi)的消息都可以在這個(gè)上下文里標(biāo)記狀態(tài)”就行。2.3 Destination消息要發(fā)往的地址Destination 是抽象類實(shí)際子類要么是Queue要么是Topic。Queue 對(duì)應(yīng)點(diǎn)對(duì)點(diǎn)模型Topic 對(duì)應(yīng)發(fā)布訂閱模型。在代碼里session.createQueue()或session.createTopic()創(chuàng)建的只是邏輯地址不需要在 Broker 側(cè)預(yù)先建好ActiveMQ 會(huì)在第一次使用時(shí)自動(dòng)創(chuàng)建。Queue queue session.createQueue(DEMO.ORDER); Topic topic session.createTopic(DEMO.NEWS);這里有個(gè)細(xì)節(jié)隊(duì)列名稱建議使用“域名前綴 業(yè)務(wù)名”的格式比如ORDER.CREATED、STOCK.DEDUCTED為了在管理后臺(tái)一眼能看出用途。我見過用queue1、test2這樣的名字上生產(chǎn)的后來排查問題差點(diǎn)被隊(duì)友打死。2.4 MessageProducer 與 MessageConsumer實(shí)際干活的兩個(gè)角色生產(chǎn)者和消費(fèi)者都在 Session 上創(chuàng)建。生產(chǎn)者創(chuàng)建時(shí)可以指定默認(rèn)目的地也可以不指定發(fā)送時(shí)再傳目的地。生產(chǎn)者還支持設(shè)置是否持久化、優(yōu)先級(jí)、存活時(shí)間等特性這部分會(huì)影響消息的存儲(chǔ)行為后面展開。MessageProducer producer session.createProducer(queue); producer.setDeliveryMode(DeliveryMode.PERSISTENT); TextMessage message session.createTextMessage(hello jms); producer.send(message);消費(fèi)者既可以主動(dòng)拉取消息也可以注冊(cè)消息監(jiān)聽器異步接收消息。主動(dòng)拉取用consumer.receive()它會(huì)阻塞等待可以傳入超時(shí)時(shí)間異步監(jiān)聽用MessageListener接口Broker 一有消息就回調(diào)onMessage方法。2.5 Message 結(jié)構(gòu)消息頭、屬性、消息體三層分工JMS 的消息對(duì)象由三部分組成。第一個(gè)是消息頭header存放 JMS 規(guī)范定義的固定字段比如JMSDestination、JMSMessageID、JMSPriority、JMSExpiration。第二個(gè)是消息屬性properties可以看成附加的元數(shù)據(jù)支持字符串、數(shù)字、布爾等類型常用在消息篩選和路由上。第三個(gè)是消息體body存放業(yè)務(wù)數(shù)據(jù)本身。消息體有幾種類型TextMessage適合傳輸文本和 JSON 字符串BytesMessage適合二進(jìn)制數(shù)據(jù)MapMessage適合鍵值對(duì)結(jié)構(gòu)ObjectMessage適合序列化對(duì)象但跨語言不友好StreamMessage用得最少。實(shí)際項(xiàng)目里 80% 的流量都是TextMessage因?yàn)闃I(yè)務(wù)方一般約定用 JSON 傳結(jié)構(gòu)化數(shù)據(jù)不會(huì)強(qiáng)行依賴 Java 對(duì)象序列化。我自己的習(xí)慣是消息體只放必要的業(yè)務(wù)數(shù)據(jù)別把整個(gè)數(shù)據(jù)庫實(shí)體塞進(jìn)去。因?yàn)橄⒖赡鼙欢鄠€(gè)系統(tǒng)消費(fèi)每個(gè)系統(tǒng)關(guān)心字段不一樣塞整個(gè)實(shí)體不僅體積大而且上游實(shí)體變更會(huì)導(dǎo)致下游反序列化失敗。3. ActiveMQ 落地實(shí)操從下載啟動(dòng)到第一個(gè)消息跑通理論講完了得有真家伙。我當(dāng)時(shí)本地環(huán)境是 JDK 8下載的是 Apache ActiveMQ 的穩(wěn)定發(fā)行版。注意 ActiveMQ 有兩個(gè)分支一個(gè)叫 ActiveMQ Classic一個(gè)叫 ActiveMQ Artemis兩者都是 ActiveMQ但 Artemis 是新一代架構(gòu)API 上對(duì) JMS 規(guī)范的支持更現(xiàn)代。作為學(xué)習(xí) JMS 的入口我建議用 Classic因?yàn)橘Y料多、踩坑記錄全先把規(guī)范玩明白。3.1 啟動(dòng) Broker十分鐘確認(rèn)環(huán)境下載解壓后進(jìn)入 bin 目錄Linux/macOS 下執(zhí)行./activemq startWindows 下執(zhí)行activemq.bat start。啟動(dòng)完成后默認(rèn)監(jiān)聽以下幾個(gè)重要端口端口用途61616JMS 客戶端連接的 OpenWire 端口8161Web 管理控制臺(tái)端口5672AMQP 協(xié)議端口默認(rèn)也開啟打開瀏覽器訪問http://127.0.0.1:8161/默認(rèn)登錄賬號(hào)是 admin密碼也是 admin進(jìn)去就能看到隊(duì)列列表、Topic 列表、連接數(shù)、消息統(tǒng)計(jì)等。我強(qiáng)烈建議學(xué)習(xí)階段養(yǎng)成盯控制臺(tái)的習(xí)慣很多代碼“看起來沒反應(yīng)”的問題在控制臺(tái)里一眼就能看出來——消息到底有沒有進(jìn)來、被誰消費(fèi)了、有沒有進(jìn)入死信。3.2 第一個(gè) JMS 生產(chǎn)者發(fā)送一條持久化文本消息下面這端代碼是我當(dāng)時(shí)跑通的第一個(gè)生產(chǎn)者。為了方便閱讀我把異常處理簡(jiǎn)化了學(xué)習(xí)階段先跑通生產(chǎn)上請(qǐng)務(wù)必正確封裝資源關(guān)閉邏輯。import javax.jms.*; import org.apache.activemq.ActiveMQConnectionFactory; public class QueueProducer { public static void main(String[] args) throws Exception { // 1. 連接工廠指向本地 Broker ActiveMQConnectionFactory factory new ActiveMQConnectionFactory(tcp://127.0.0.1:61616); // 2. 創(chuàng)建連接并啟動(dòng) Connection connection factory.createConnection(); connection.start(); // 3. 創(chuàng)建會(huì)話非事務(wù) 自動(dòng)確認(rèn) Session session connection.createSession(false, Session.AUTO_ACKNOWLEDGE); // 4. 創(chuàng)建目的地 Queue queue session.createQueue(DEMO.ORDER); // 5. 創(chuàng)建生產(chǎn)者 MessageProducer producer session.createProducer(queue); producer.setDeliveryMode(DeliveryMode.PERSISTENT); // 6. 發(fā)送一條文本消息 TextMessage textMessage session.createTextMessage(訂單已創(chuàng)建訂單號(hào)20250101); producer.send(textMessage); System.out.println(已發(fā)送消息 textMessage.getText()); // 7. 關(guān)閉資源 producer.close(); session.close(); connection.close(); } }這個(gè)例子里最容易忽略的是connection.start()。有的教程會(huì)在創(chuàng)建生產(chǎn)者之前就調(diào)用 start有的會(huì)在發(fā)送之后才調(diào)用。start()本身不是發(fā)送動(dòng)作的開關(guān)但它會(huì)讓連接進(jìn)入可發(fā)送/接收狀態(tài)。如果你只創(chuàng)建連接不 start消息照樣能發(fā)出去但消費(fèi)者端不 start 的話就一直收不到消息。我當(dāng)初就踩過這個(gè)坑后面專門講。3.3 第一個(gè) JMS 消費(fèi)者同步接收和異步監(jiān)聽兩種方式消費(fèi)者有兩種寫法我建議都試一遍。第一種是主動(dòng) receive適合測(cè)試和批處理任務(wù)。import javax.jms.*; import org.apache.activemq.ActiveMQConnectionFactory; public class QueueConsumer { public static void main(String[] args) throws Exception { ActiveMQConnectionFactory factory new ActiveMQConnectionFactory(tcp://127.0.0.1:61616); Connection connection factory.createConnection(); connection.start(); Session session connection.createSession(false, Session.AUTO_ACKNOWLEDGE); Queue queue session.createQueue(DEMO.ORDER); MessageConsumer consumer session.createConsumer(queue); // 阻塞 3 秒沒消息會(huì)超時(shí)返回 null Message message consumer.receive(3000); if (message instanceof TextMessage) { System.out.println(收到消息 ((TextMessage) message).getText()); } consumer.close(); session.close(); connection.close(); } }第二種是注冊(cè)監(jiān)聽器異步接收實(shí)際項(xiàng)目里這種用得更多因?yàn)樗粫?huì)阻塞業(yè)務(wù)線程。示例代碼我放在下面consumer.setMessageListener(new MessageListener() { Override public void onMessage(Message message) { if (message instanceof TextMessage) { try { System.out.println(異步收到消息 ((TextMessage) message).getText()); } catch (JMSException e) { e.printStackTrace(); } } } }); Thread.sleep(5000);這里有個(gè)容易翻車的地方Thread.sleep(5000)是必要的。因?yàn)閙ain方法執(zhí)行完后 Java 進(jìn)程就退出了消費(fèi)者監(jiān)聽器注冊(cè)完還沒來得及收消息進(jìn)程就沒了。看起來像是“監(jiān)聽器沒生效”其實(shí)只是主線程提前退出。生產(chǎn)環(huán)境一般由應(yīng)用服務(wù)器或 Spring 容器持有消費(fèi)者生命周期不存在這個(gè)問題。3.4 跑完之后去控制臺(tái)觀察四個(gè)維度第一個(gè)消息鏈路跑通后我不急著寫第二個(gè) Demo而是去管理控制臺(tái)把所有變化對(duì)照了一遍。四個(gè)維度最有價(jià)值Number Of Pending Messages隊(duì)列里待消費(fèi)的消息數(shù)量。如果這個(gè)數(shù)字一直漲說明消費(fèi)端有問題。Number Of Consumers當(dāng)前有多少消費(fèi)者掛著。Messages Enqueued / Dequeued入隊(duì)和出隊(duì)的累計(jì)數(shù)能看出積壓到底是多少。Blocked Time連接被阻塞的時(shí)間如果很大說明消費(fèi)者處理不過來。先建立這套觀察手段后面排坑會(huì)省很多時(shí)間??湛谡f“消息丟了”“隊(duì)列卡了”很容易被運(yùn)維懟把控制臺(tái)截圖甩過去才是正確的溝通方式。4. 隊(duì)列模式和發(fā)布訂閱模式看起來代碼差不多語義差遠(yuǎn)了JMS 里最繞、也最影響選型的就是兩種消息模型點(diǎn)對(duì)點(diǎn)模式Queue和發(fā)布訂閱模式Topic。很多初學(xué)者能分別跑通但沒搞明白為什么需要兩種。4.1 Queue一條消息只被一個(gè)消費(fèi)者取走點(diǎn)對(duì)點(diǎn)模型下一條消息只會(huì)被一個(gè)消費(fèi)者成功接收。你可以啟動(dòng)多個(gè)消費(fèi)者實(shí)例同時(shí)消費(fèi)同一個(gè)隊(duì)列ActiveMQ 會(huì)自動(dòng)做負(fù)載均衡把不同消息分發(fā)給不同的消費(fèi)者。這像是一堆快遞包裹放在驛站多個(gè)配送員各自拿走一部分每個(gè)包裹最終只會(huì)被一個(gè)配送員取走。這個(gè)模型適合“任務(wù)分發(fā)”場(chǎng)景比如一批待處理文件10 個(gè) worker 搶占處理比如訂單狀態(tài)變更庫存服務(wù)和積分服務(wù)如果都要處理就不能用同一個(gè) Queue因?yàn)橄⒅唤o一個(gè)人。這里我補(bǔ)充一個(gè)容易誤解的點(diǎn)多個(gè)消費(fèi)者消費(fèi)同一個(gè)隊(duì)列和 JMS 1.1 里的 QueueReceiver 概念有細(xì)微差別。如果兩個(gè)消費(fèi)者的selector條件互斥消息可能會(huì)按條件被分流但默認(rèn)無 selector 時(shí)就是平均分發(fā)不是廣播。4.2 Topic一條消息廣播給所有訂閱者發(fā)布訂閱模型下一條消息會(huì)被所有“當(dāng)前活躍訂閱者”都收到。這像是廣播喇叭誰在聽誰就能聽見。Topic 模式下沒有“競(jìng)爭(zhēng)消費(fèi)”的概念消費(fèi)者訂閱同一個(gè) Topic各自都能收到全量消息。但 Topic 有一個(gè)關(guān)鍵限制默認(rèn)情況下非持久訂閱者只在連接期間且保持訂閱狀態(tài)時(shí)才能收到消息。如果消費(fèi)者先掛了生產(chǎn)者后發(fā)消息這個(gè)消費(fèi)者重啟之后是收不到“離線期間”的消息的。這讓我當(dāng)初很意外因?yàn)樗?Queue 的行為明顯不一樣——隊(duì)列里消費(fèi)者掛多久都不怕消息會(huì)積壓著但 Topic 不會(huì)。要解決離線訂閱丟失的問題JMS 提供了持久訂閱Durable Subscription。持久訂閱狀態(tài)下Broker 會(huì)為這個(gè)訂閱者保存未消費(fèi)的消息等它上線后再推送。4.3 代碼對(duì)比一條線上隊(duì)列一條線上廣播Queue 和 Topic 的代碼結(jié)構(gòu)幾乎一致只有兩行不同——目的地對(duì)象和創(chuàng)建方式。// 消費(fèi)者隊(duì)列模式 Queue queue session.createQueue(DEMO.ORDER); MessageConsumer consumer session.createConsumer(queue);// 消費(fèi)者Topic 模式非持久訂閱 Topic topic session.createTopic(DEMO.NEWS); MessageConsumer consumer session.createConsumer(topic);持久訂閱的消費(fèi)者寫法會(huì)多一點(diǎn)Topic topic session.createTopic(DEMO.NEWS); // 需要為訂閱者設(shè)置唯一名稱 MessageConsumer consumer session.createDurableSubscriber(topic, news-consumer-1);createDurableSubscriber第二個(gè)參數(shù)是訂閱 IDBroker 用這個(gè) ID 區(qū)分不同的持久訂閱者。如果你用相同的訂閱 ID 連接兩次第二次會(huì)替代第一次的訂閱關(guān)系。發(fā)送端完全一樣MessageProducer producer session.createProducer(topic); producer.send(session.createTextMessage(財(cái)經(jīng)早報(bào)));4.4 選型判斷別讓“感覺好用”替你做決定學(xué)習(xí)期間我總結(jié)了一個(gè)很簡(jiǎn)單的判斷規(guī)則同一業(yè)務(wù)事件如果多個(gè)系統(tǒng)需要各自獨(dú)立處理用 Topic如果一個(gè)任務(wù)的多個(gè)實(shí)例競(jìng)爭(zhēng)處理同一批消息用 Queue。舉兩個(gè)對(duì)比場(chǎng)景訂單創(chuàng)建后觸發(fā)庫存扣減、積分增加、短信通知這是“一魚多吃”三個(gè)系統(tǒng)各自消費(fèi)同一事件應(yīng)該用 Topic 或給每個(gè)消費(fèi)者建獨(dú)立 Queue。秒殺活動(dòng)里有 50 萬條搶購請(qǐng)求后面有 10 臺(tái)冪等處理服務(wù)實(shí)例消化這是“任務(wù)競(jìng)爭(zhēng)”應(yīng)該用 Queue。更常見的企業(yè)做法是“混合使用”用 Topic 接收領(lǐng)域事件然后每個(gè)訂閱者內(nèi)部再用 Queue 做異步削峰。初學(xué)階段先別追求花哨能把 Queue 和 Topic 的邊界吃透就超過了大多數(shù)人。5. 可靠消息的底層機(jī)制確認(rèn)、事務(wù)、持久化一次講清消息中間件最常被問的一句話是“消息到底會(huì)不會(huì)丟”答案取決于三層配置消費(fèi)者的確認(rèn)方式、會(huì)話的事務(wù)邊界、Broker 的持久化策略。每一層都直接影響消息的可靠性但要組合起來才有意義。5.1 確認(rèn)模式消費(fèi)者收完之后Broker 才敢刪消息主動(dòng)和異步監(jiān)聽之外Session 的確認(rèn)模式?jīng)Q定了消息何時(shí)被“算作處理成功”。在 JMS 1.1 里有四種常見模式模式行為適用場(chǎng)景AUTO_ACKNOWLEDGE消費(fèi)者收到消息后自動(dòng)確認(rèn)receive 返回或 onMessage 返回時(shí)業(yè)務(wù)處理邏輯簡(jiǎn)單、處理失敗可以接受消息丟失的場(chǎng)景CLIENT_ACKNOWLEDGE需要手動(dòng)調(diào)用 message.acknowledge() 確認(rèn)處理流程較復(fù)雜希望確認(rèn)時(shí)機(jī)由業(yè)務(wù)代碼控制的場(chǎng)景DUPS_OK_ACKNOWLEDGE允許重復(fù)消息延遲確認(rèn)性能好可容忍重復(fù)消費(fèi)的統(tǒng)計(jì)類場(chǎng)景SESSION_TRANSACTED配合事務(wù)會(huì)話使用需要保證消息收發(fā)與業(yè)務(wù)操作原子一致的場(chǎng)景最常見的坑是使用 AUTO_ACKNOWLEDGE但是消費(fèi)者在onMessage里處理到一半拋異常。此時(shí)消息實(shí)際上已經(jīng)被確認(rèn)了Broker 會(huì)把它刪除重啟消費(fèi)者后這條消息不會(huì)再出現(xiàn)處理自然就丟失了。正確的做法是——如果處理失敗需要重試要么用 CLIENT_ACKNOWLEDGE 模式收到消息后先不確認(rèn)處理成功再調(diào)用message.acknowledge()要么開啟事務(wù)處理失敗就session.rollback()。CLIENT_ACKNOWLEDGE 模式有一個(gè)細(xì)節(jié)很容易忽略acknowledge()不只是確認(rèn)當(dāng)前這條消息而是確認(rèn)這個(gè) Session 里“已經(jīng)消費(fèi)但尚未確認(rèn)”的所有消息。如果同時(shí)消費(fèi)了多條且逐條處理調(diào)用一次 acknowledge 會(huì)把這批全確認(rèn)了。要精確控制單條消息必須結(jié)合事務(wù)會(huì)話每個(gè)事務(wù)處理一條就 commit 一次。5.2 事務(wù)會(huì)話讓發(fā)送和接收具備原子性connection.createSession(true, Session.SESSION_TRANSACTED)開啟了事務(wù)模式。事務(wù)模式下生產(chǎn)者的發(fā)送動(dòng)作不會(huì)立即生效而是要等session.commit()才真正把消息提交給 Broker消費(fèi)者的接收動(dòng)作也不會(huì)立即被確認(rèn)而是等 commit 時(shí)才確認(rèn)這一批消息。如果業(yè)務(wù)處理失敗調(diào)用session.rollback()消息會(huì)被回滾之后可以再次消費(fèi)。事務(wù)會(huì)話對(duì)“發(fā)送”和“接收”是獨(dú)立的語義。比如在一個(gè)服務(wù)里先接收消息 A處理后發(fā)送消息 B然后 commit。這意味著 A 的消費(fèi)確認(rèn)和 B 的發(fā)送是同時(shí)生效的。這個(gè)組合非常實(shí)用相當(dāng)于把“業(yè)務(wù)成功了才把消息標(biāo)記為已處理”這一個(gè)要求交給中間件來保證。不過事務(wù)也不能濫用。事務(wù)越大、批量越大Broker 的鎖競(jìng)爭(zhēng)和日志壓力越大。經(jīng)驗(yàn)值是一個(gè)事務(wù)里處理的業(yè)務(wù)消息量控制在幾十條以內(nèi)尤其在高并發(fā)場(chǎng)景下過大的事務(wù)反而會(huì)成為瓶頸。5.3 持久化消息存儲(chǔ)到磁盤進(jìn)程重啟才能恢復(fù)ActiveMQ 默認(rèn)將消息保存在內(nèi)存里同時(shí)提供 KahaDB 作為默認(rèn)持久化方案它會(huì)將消息寫入本地磁盤。對(duì)生產(chǎn)環(huán)境來說強(qiáng)烈建議開啟持久化并且生產(chǎn)者發(fā)送時(shí)設(shè)置DeliveryMode.PERSISTENT??梢赃@樣理解二者的關(guān)系持久化確保 Broker 重啟后消息還在PERSISTENT 發(fā)送模式確保每條消息都走持久化存儲(chǔ)。即使 Broker 配置了 KahaDB如果生產(chǎn)者發(fā)送時(shí)用的是非持久化模式消息還是可能因?yàn)?Broker 崩潰而丟失。ActiveMQ 的主配置文件中persistenceAdapter的部分默認(rèn)就是 KahaDBpersistenceAdapter kahaDB directory${activemq.data}/kahadb/ /persistenceAdapter學(xué)習(xí)階段可以刻意做一次“重啟測(cè)試”發(fā)送一條持久化消息但消費(fèi)者不啟動(dòng)然后重啟 Broker再啟動(dòng)消費(fèi)者觀察消息是否還在。我第一次測(cè)的時(shí)候發(fā)現(xiàn)消息還在其實(shí)很不解——后來意識(shí)到這就是持久化在起作用。5.4 組合起來可靠消息的生產(chǎn)端配置怎么開把三層機(jī)制組合起來一個(gè)穩(wěn)妥、可靠的生產(chǎn)者配置看起來是這樣Session session connection.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer producer session.createProducer(queue); producer.setDeliveryMode(DeliveryMode.PERSISTENT); producer.setTimeToLive(60000); // 消息有效期為 1 分鐘 producer.send(message);消費(fèi)者側(cè)如果對(duì)處理結(jié)果有嚴(yán)格成功要求通常選擇事務(wù)會(huì)話Session session connection.createSession(true, Session.SESSION_TRANSACTED); MessageConsumer consumer session.createConsumer(queue); TextMessage msg (TextMessage) consumer.receive(); // 處理業(yè)務(wù)邏輯比如更新數(shù)據(jù)庫、調(diào)用外部接口 // 都成功后提交 session.commit(); // 失敗則回滾 session.rollback();這里涉及一個(gè)進(jìn)階考量如果消費(fèi)者處理到一半進(jìn)程崩了事務(wù)尚未 commitBroker 會(huì)重新投遞這條消息。重新投遞可能導(dǎo)致重復(fù)消費(fèi)所以消費(fèi)者的業(yè)務(wù)邏輯必須做冪等。消息中間件本身并不能徹底避免重復(fù)投遞它只能保證“至少一次”不能保證“正好一次”。這句話我建議所有初學(xué)者刻在腦子里。6. 學(xué)習(xí)過程中實(shí)際踩過的四個(gè)坑這部分是我最想寫的。Demo 都能跑通但生產(chǎn)要素一進(jìn)來問題就花樣百出。下面四個(gè)坑都是我真實(shí)遇到過的按照排查鏈路寫出來方便你以后對(duì)著復(fù)現(xiàn)。6.1 第一個(gè)坑啟動(dòng) Broker 就報(bào)端口占用現(xiàn)象執(zhí)行./activemq start后控制臺(tái)報(bào)java.net.BindException: Address already in use: JVM_Bind。排查我把堆棧里暴露的端口號(hào) 61616 用lsof -i:61616查了下發(fā)現(xiàn)是本機(jī)之前跑過一個(gè)沒關(guān)干凈的 ActiveMQ 實(shí)例。這提醒我兩個(gè)習(xí)慣一是問題定位要先確認(rèn)端口占用而不是盲目重裝二是啟動(dòng)前用./activemq stop或jps查看已有 Java 進(jìn)程別把多個(gè) broker 實(shí)例混在一起跑。如果你是在同一臺(tái)機(jī)器上跑多個(gè) broker 做集群學(xué)習(xí)必須修改conf/activemq.xml里的 transportConnector 端口還要調(diào)整conf/jetty.xml里的管理端口否則必然沖突。6.2 第二個(gè)坑隊(duì)列里明明有消息消費(fèi)者卻收不到現(xiàn)象生產(chǎn)者發(fā)送成功控制臺(tái)里Number Of Pending Messages是 5但消費(fèi)者啟動(dòng)后一條都沒收到。排查過程我先確認(rèn)消費(fèi)者確實(shí)連接上了 broker——控制臺(tái)的 Connections 頁面能看到消費(fèi)者連接。然后檢查消費(fèi)的隊(duì)列名發(fā)現(xiàn)生產(chǎn)者和消費(fèi)者用的隊(duì)列名不一致。這個(gè)屬于低級(jí)錯(cuò)誤。但還有一個(gè)更隱蔽的原因困擾了我更久消費(fèi)者連接沒調(diào)用connection.start()。我照著網(wǎng)上某篇文章只創(chuàng)建了 connection 和 session沒有顯式調(diào)用 start。這個(gè)操作在“異步監(jiān)聽 等待”的例子中看起來沒問題但實(shí)際消息分發(fā)一直沒有真正開始。補(bǔ)上connection.start()后一切正常。這個(gè)教訓(xùn)讓我從此養(yǎng)成了一個(gè)習(xí)慣JMS 樣板代碼一定逐行核驗(yàn)別漏掉生命周期方法。6.3 第三個(gè)坑發(fā)布訂閱模式下“先啟動(dòng)生產(chǎn)者后啟動(dòng)消費(fèi)者”丟消息現(xiàn)象我用 Topic 建模一個(gè)廣播消息先運(yùn)行生產(chǎn)者發(fā)了兩條消息再啟動(dòng)消費(fèi)者結(jié)果消息一條都沒收到。排查過程這其實(shí)是 Topic 模型的正常行為不是 bug。非持久訂閱者不會(huì)收到訂閱之前的消息。我當(dāng)時(shí)誤以為 Topic 和 Queue 一樣消息會(huì)先積壓在 broker 里消費(fèi)者一來就全推給它。搞清楚這個(gè)機(jī)制后我重新設(shè)計(jì)了一版客戶端先啟動(dòng)消費(fèi)者并保持在線再觸發(fā)生產(chǎn)者發(fā)送消息就正常收到了。如果業(yè)務(wù)上確實(shí)需要“離線訂閱不丟消息”就要在消費(fèi)端使用createDurableSubscriber。注意持久訂閱的訂閱 ID 一旦創(chuàng)建就不能隨意變更否則舊的持久訂閱消息將無法再被消費(fèi)會(huì)一直堆積在 broker 中。6.4 第四個(gè)坑重復(fù)消費(fèi)引發(fā)的臟數(shù)據(jù)問題現(xiàn)象消費(fèi)者消費(fèi)消息后更新了數(shù)據(jù)庫但進(jìn)程在數(shù)據(jù)庫事務(wù)提交后、Session 提交前崩潰了重啟后同一消息被再次消費(fèi)數(shù)據(jù)庫被更新了兩次。排查過程當(dāng)時(shí)我用了事務(wù)會(huì)話以為有事務(wù)就萬事大吉。實(shí)際上事務(wù)會(huì)話保證的是“消息確認(rèn)和業(yè)務(wù)處理的原子性”但“業(yè)務(wù)處理”本身如果不在同一個(gè)數(shù)據(jù)庫事務(wù)里狀態(tài)就無法對(duì)賬。后來我用了一個(gè)冪等方案消息體帶業(yè)務(wù)主鍵消費(fèi)者在處理前先查一下數(shù)據(jù)庫是否已有對(duì)應(yīng)記錄有就直接返回沒有才執(zhí)行業(yè)務(wù)并落庫且主鍵唯一索引兜底。這樣即使消息重復(fù)投遞也不會(huì)產(chǎn)生重復(fù)數(shù)據(jù)。這個(gè)坑給我最大的啟發(fā)是消息中間件只保證傳輸層面的至少一次投遞消費(fèi)端必須自己做好冪等。你以為中間件幫你解決了所有問題它只是幫你把問題限定在了一個(gè)可控范圍內(nèi)剩下的還要靠自己的業(yè)務(wù)設(shè)計(jì)。7. 學(xué)習(xí)收尾時(shí)的一些心得過完前面這六個(gè)章節(jié)后我又重新回頭看了最初促使我開始學(xué)習(xí)的那個(gè)“同步調(diào)用雪崩”場(chǎng)景。用上 ActiveMQ 之后其實(shí)還沒有結(jié)束還配套做了消費(fèi)并發(fā)度控制、數(shù)據(jù)庫連接數(shù)控制、失敗重試隊(duì)列、監(jiān)控告警才敢說這個(gè)鏈路基本可靠了。這個(gè)認(rèn)知我覺得比學(xué)會(huì) API 本身更重要消息中間件解決的是通信模式問題但一個(gè)系統(tǒng)的穩(wěn)定性永遠(yuǎn)要靠整體設(shè)計(jì)不會(huì)因?yàn)橐胍粋€(gè)組件就自動(dòng)變好。如果你正在學(xué) JMS 和 ActiveMQ我給三條很實(shí)在的建議。第一條不要只看著我的代碼抄一定自己把生產(chǎn)者、消費(fèi)者、管理控制臺(tái)三樣對(duì)起來跑通一個(gè)完整的收發(fā)。第二條把 Queue 和 Topic 的區(qū)別多做幾個(gè)實(shí)驗(yàn)包括離線訂閱、多個(gè)消費(fèi)者消費(fèi)同一個(gè)隊(duì)列、持久訂閱恢復(fù)這些體驗(yàn)比背概念管用太多。第三條第一次接觸消息可靠性的時(shí)候強(qiáng)制自己回答“消息什么時(shí)候會(huì)丟、重復(fù)消費(fèi)怎么兜底、中間件重啟后消息還在不在”這三個(gè)問題回答完再繼續(xù)深入事務(wù)和持久化否則知識(shí)很容易停留在 API 層面。最后分享一個(gè)小技巧學(xué)習(xí)期間可以在 ActiveMQ 的配置里臨時(shí)把日志級(jí)別調(diào)成 DEBUG重點(diǎn)看 messages 相關(guān)日志和 session 相關(guān)日志。以前我一直覺得中間件日志太多不看后來排查那兩次詭異問題時(shí)DEBUG 日志里的 broker 內(nèi)部流轉(zhuǎn)信息幫了大忙。日志是排查問題最早出手的武器不要等到控制臺(tái)里消息都詭異了才想起來翻日志。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
五月激情婷婷六月丁香| 5月婷婷激情6月| 色婷婷亚洲婷婷| 综合久久丁香婷婷,五月婷婷六月丁香,开心激情综合网,六月丁香在线观看,婷婷丁 | 五月丁香网av| www.97碰碰com| 97夫妻超碰| 蜜桃人妻无码AV天堂三区| 99热99在线| 4399无码视频| 国产精品a无线| 五月丁香色婷婷综合| 99热丁香| 在线sebiav精品视频| 久操热线| 色五月天丁香婷婷| 国产毛片精品一区二区色欲黄A片| 激情婷婷内射| 婷香五月网在线| 亚洲4区国产欧美| 爱久久小说下载网| 国产美女无遮挡裸体毛片A片| 丁香婷婷影院| 狠狠色狠狠操| 五月婷婷av| www.色窝| 99色天堂| 天天做天天爽| 97婷婷狠狠| 99操逼| 99热精品网| 色噜噜综合网| 做爱夜夜干天天操| 丁六月激情| 任你艹| 久久大香蕉同僚| 99综合99| 91网站黄| 亚洲成人免费在线| 最新热中文字幕| 久久综合干| 成人AV网站在线| 丁香婷婷AV| 国自产拍偷拍精品啪啪一区二区| 无遮挡国产高潮视频免费观看 | 91碰视频| 99热| 日韩一级| 97色操| 九九综合88| 日本精品人妻无码77777| 在线只有精品| 天天日天天久久青青| 五月婷婷六月天| 六月丁香久久| 狠狠操狠狠| 色五月激情五月| 亚洲精品视频在线| 变态 另类 在线| 极品人妻VIDEOSSS人妻| 91高潮喷水久久久久久久久| 日熟女| 久久综合无| 色噜噜狠狠色综合网| 色噜噜狠狠色综合网| 99热精品10| 伊人网啪啪| 五月婷婷激情久久| www.狠狠狠.com| 激情五月天色爱| 天天爱天天做天天爽| 色偷偷狠狠| 狠狠人人婷婷| 久久久久9999| 99热第一页| 超碰在线综合| 天天草婷婷五月| www.色擼擼.com| 思思热99热| 99九九精品视频| www.久久| 99丝袜精品视频网站| 国产午夜精品一区二区| 色五月在线| 亚洲成人噜噜| 丁香五月天综合| 精品一二三区久久AAA片| 苗黎美女四级成人版一级二级毛片| yw.av| 久久青青日本视频| 久久婷婷五月天激情新地址| 综合激情网激情五月。| 变态另类9| 色婷婷狠狠| 大香蕉啪啪啪| 狠狠久久婷五月| 国产欧美婷婷| 色五婷婷在线视频| chaopengdaxiangjiao| 丁香六月成人网| 中美日韩成人在线| 99热这里只有免费精品| 思思热在线| 波多野结衣不卡AV| 天天情天天狠天天透| www.日韩艹| 五月婷婷真爱激情网| 婷婷五月香蕉| 六月婷婷日| 久草五月婷婷| 久久婷婷综合五月趴| 中文字幕视频在线播放| 免费观看高清无码| 婷婷六月婷婷| 欧美丁香婷婷五月| 久久综合色五月| 五月开心婷婷极品激情| 日日狠狠久久偷偷四色综合免费| 免费精品99| 五月停停99| 婷婷丁香熟妇综合网| 麻豆五月丁香婷婷| 久久精品99国产精品日本| 888久久久| 丁香六月婷婷综合激情欧美| 欧美天堂久久| 2013AV天堂| 天天插综合在线| 五月天婷婷色综合| 天堂网亚洲色图| 亚洲综人色综网| 日韩aaa| 欧美性猛交99久久久久99按摩| 1024成人在线观看| 五月天成人小说| 日本美女97在线视频| 色色五月天激情| 丁香五月五月婷婷五月天激情四射| 久久99热这里只有精品| 大香蕉啪啪| 26uuu亚洲欧美日本| 日韩另类| 色小说婷婷五月天天天| 99热这里都是精品| 伊人超碰| chaopengdaxiangjiao| 色五月婷婷色| 久久性爱视频网站| 综合天天综合| 亚洲天堂热| 天天肏天天肏天天肏| 亚洲另类久久| 成人va在线| 久久少妇视频| 亚洲日韩一页精品发布| 国产精品激情AV久久久青桔| 永久天堂日本| 91成人视频| 婷婷久草| 丁香五月综合在线播放| 五月婷婷在线观看黄| 黄色成人网站在线播放| 国产亚洲精品久久久久久牛牛| 无码日本精品XXXXXXXXX| 日本人妻伦在线中文字幕 | 婷婷久久久| www.婷婷| 成人无码中文| www,五月天com| 天天在线久久综合 | 四川操逼站| 婷婷激情人妻| 色五月av伊人| nvrentiantang av| 色一情一乱一乱一区91Av| 99ER热精品视频| 97性高潮久久久| 啪啪婷婷五月天激情| 色婷婷手机在线| 欧美熟女乱又伦| 噼里啪啦完整版中文在线观看| 天天插天天射天天干| 在线观看婷婷5月| 毛v一区二区视频| 精品人妻伦九区久久AAA片| 五月日韩中文字幕| AV网站免费在线| 丁香激惜男女| 亚洲成人在线综合| 人操综合| 蜜桃婷婷五月| 99爱精品| 中文字幕网伦射乱中文| 黄色五月婷婷| 色婷婷社区| 丁香五月激情婷婷| 99热观看| 另类婷婷丁香| 色99综合视频| 亚洲免费观看高清完整版AV线| 五月激情综合网| 亚州在线中文字幕| 丁香婷婷激情| 四色永久成人网站| 婷婷久久丁香| 影音先锋 91工厂| 青青草原爱爱网| 99久在线精品99re8热| www久久五月com| 五月天婷婷青青草| 五月亭亭开心网| 色五月婷婷DVD| 国产三级片91| 七七色综合| 任你草| 性色播| 久99久视频精品| 五月婷婷黄色| 99色网站| 操熟女成人网| 久久在这里有精品| 日本不卡中文字幕| 97婷婷狠狠久久综合9色| 亚洲无码色| www.99成人视频| 色婷婷亚洲| 色欲AVV| 国产成人综合网| 蜜臀嫩草| 如何安全看伊人婷婷| 亚洲传媒在线观看| 性按摩玩人妻HD中文字幕| 激情床戏| 天天操综合网| 五月婷婷之美女图片| 五月丁婷香| 丁香六月婷婷色播| 午夜福利8055| 久久成人亚洲欧美电影| 精品久久久91久久影视网| 精品五月天| 国产欧美日韩一区二区三区| 激情综合自拍五月婷婷色五月| 九九色院| 五月婷婷色啪| 激情五月综合网最新| 加勒比久热| 精品国产乱码久久久久久免费| 九九色精品| 26uuu精品一区二区| 亚洲五月色| 精品九九视频在线观看| 97久久香草精品视频| 丁香婷婷网| 久久99精品久久久久久三级| 色哟哟性爱av| 91视频一起草| 丁香六月婷婷综合| 丁香六月婷| 97人人干。| 一级片操逼视频| 五月天婷婷综合| 来吧亚洲综合网| 五月天啪啪视频| 日本色久| 久久国产色| 色婷婷香蕉| 操操自拍| 国产成人亚洲综合A∨婷婷| 五月丁香色| 色五月超碰| 伊人玖玖网| 五月天激情网图片| 伊人99热| 亚洲成人AV高清字幕| 亚洲愉拍99热成人精品| 99热色综合| 99热97美女| 五月婷九月| 天堂在线婷婷| 91欧美日韩综合| 五月丁香久久网| caopeng超碰| 五月天成人在线视频丁香| 永久的网站AAAA | 亚洲激情久久| A片天天| 五月丁香亭亭A片| 操操操91| 狠狠色丁香久久久婷| Se.婷婷五月天| 天天综合情| 婷婷久久午夜网| 精品无码色| 丁香五月综合福利视频导航| 中文AV网站| 丁香五月区| 人人摸人人搞| 综合久久综合五月天婷婷| 丁香五月九九| 婷婷丁香社区网| 白天AV月月| 久久九九热视频| 狠狠狠狠狠狠色| 丁香色婷婷五月天| 国产欧美大香蕉一区| 99久久人妻精品无码二区| 99视频啪啪| 国产成人综合在线| 日本成人噜噜| 99精品免费视频| 亚州在线中文字幕| 欧美色婷婷| 思思热再线视频| 成人免费在线电影| 影音先锋男人站,影音先锋男人色资源网,影音先锋AV最新资源站,影音先锋AV资源 | 六月天婷婷| 成人AV播放| 五月天成人综合| 五月丁香六月婷婷不卡免费无码 | 在线18av | 亚洲AV第二区国产精品| 色了色综合| 97香蕉碰碰人妻国产欧美| 丰满少妇猛烈A片免费看观看| 密视AV综合在线| 99国产小视频2013| 97干视频在线| 色约约视频一区二区三区四区五区 | 99热这里只有精品50| 丰满少妇乱A片无码| 五月婷婷综合在线视频小说| WWW.天天日| 婷婷婷婷婷婷婷婷婷婷丁香| 成人av免费观看| 99热亚洲精品| 婷婷97| 日本99在线视频| 欧洲婷婷五月天| 5月婷婷综合| 婷婷六月丁香在线| 五月天综合影院| 久久婷婷六月综合综合| 日日日日日| 久久婷婷五月天丁香| 色色色色色色色色色色色色色五月天 | 国产精产国品一二三在观看| 亚洲成人丁香花| 丁香五月手机在线| 婷婷五月丁香基地| 亚洲午夜成人av电影网| 开心激情色婷婷五月天| 久久思思热| 五夜丁香| 大香蕉伊人99| 黄色成人网站在线播放| 婷婷99热| 五月丁香啪啪啪| 色婷六月| 欧美色99| 国产激情在线| 狼人狠狠操| 国产欧美va| 婷婷激情六月中文| 日日综合网| 色噜噜狠狠狠狠色综合久欧美| 五月丁香拍拍激情综合| 老师的粉嫩小又紧水又多A片视频 粉嫩AV久久一区二区三区 | 天天色播| 婷婷五月天av网| 欧美色五月| 99在线视频资源| 亚洲精品99| 色婷婷情片| 五月天开心网| 日本3级片偷拍网站| 日本女人久久| 激情丁香婷婷六月天| 色五月激情五月| 99操99| 中文字幕 码精品视频网站| 99九九精品视频| 操碰99| 色五月天.con| 激情内射人妻1区2区3区| 九九热思思热| 婷婷丁香五月天熟女丝袜| AV性爱网| 精品久久99码| 激情五月婷婷视频| 婷婷五月精品中文字幕| 26uuu国自产精品| CHINESE熟女老女人HD视频| 丁香婷婷丁香五月欧美人| 无码AV久久久久久久久| 五月天天天色| 91久操| 五月丁香六月激情综合| 欧美狠狠地| 九九伦子片| 91超碰在线播放| 影音先锋xfplay资源男人网| 玖玖综合玖玖| 色婷婷狠狠| 久久99这里只有精品视频| 色yeye欧美| 91凹凸在线| 色五月丁香总合网| 色开心五月婷婷丁香HD| 丁香六月在线| 深爱五月网| 香蕉狠狠爱视频| 丰满老熟妇BBBBB搡BBB| 超碰高清在线| 丁香婷婷六月天| 中文字幕+中文在线| 亚洲精品视频在线播放| 色区域网站视频| 色综合久久88色综合天天99| 真实的国产乱XXXX在线91| 2017狠狠干| 五月丁香婷婷AV天堂| 91日本在线免费| 久九色| 爱婷婷五月| 丁香五月香蕉| 亚洲综合欧美色丁香婷婷888月图片| 欧洲亚洲免费视频9| 26uuuavcom| 99热久草| 婷婷久久婷婷| aaa久久久| 五月婷婷综合激情网| 日韩六六久久电影| 97成人丁香婷婷| 91超级碰人人操| 五月婷婷综合网| 国产色色视频| 天天夜夜操| 激情综合五月婷| 久久99jiu9| 国产精产国品一二三在观看| 久久99婷婷| 久久免费婷婷视频| 99综合免费视频| 思思99热热热99| 啪啪六月婷婷| 91大神在线免费看视频全集男男一起操| www.色五月| 97久久草草超级碰碰碰| 五月天丁香成人| 五月天婷婷丁香社区| 热热久久精品视频| 久热这里只有国产| www,8050,午夜三级| 六月久久婷婷| 99色视频在线观看最新| 99热丁香| 欧美久久网| 色婷婷久久9.com| 嫩草AV久久伊人妇女超级A| 亚洲精品视频在线播放| 激情婷婷丁香五月天| 免费五月婷婷网| 99精品在线下载| 日 日干 日日做| 99热这里在线精品| 婷婷久久夜| 人妻性爱av网站| 色9999日韩国产| WWW色色色COm| 四色永久成人网站| 婷婷五月天成人导航| 一区二区成人电影| 丁香五月天导航| 99色在线视频| 国产精品在线视频| 777久久综合视频| wWw色五月| av 一区三区四区| 夜夜骑操AV| 激情综合网,婷婷| 天天舔天天摸天天射| 人妻乱码久久久| 色青青五月| 婷婷五月天伦理| 色五月aV| 婷婷六月色开| 色色激情网| 一级性爱视频| 婷婷视频在线| 国产一区18| www.婷婷五月天| 色色操| 色五月久久成人婷婷| 色综合久久88色综合天天人守婷| 婷婷五月天BBw| 青草青青草| 综合色影院| 91狠狠色丁香婷婷综合久久精品| 桃色五月天| 99只有精品9| 热996精品在线观看| 久久五月激情综合| 久久这里面只有精品视频| 丁香五月综合福利视频导航| 亚洲综合热| 成人午夜无码视频| 婷婷婷婷婷婷婷婷婷婷丁香| 丁香五月婷婷激情四射| 5月丁香综合网| 人人人va亚洲视频在线| 色色色综合网| yw.av| 久久香蕉网| www.热99热| 五月天堂色| 成熟妇人A片免费看网站| 97操碰日本女人| 色婷婷香蕉| 毛片新网地| 99色五月| 欧美性爱丁香五月| 色九月婷婷| 久久视频这里99| 99热最新| 国内一级精品| 亚洲婷婷乱乱丁香| 99色精品| 超碰无码318604| 韩国情人在线电视剧免费观看高清版全集 | 久久一伦| 丁香色播五月天| 伊人玖玖婷婷| 99久热视频在线| 久久香蕉影院| 婷婷综合五月| 五月婷婷精品视频| 五月丁香六月婷婷综合网| 激情五月天在线免费美女视频| 色婷五月天| 成人啪啪色婷婷久| 人人看人人草人人摸| 婷婷色婷婷| 日韩啪图| site:ornaments52.com| 婷婷五月天丁香社区| 玖玖99婷婷| 天天草人人摸| 97天堂| 色五月婷婷1| 天天天天做夜夜夜夜做| 亚洲亚洲人成综合网络| 五月丁香六月婷婷啪啪综合 | 狠狠五月天激情| 99热综合| 99精品视频在线免费观看| 国产免费一区二区三区三州老师F1F1.CC | 玖玖爱伊人网| 26uuu国产精品| 在线观看中文字幕| 激情综合无码| 情色五月天网站| 伊人在线另类| 国产乱妇乱子伦| 性做爰1一7伦| 99热国产在| 天天肏夜夜肏| 婷婷丁香在线| 天天插天天插天天插天天插| 丁香五月婷婷色| 五月丁香久| 婷婷操超碰| 九九热免费视频| 色婷婷精品视频在线播放| 丁香综合伊人AV| 青草视频在线播放| 我爱va亚洲va52| 婷婷五月花| 丁香五月天无码| 熟妇人妻中文字幕无码老熟妇| 人妻乱码久久久| 国产人妻777人伦精品HD| 97干欧美| 成人丁香五月| 婷婷五月丁香高清无码| 国产XXXX搡XXXXX搡麻豆| AV 3P| 少妇性按摩无码中文A片 | 婷婷五月天AV激情| 91人人人人人人人| 在线视频99| 亚洲在线操| 亚洲激情综合| 六月五月久久丁香| 中文字幕91,综合| 色婷婷综合影院| 久久精品4| 九九久久99| 五月色丁香国产在线视频| 狠狠CAO日日穞夜夜穞AV | 俺去也五月| 亚洲AV网站在线观看| 五月丁香啪啪综合| 91啪级电影| 久久婷婷五月综合色天| 五月综合激情视频在线| 99视频这里只有免费精品| 日产精品久久久久久久蜜臀| www.色五月.com| www.jiujiujiu| 思思热在线视频精品| 影音先锋 91工厂| 久久久九九九 99| 热久久91| 青青操绿aaa一区日v| 色色97丁香婷婷五月天| 91九色在线| er99免费视频在线| www.maotanji.com| 人妻丰满精品一区二区A片| 性色视频| 五月天国产成人| 中文字幕精品无码一区二区| 久热这里只有精品6| 中文无码婷婷| 人人摸人人干| 日本天天操| 天天日本夜夜谢| 五月丁香婷婷无码中文| 久久五月婷婷视频| AA片在线观看视频在线播放| 9热视频在线观看| 九九九成人在线视频| 久久久99日本大片| www久久久久久久久久久| 婷婷久久精品| 五月天另类图片| 天天色综和网| 精品牛仔裤超碰| 婷婷五月天综合亚洲| 伊人激情啪啪| 五月激情综| 国产成人AV人人爽人人澡Va| 99九九99九九九视频精彩| www,黄色在线,con| 久久性爱视频| 婷婷五月六月| 天堂久久婷婷| 五月天婷婷在线AN| α久久| 天天插天天狠| 久操无码| 91肏| 亚洲精级| 任你躁XXXXX麻豆精品| 久久激情五月| 99在线视频精品| 亚亚州久久高潮| 五月花成人网| 九九精品片一| 久久er免费视频| 五月天综合激情网| 丁香久月| 冬月かえでAV无码播放| 久久99三级在线视频| 色五月,com| 99re热视频这里只精品| 亚洲综合激情五月久久| 婷婷六月天| 在线中文av| 97婷婷丁香| 欧美日韩成人一区二区| 丁香五月婷婷激情尤物| 殴美综合激情五月天免费视频| 激情色视频| 青青草日本亚洲| 激情丁香淫荡婷婷| 丁香5月综合啪啪| 青青.com| 亚洲激情五月婷婷日日| 99精品视频在线免费观看| 色色五月天婷婷| 爱射综合| 五月天色狠狠| 久久狠色噜噜狠狠狠狠97| 9色在线| 九九久久99| 性爱先锋AV| 亚洲性受XXXX五月丁香| 美女va| 4399在线观看免费高清电视剧| 婷婷中文字幕| 99热 免费| 人人人人人人人人人草| 五月丁香婷婷三级| 日韩aaaaa| 婷婷色在线播放| 熟女网站久久| 26uuu国产| 精品一二三区久久AAA片| 日本不卡中文字幕| 欧美成人精品A片免费一区99| 国产一区二区三区影院| 日日夜夜九九| 午夜婷婷久久| 天天骑日日爽| 丁香社区婷婷五月| 伊人五月丁香| 亚洲成人高清在线| 99热色精品| 色欲AVV| av在线免费网站 | 深爱婷婷网| 欧洲不卡视频| 国产亚洲精品久久久久久郑州| 色五月天婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷婷 | 高清a片基地| 五月五月婷婷| 美女天天久久| 免费视频这里只有精品| 五月天天综合| 嫩草AV久久伊人妇女超级A| www,黄色在线,con| 26uuu丁香婷婷五月| 激情q青青草在线婷婷| 日日撸日日操| 色色五月婷| www.91av.com| 五月天激情影院| 第二色AⅤ| 六月综合婷婷开心伊人| 色色色热| 99久久.www| 婷婷五月综合欧美在线播放| 天天色天天日| 欧美日本日韩| 碰碰91| 婷婷五月精品中文字幕| 五月婷婷,六月丁香| 九月色婷婷婷| 影音先锋女人av鲁色资源网小说免费| 激情五月狠狠| 综合久久影院| 97在线天堂| 丁香五月婷婷无码AV| 国产精品VA在线| 蜜桃人妻无码AV天堂三区| 丁香五月综合无码趴趴| 东北婷婷五月天| 日韩久久视频| 99亚色色色| 伊人六月无码视频| 97热这里精品在线视频| 99色爱| 色婷婷综合综合网| 热这里| 婷婷五月天激情文学| 国产精品成人网址| 这里只有精彩小视频视频网站| 亚洲狠狠狠| 久色五月| 婷婷五月天开心网| 婷婷射图| 五月丁香啪| 七七久久综合| 艹| 色色色综合| 俺也去在线久久精品23欧美综合视频网站,丰满人妻一区二区三区在线视频53,丰满 | 亚洲宗合激情| 婷婷的五月天另类视频| 狠狠干五月天| 激情综合色网| 中文无码婷婷| 五月天婷婷社区久久综合| 婷婷激情五月天视频在线| 亚洲激情网| 97人人超| 99色综合网| 色碰碰| 丁香色综合| 成人版视频在线观看| 婷婷五月丁香色综合| 五月伊人婷婷| 99在线视频免费| 九九热精品| 国产精品视频网| 黄色激情五月天| ww超碰在线| 青青草原精品久久| 国产综合A片| 狠狠va| 五月天丁香婷婷久久九| 可以免费看的av网站| 91大神操美女| 91啪啪| 天天做天天爱天天摸| 开心五月丁香婷婷| 五月好婷婷| 成人精品在线观看| 五月婷婷丁香综合| 啪啪操网| 日本成人噜噜| av免费在线看不卡无毒| 九九九九九无码| 丁香婷婷深情五月亚洲| 97香蕉久久超级碰碰高清版| 久99热| 色婷精品91| 色狠狠综合| 99热99日…..| 五月天激情综合10p| 狠狠搞亚洲| 九月综合| 天天舔天天爽| 超碰在线日夜| 激情婷婷网| 99色中文| 九九国产精视频| 天天干狠狠操| 色五月在线视频观看| 五月丁香色婷婷| 国产一级片| 最近中文字幕大全免费版在线| 99热在线观看| 91热在线观看视频| 91视频精品99| 婷婷区日本| 天天高潮夜夜爽| 9热视频在线观看| 天天射影院| 狠狠狠狠狠狠草| 99综合自拍| 色五月婷婷五月丁香五月激情五月视频 | 婷婷五月天啪啪| 99这里只有精品| 99色色网| 亚洲AV日韩AV永久无码网站| 狠狠人妻色综合| 五月丁香色五月| 五月婷婷婷丁香播| 久久小视频| 精品国产a| 99自拍视频在线| 99re在线观看| 色99欧洲色19| 四色永久成人网站| 久久婷婷青青草| 久久刺激网| 五月天色婷婷小说| 国产va视频| 99超级碰免费视频| 自拍视频在线观看9| 激情网第九色| 九九久久网| 国产日韩欧美性爱| 性爱激情小说AV五月丁香花| 免费视频舔| 天天操人人干| 全部老头和老太XXXXX| 99热久97| 激情丁香五月激情婷婷| 99热最新网址| AV在线二十六页| 激情综合五月激情| 九月色婷婷综合| 影音先锋91网站在线观看| 婷婷中文字幕欧美| 亚洲国产精品五月天| 99色视频在线| 中文字幕 中文字幕明步| 99riAv1国产在线观看| 97五月天婷婷| 亚洲无线视频| 秋霞av不能| 在线五月色播| 99久久99九九99九九九| 91九色成人原创视频| 色婷婷在线视频久| 丁香五月天啪啪| www.AV在线| 色高清无码视频| 开心婷婷五月| 久久综合丁香| 九九免费精品| 嫩草AV久久伊人妇女超级A| 天天搡日日搡aaaaⅩ| 五月花综合视频| 99在线精品免费视频| 丁香五月自拍| 91大神操美女| 日韩无码系列| 激情五月婷婷丁香综合网| 精品一二三区久久AAA片| 99激情网| 丁香伊人网| 九九人人看| 九九激情视频| 99日热在线视频| 狠色狠色狠色狠色狠色网| 久久婷狠狠色| 999久久久国产精品| 26uuu另类亚洲欧美日本一| 亚洲中文字幕在线观看| 色色综合成人网| 一区二区三区视频| 伊人干综合| 97婷婷狠狠| 99亚洲精美视频在线观看| 六月丁香VA| 色情激情五月婷婷| 色丁香影院| 亚州第一黄网| 婷婷激情五月天小说校园| 精品二区| 开心五月婷婷在线| www.99精品日操伊人乱碰在线| 婷婷五月天无码熟女| 色婷婷狠狠| 丁香五月天激情婷婷丁香六月 | 另类小说五月天| 欧美性猛交99久久久99| 五月天天久久香| 伊人婷婷五月天av| 天天爱综合网| 青青999| 天天爱天天秀天天做| 9色免费网| 99热精品在这里| 97久久久免费福利网址| 天天爽天天操| 日韩色色一区| 99热丁香| 影音先锋色婷婷| 五月丁香成人网| 九九热亚洲中文在线观看免费| 另类在线| 精品99爱免费视频在线观看| 欧州婷婷五月天综合| 日日夜夜综合| 久久久久久久久久婷婷| 色五月天丁香| 少妇丁香婷婷| 色欧美一级| 婷婷五月天激情五月天| 极品少妇婷婷五月| 天堂A∨在线| 丁香六月色婷婷欧美| 欧美成人精品A片免费一区99 | 丁香五月激情啪啪| 91丨九色丨白浆秘| 婷婷丁香五月综合| 激情婷婷另类| 激情五月天婷婷色色色色色色色色色色色| 五月天色区| 思思99热热热99| 久久精品A片777777| 激情五月综合网最新| 五月丁香毛片| 九色七七| 丁香五月视频在线观看| 国产在线网址1| 伊人色综合网| 日本精品在线噜噜噜| 丁香五月婷婷国产av| 高清无码入口| 色五月婷色彩免播放器| seav天堂| 99色在线观看视频| 综合狠狠干| 午夜色丁香| 丁香婷婷久久| 婷婷五月中文字幕国产| 人妻AV在线观看| 欧美丰满熟妇BBB久久久| 在线1青婷| 丁香婷婷网| 91av传媒高清在线视频网| 99.N在线视频| 色婷婷婷婷成人网| www.综合久久| 91久久久久久久久18| 五月丁香伊人网| 99热精品99| 日本熟妇乱妇熟色A片蜜桃| 丁香五月天中文字幕| 色五月婷色彩免播放器| 丁香婷婷五月人体| 99自拍视频| 四月婷婷丁香五月| 亚洲婷婷丁香五月在线| 五月丁香 狠狠爱| 99热最新| 五月成人天| 五月色婷婷在线观看| 婷婷久久色| AA片在线观看视频在线播放| 色综合久久88色综合天天看| 色五月天天| 人妻久热| 婷婷激情五月天激情小说| 久久久久久久人妻| av狠狠操| 夜夜夜夜做天天天做无码视频| www.久久婷婷| 亚洲精品V天堂中文字幕| 激情99| 婷婷六月花| 青青草性爱视频| 久久99久久99精品免观看粉嫩| 五月丁香六月片| 丁香九月婷婷| 天天爽天天干| 亚洲欧美另类在线23p| 成人va在线观看视频| 99热99| 老司机视频lsj爱就色| 五月天色丁香| 久色大| 久久免费视频62| 99er6| 色婷婷五月天偷拍| 婷婷五月成人社区| 成人无码精品1区2区3区免费看| 99九九综合久久九九| 天天操夜夜爽歪歪| 五月天婷婷导航| 欧美天天爽| 97碰| 婷婷五月天丁香激情| 丁香五月伊人| 99国产精品久久久久久久久久久| 日欧大屏操| 丁香五月天BBw| 色婷婷五月天激情综合| 噜噜色五月| 日本人妻A片成人免费看片| 99综合熟女| 天堂综合久| 亚洲精品444久久久久久| 婷婷丁香18| 色欲一区二区三区精品A片| 99爱视频在线观看| 激情性爱五月天| 日本天堂免费99| 开心激情综合| 五月婷丁香| 五月婷婷六月丁香在线视频| 色色色.com| 中文不卡一二三区| 六月激情婷婷综合| tingtingjiqingwuyue| 激情婷婷五月女| 综合丁香婷婷五月天| 九九色色网| 超级黄色片| 欧美色九| 91艹人| 91九色 婷婷| 亚洲精品九九| 丁香五月婷婷色偷偷| 97操碰日本女人| 免费观看高清无码| 丁香六月成人| 激情五月四色| 色啪久 | 精品一区二区三区四区五区六区| www.色婷婷| 国产毛片精品一区二区色欲黄A片| 九九香蕉网| 激情丁香五月| 国产午夜成人AV在线播放| 日本人妻伦在线中文字幕| 极品人妻VIDEOSSS人妻| 九九视频在线观看视频6| 亚洲mm免费| 婷婷久久婷婷色五月| 成人 九九九九| 色99最新网址| 综合激情在线观看| Av在线不卡一区| 婷婷国产欧美97| 99超碰在线免费| 97色97干| www,8050,午夜三级| 精品久久人妻热| 在热视频精品| 色五婷婷在线视频| 女婷久久| 色久女| 99热在线观看| 六月成人网| 亚洲影院婷婷色| 99精品97| 九九视频免费| 狠狠干激情五月| 99热99热在线| 色综合久久44| av中文在线| 婷婷天堂伊人| 停停综合色色| 久99热| 五月色欧洲| 欧美噜一噜| 九九99热| 五月天社区| 欧美日韩成人h| 97热在线精品| 99re这里只有精品9| www开心激情网| 久re热视频| AAA久久久| 欧美成人AAA片一区国产精品| www.天天干| 色婷大香蕉| 色五月婷婷婷婷婷婷婷婷婷婷| 夜夜爽日日躁| 婷婷丁香五月天激情| 五月丁香六月激情欧美综合| 国产又爽又猛又粗的视频A片| 超碰免费电影| 丁香六月婷婷综合色| 色色丁香激情五月| www.五月婷婷| 高清资源站日A美A欧亚…| 射琪琪| 婷婷综合网在线| 激情小说之五月| 91九色在线视频| 俺去也五月| 99久久97| 婷婷亚洲五| 色婷婷五月在线| 综合激情婷婷| 一婬一伦一区二区三区| 色视频2025| 婷婷五月综合激情免费| 亭亭五月丁香五月天激情| 色狠狠色噜噜AV天堂五区| 婷婷激情人妻| 思思热热久久| 99热最新| 91jiuseshunv| 久er7久热| 丁香六月亚洲综合 | 日本视频久久| 久久这里都是精品| 99九九视频| 亚洲成人AV电影网| 亚洲日本激情| 久久久五月五丁香| 国产婷婷婷| 高清国产一级婬片a免费| 五月婷婷熟女| WWW久久久| 丁香五月激情五月色综合| 丁香五月天AV在线| 这里只有精品1| 日本二级毛片二级毛片| 五月婷婷日本| 色色色色色色97| 丁香五月婷婷五月| 五月婷婷色综图片| 97丁香五月| 久久se 综合网| 99热只有精品在线播放| 丁香成人视频| 五月丁香啪啪啪| 女同激情久久av久久| 欧美日本va| 九久久九精品视频| 操笔无码| 激情五月婷婷五月| 99精品丰满| 深爱五月天天| www.色婷婷| 婷婷丁香九月| 小视频久久久aaa| 字幕网AV中文字幕| 狠狠色情婷婷| AA丁香综合激情| 国产精品成人AV在线| 丁香五月婷婷视频| 碰碰碰碰碰99| 五月天欧美激情| 岛国在线观看91| 亚洲成色综合网站免费观看| 97人人干| ww久久| 香焦网五月天| 久xxxx| 成人免费在线电影| 婷婷激情五月天小说| 国产色五月婷婷| 色视频色综合91| 狠狠人妻久久久久久综合丁香| 99精品在线| 狠狠搞五月天| 噜噜噜狠狠色综合| 亚洲在线操| 92久久| 人人操AV| 九九色综合| 色综合色五月| 久久久久9| 女人露出p毛视频www网站| 91操操| 99久久喉9| 狠狠五月天婷婷激情网。| 婷婷D区| 精品无码av丁香五月激情| 五月激情六月宗合| 色婷婷婷av | 日韩AV中文在线观看| 伊人深爱综合| 国产精品成人网址| 日日操,天天操| 果冻传媒A片一二三区| 五月丁香激情婷婷综合| 九月性爱网| 一级黄色尤物综合视频手机在线观看| 天堂网亚洲色图| 五月天久久综合婷婷| 秋霞AV美国| 九九九九九九九九九九九九九国产精品| 五月婷在线视频免费播放| 影音 五月 婷婷 久久| 亚洲色A| 99人人操| 亚洲综合草草| 日本精品干| 色婷婷电影网| oVV4WIB3vFi8D| 久久香视频| 综合色影院| 99热91| 超碰狠狠干99| 五月婷婷六月丁香色| 狠狠干在线| 99热这里全是精品| 亚洲视频在线观看99| 99天堂在线观看免费视频| 99精品视频免费| 人人妻人人澡人人爽| 婷婷综合久久| 午夜 外网 精品 在线| ou洲色吧| 色欲婷婷五月天| 久久婷婷五月天懂色| 五月日韩中文字幕| 久久免片| 久久久8| 99热久久这里只有精品| 内射丰满人妻| 伦99热| 欧美日本黄色| 99操逼视频| 国产AV一区二区三区最新精品| 激情婷婷五月基地| 91大神操美女| 精品人妻伦九区久久AAA片| 久久久久99精品成人片| 激情宗合 激情宗合| 天天日日夜夜| 丁香五月六月激情| 丁香久久激情俄|