標籤:
一:為什麼要使用訊息佇列呢?
在開發上一個APP後台時候,其中很重要的一塊就是訊息,通訊模組,使用的是開源的Openfire。
架構:
兩台API伺服器
兩台Openfire伺服器
若干資料庫伺服器叢集
其中業務的很大一部分都需要發送訊息,使用者下了訂單,使用者取消訂單,等等都需要伺服器給使用者來發送訊息。使用的解決方式就是在Openfire的基礎上規定了自己的訊息格式。使用者去操作,然後API伺服器通知Openfire伺服器去發送訊息。Openfire伺服器去接受來自API伺服器的請求,然後去給使用者發送訊息。
這個其中就有一個問題,無數的介面都會告訴Openfire伺服器去發送訊息,當請求多到一定程度的時候Openfire伺服器肯定是處理不過來的。
解決辦法:
先使用速度快的東西先把需要發送的訊息首先存下來。然後測試出每秒Openfire伺服器在可以接受的請求次數,然後每秒從存下來的訊息中按順序取出訊息來發送。
在沒有太多經驗的情況下,選了個據說最簡單的redis,測試了下勉強還可以。
這是我第一次使用訊息佇列的經曆。
二:使用訊息佇列
在接手新項目時候,是電商類APP,其中有一個非常重要的功能就是,在不停的降價當中,在到一定的時候,公司內部的托一出手,後面會跟著很多人來出價。其中後台近期可能存在的壓力很可能就出在這裡。這裡也是非常重要的一環。
為了保證這個環節的穩定性,決定採用activeMQ(為什麼採用這個呢,多試驗技術換換哈哈)
下面正式開始ActiveMQ的使用。
三:在測試伺服器上面搭建ActiveMQ
首先下載ActiveMQ
下載網址:http://activemq.apache.org/activemq-5132-release.html
tar xzfv apache-activemq-5.13.2-bin.tar.gz 解壓
cd cd apache-activemq-5.13.2/ 進入目錄
./bin/activemq start 啟動ActiveMQ
/sbin/iptables -I INPUT -p tcp --dport 8161 -j ACCEPT 開啟ActiveMQ預設控制台連接埠
/sbin/iptables -I INPUT -p tcp --dport 61616 -j ACCEPT 開啟ActiveMQ預設串連連接埠
/etc/rc.d/init.d/iptables save 儲存
在測試伺服器上安裝ActiveMQ完畢
四:開啟ActiveMQ控制台
http://ip:8161/admin
然後點擊queues 建立一個queues
然後我們就可以開始代碼代碼之路了!!!!!
五:使用java來測試ActiveMQ
建立一個生產者:
package com.nico.utils.ActiveMq;/** * Created by Administrator on 2016/4/27. */import javax.jms.Connection;import javax.jms.ConnectionFactory;import javax.jms.DeliveryMode;import javax.jms.Destination;import javax.jms.MessageProducer;import javax.jms.Session;import javax.jms.TextMessage;import org.apache.activemq.ActiveMQConnection;import org.apache.activemq.ActiveMQConnectionFactory;public class Sender extends Thread { public static void sendMessage(Session session, MessageProducer producer, int i) throws Exception { TextMessage message = session .createTextMessage("ActiveMq 發送的訊息" + i); // 發送訊息到目的地方 System.out.println("發送訊息:" + "ActiveMq 發送的訊息" + i); producer.send(message); } @Override public void run() { int messageNo = 1; while (true) { // ConnectionFactory :串連工廠,JMS 用它建立串連 ConnectionFactory connectionFactory; // Connection :JMS 用戶端到JMS Provider 的串連 Connection connection = null; // Session: 一個發送或接收訊息的線程 Session session; // Destination :訊息的目的地;訊息發送給誰. Destination destination; // MessageProducer:訊息寄件者 MessageProducer producer; // TextMessage message; // 構造ConnectionFactory執行個體對象,此處採用ActiveMq的實現jar connectionFactory = new ActiveMQConnectionFactory( ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD, "tcp://{ip}:61616"); try { // 構造從工廠得到連線物件 connection = connectionFactory.createConnection(); // 啟動 connection.start(); // 擷取操作串連 session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE); // 擷取session注意參數值xingbo.xu-queue是一個伺服器的queue,須在在ActiveMq的console配置 destination = session.createQueue("FirstQueue"); // 得到訊息產生者【寄件者】 producer = session.createProducer(destination); // 設定不持久化,此處學習,實際根據項目決定 producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); // 構造訊息,此處寫死,項目就是參數,或者方法擷取 sendMessage(session, producer,messageNo); session.commit(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (null != connection) connection.close(); } catch (Throwable ignore) { } } messageNo++; try { sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }}
建立一個消費者:
package com.nico.utils.ActiveMq;import javax.jms.Connection;import javax.jms.ConnectionFactory;import javax.jms.Destination;import javax.jms.MessageConsumer;import javax.jms.Session;import javax.jms.TextMessage;import org.apache.activemq.ActiveMQConnection;import org.apache.activemq.ActiveMQConnectionFactory;public class Receiver extends Thread{ @Override public void run() { // ConnectionFactory :串連工廠,JMS 用它建立串連 ConnectionFactory connectionFactory; // Connection :JMS 用戶端到JMS Provider 的串連 Connection connection = null; // Session: 一個發送或接收訊息的線程 Session session; // Destination :訊息的目的地;訊息發送給誰. Destination destination; // 消費者,訊息接收者 MessageConsumer consumer; connectionFactory = new ActiveMQConnectionFactory( ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD, "tcp://{ip}:61616"); try { // 構造從工廠得到連線物件 connection = connectionFactory.createConnection(); // 啟動 connection.start(); // 擷取操作串連 session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE); // 擷取session注意參數值xingbo.xu-queue是一個伺服器的queue,須在在ActiveMq的console配置 destination = session.createQueue("FirstQueue"); consumer = session.createConsumer(destination); while (true) { //設定接收者接收訊息的時間,為了便於測試,這裡誰定為100s TextMessage message = (TextMessage) consumer.receive(100000); if (null != message) { System.out.println("收到訊息" + message.getText()); } else { break; } sleep(3000); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (null != connection) connection.close(); } catch (Throwable ignore) { } } }}
然後開啟我們的測試:
package com.nico.utils.ActiveMq;/** * Created by Administrator on 2016/4/27. */public class ActiveDemo { public static void main(String[] args){ Receiver receiverThread=new Receiver(); receiverThread.start(); Sender senderThread=new Sender(); senderThread.start(); }}
列印結果:
發送訊息:ActiveMq 發送的訊息1收到訊息ActiveMq 發送的訊息1發送訊息:ActiveMq 發送的訊息2收到訊息ActiveMq 發送的訊息2發送訊息:ActiveMq 發送的訊息3收到訊息ActiveMq 發送的訊息3發送訊息:ActiveMq 發送的訊息4收到訊息ActiveMq 發送的訊息4
然後就可以簡單看到測試結果。
然後將隊列整合到系統中去就可以!
訊息佇列ActiveMQ