1 爲什麼要使用RabbitMQ
1.1 RabbitMQ基礎
AMQP
,即Advanced Message Queuing Protocol
,高級消息隊列協議,是應用層協議的一個開放標準,爲面向消息的中間件設計。
消息中間件主要用於組件之間的解耦
,消息的發送者無需知道消息使用者的存在,反之亦然。
AMQP
的主要特徵是面向消息、隊列、路由(包括點對點和發佈/訂閱)、可靠性、安全。
RabbitMQ
是一個開源的AMQP
實現,服務器端用Erlang
語言編寫,支持多種客戶端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP
等,支持AJAX
。用於在分佈式系統中存儲轉發消息,在易用性、擴展性、高可用性等方面表現不俗。
1.2 同步變異步
1.2.1 逐一流程
下圖所示的是,流程是依次發送的,即:下訂單->訂單服務->發短信->發email->發push,所以時間很多
1.2.2 線程池
如下圖所示,在訂單服務中開啓一個線程池,線程不在等待其他線程的結果,可以將同步轉換爲異步,但是不能解耦合
1.2.3 用MQ系統
如下圖所示,使用消息隊列,MQ
系統,也可以把同步變爲異步:當用戶下訂單後,MQ
系統返回訂單id,不在管MQ
系統,其實MQ
系統在和其他系統交互就和訂單服務沒有什麼影響了
1.3 解耦合服務
使用MQ服務還可以解除彼此間的耦合
1.4 流量削鋒
互聯網的秒殺服務,如果巨大請求量發送到秒殺服務, 可能讓服務器癱瘓,這時候用消息隊列,接收處理巨大的請求,因爲它不處理秒殺請求,所以還要給秒殺服務。這時候可以在消息隊列裏面設置一個閥值,如果達到某個請求,就不在發送給秒殺服務,而發送給其他服務了
2 消息隊列基礎知識
2.1 Provider
消息生產者, 就是投遞消息的程序。
2.2 Consumer
消息消費者, 就是接受消息的程序。
2.3 沒有使用消息隊列時消息傳遞方式
2.4 使用消息隊列後消息傳遞方式
2.5 什麼是隊列
隊列就像存放了商品的倉庫或者商店,是生產商品的工廠和購買商品的用戶之間的中轉站
2.6 隊列裏存儲了什麼
在rabbitMQ
中, 信息流從你的應用程序出發, 來到Rabbitmq
的隊列,所有信息可以只存儲在一個隊列中。 隊列可以存儲很多信息, 因爲它基本上是一個無限制的緩衝區, 前提是你的機器有足夠的存儲空間。
2.7 隊列和應用程序的關係
多個生產者可以將消息發送到同一個隊列中, 多個消息者也可以只從同一個隊列接收數據
3 入門案例
3.1 RabbitMQ配置文件
3.1.1 RabbitMQ的座標
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
3.1.2 添加RabbitMQ相關的配置
# 給應用起一個名字
spring.applicatin.name=springcloud-mq
# RabbitMQ的安裝地址
spring.rabbitmq.host=192.168.126.140
# RabbitMQ的訪問端口,和頁面的15672端口不一樣
spring.rabbitmq.port=5672
# RabbitMQ的用戶名
spring.rabbitmq.username=admin
# RabbitMQ的密碼
spring.rabbitmq.password=123456
3.2 代碼部分
3.2.1 創建隊列
@Configuration
public class QueueConfig {
//@Bean 方法的名字是默認的id名字,因此不要使用get+方法名
@Bean
// 注意:Queue要使用:org.springframework.amqp.core.Queue
public Queue createQueue() {
return new Queue("test_mq");
}
}
3.2.2 創建消息提供者
@Component
public class QueueSender {
@Autowired
private AmqpTemplate amqpTemplate;
public void send (String msg) {
//向消息隊列發送消息
//參數一: 隊列的名稱。
//參數二: 消息
this.amqpTemplate.convertAndSend("test_mq",msg);
}
}
3.2.3 消息接收者
@Component
public class QueueReciver {
//此處的註解用來檢測某一個特定隊列是否變化
@RabbitListener(queues="test_mq")
public void reciver(String msg) {
System.out.println("=====================");
System.out.println(msg);
System.out.println("=====================");
}
}
3.2.4 測試類
@RunWith(SpringRunner.class)
@SpringBootTest(classes=AppAction.class)
public class QueueTest {
@Autowired
private QueueSender sender;
/*
* 測試消息隊列
*/
@Test
public void test(){
this.sender.send("Hello RabbitMQ");
}
}
3.3 鏈接拒絕報錯
3.3.1 用戶名密碼錯誤
報錯:
ACCESS_REFUSED - Login was refused using authentication mechanism PLAIN. For details see the broker logfile.
解決:
- 仔細檢查下賬號密碼是否正確
- 登錄後把如下的
Can access virtual hosts
修改爲/
3.3.2 Centos虛擬機的主機名問題
3.3.2.1 Centos7 改主機名兩個地方一致
對於Centos7
要修改主機名保持的話,用hostnamectl
還有在/etc/hosts
這個文件也要改一下
3.3.2.2 Centos6 改主機名兩個地方一致
修改/etc/hosts
下的文件
還有/etc/sysconfig/network
下的文件