首先說一下,MQ全稱爲Message Queue消息隊列是一種應用程序對應用程序的通信方法。應用程序通過讀寫出入隊列的消息(針對應用程序的數據)來通信,而無需專用連接來鏈接它們。消息傳遞指的是程序之間通過在消息中發送數據進行通信,而不是通過直接調用彼此來通信,直接調用通常是用於諸如遠程過程調用的技術。排隊指的是應用程序通過 隊列來通信。隊列的使用除去了接收和發送應用程序同時執行的要求。(來自百度百科)
使用場景:
在項目中,將一些無需即時返回且耗時的操作提取出來,進行異步處理,而這種異步處理的方式大大的節省了服務器的請求響應時間,從而提高了系統的吞吐量。
RabbitMQ
遵循AMQP協議,用erlang語言開發,一個開源的消息代理和隊列服務器,用來通過普通協議在完全不同的應用之間共享數據,或者簡單地將作業排隊以便讓分佈式服務器進行處理。
RabbitMQ的結構圖:
Exchange:消息交換機,它指定消息按什麼規則,路由到哪個隊列。
Queue:消息隊列載體,每個消息都會被投入到一個或多個隊列。
Binding:綁定,它的作用就是把exchange和queue按照路由規則綁定起來。
Routing Key:路由關鍵字,exchange根據這個關鍵字進行消息投遞。
vhost:虛擬主機,一個broker裏可以開設多個vhost,用作不同用戶的權限分離。
producer:消息生產者,就是投遞消息的程序。
consumer:消息消費者,就是接受消息的程序。
channel:消息通道,在客戶端的每個連接裏,可建立多個channel,每個channel代表一個會話任務。
(2)客戶端聲明一個exchange,並設置相關屬性。
(3)客戶端聲明一個queue,並設置相關屬性。
(4)客戶端使用routing key,在exchange和queue之間建立好綁定關係。
(5)客戶端投遞消息到exchange
Maven項目,添加依賴:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.itcast.rabbitmq</groupId>
<artifactId>itcast-rabbitmq</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>
</dependencies>
</project>
public class ConnectionUtil {
public static Connection getConnection() throws Exception {
//定義連接工廠
ConnectionFactory factory = new ConnectionFactory();
//設置服務地址
factory.setHost("192.168.88.128");
//端口
factory.setPort(5672);
//設置賬號信息,用戶名、密碼、vhost
factory.setVirtualHost("/taotao");
factory.setUsername("www");
factory.setPassword("www");
// 通過工程獲取連接
Connection connection = factory.newConnection();
return connection;
}
}
生產者:
public class Send {
private final static String QUEUE_NAME = "test_queue";
public static void main(String[] argv) throws Exception {
// 獲取到連接以及mq通道
Connection connection = ConnectionUtil.getConnection();
//從連接中創建通道
Channel channel = connection.createChannel();
//聲明(創建)隊列
channel.queueDeclare(QUEUE_NAME,false,false,false,null);
//消息內容
String message="Hello World";
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
System.out.println(" [x] Sent '" + message + "'");
channel.close();
connection.close();
}
}
消費者:
public class Recv {
private final static String QUEUE_NAME="test_queue";
public static void main(String[] args) throws Exception {
//獲取連接以及mq通道
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
//聲明隊列
channel.queueDeclare(QUEUE_NAME,false,false,false,null);
//定義隊列的消費者
QueueingConsumer consumer = new QueueingConsumer(channel);
//監聽隊列
channel.basicConsume(QUEUE_NAME,true,consumer);//true自動模式
//獲取消息
while (true)
{
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String message = new String(delivery.getBody());
System.out.println(" [x] Received '" + message + "'");
}
}
}
小結:
之前也寫過一篇socket編程的例子。通過這個例子感覺RabbitMQ與socket編程有相似的地方
(1)相同:
socket有服務端和客戶端,RabbitMQ有生產者和消費者,都可以互通消息。
socket客戶端通過new Socket('主機號','端口號');服務端通過new ServerSocket('端口號');並且通過accept()方法進行監聽,等待連接;它們都是通過輸入輸出流交換數據。
RabbitMQ通過創建通道,創建隊列
(2)不同:
socket是即時連接,像打電話,如果客戶端或者服務端有一個斷開,那麼消息連接就會中斷,信息就會丟失,而RabbitMQ會將消息放入隊列,消費者從隊列中取消息,不存在這個問題。