目錄
基本概念?
MQ 的優(yōu)勢(shì)
?1.應(yīng)用解耦
?2.異步提速
?3.削峰填谷
?MQ 的劣勢(shì)
使用mq的條件
?常見(jiàn)MQ產(chǎn)品
?RabbitMQ簡(jiǎn)介
RabbitMQ的六種工作模式?
?JMS
RabbitMQ安裝和配置。
RabbitMQ控制臺(tái)使用。
RabbitMQ快速入門——生產(chǎn)者
需求:
RabbitMQ快速入門——消費(fèi)者
小結(jié)?
基本概念?
多個(gè)系統(tǒng)之間的通信方式有兩種,一是直接遠(yuǎn)程調(diào)用,二是通過(guò)第三方,mq就是這個(gè)第三方
MQ 的優(yōu)勢(shì)
?1.應(yīng)用解耦
一個(gè)好的系統(tǒng)肯定會(huì)要求高內(nèi)聚低耦合。
像下面這個(gè),訂單系統(tǒng)發(fā)個(gè)訂單到庫(kù)存時(shí),如果庫(kù)存系統(tǒng)損壞了可能會(huì)連帶影響訂單系統(tǒng)。
有了mq之后,消息存放在mq里面,哪怕庫(kù)存壞了幾分鐘,好了之后也可以從mq中接著拿消息出來(lái)。?
還有一個(gè)時(shí),如果要添加一個(gè)新的x系統(tǒng),一般要修改訂單系統(tǒng)的代碼來(lái)兼容。
有了mq之后,訂單系統(tǒng)會(huì)把所有消息都放到mq里面,新的系統(tǒng)的不管是什么都從mq里面拿東西就好了,就不需要改代碼了
?
?2.異步提速
同步下需要走完整個(gè)流程才能有反饋,所以很慢。
異步下,即使沒(méi)有運(yùn)行完整個(gè)流程,也會(huì)立刻返回消息,后面的系統(tǒng)會(huì)繼續(xù)從mq中取出消息執(zhí)行。這種屬于是騙人?
?3.削峰填谷
瞬時(shí)請(qǐng)求太多致使服務(wù)器宕機(jī)了。
?
?mq在這里只是緩存消息和發(fā)布消息,不負(fù)責(zé)業(yè)務(wù)邏輯處理,因此完全可以承載更多的請(qǐng)求。
如果一層mq解決不了,那就再加一層。
?使用mq技術(shù)在項(xiàng)目里面之后這些優(yōu)勢(shì)可以作為項(xiàng)目亮點(diǎn)寫在簡(jiǎn)歷上。
?MQ 的劣勢(shì)
?
使用mq的條件
?常見(jiàn)MQ產(chǎn)品
?RabbitMQ簡(jiǎn)介
RabbitMQ支持AMQP協(xié)議,
在AMQP中,交換機(jī)分發(fā)消息,queue存儲(chǔ)消息。分發(fā)通過(guò)Routes進(jìn)行?。
RabbitMq里面RabbitMQ Server作為服務(wù)端,生產(chǎn)者和消費(fèi)者都是作為客戶端,通過(guò)tcp連接和服務(wù)端進(jìn)行通信。如果每一次通信都建立tcp連接資源消耗極大,故這里Connection作為一個(gè)連接池,里面有許多管道,通過(guò)channel進(jìn)行通信,這樣可以節(jié)約資源。
?RabbitMq中有很多虛擬機(jī),每個(gè)虛擬機(jī)里面有很多Exchange和Queue,交換機(jī)可以綁定到不同的隊(duì)列上,Binding就是交換價(jià)綁定到隊(duì)列上的過(guò)程。
?
RabbitMQ的六種工作模式?
生產(chǎn)消息和消費(fèi)消息的工作方式
?JMS
類比jdbc是java程序和數(shù)據(jù)庫(kù)通信的接口,JMS就是java程序和消息隊(duì)列通信的接口。
RabbitMQ安裝和配置。
在云服務(wù)器上直接安裝docker版本的就可以了。
Downloading and Installing RabbitMQ — RabbitMQ
docker run -it --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3.12-management
運(yùn)行如下所示
或者這樣安裝,這個(gè)就是后臺(tái)運(yùn)行,不會(huì)停機(jī)自動(dòng)刪除容器
docker run \
-e RABBITMQ_DEFAULT_USER=itcast \
-e RABBITMQ_DEFAULT_PASS=123321 \
--name mq \
--hostname mq1 \
-p 15672:15672 \
-p 5672:5672 \
-d \
rabbitmq:3.12-management
?
安裝好后通過(guò)IP+端口訪問(wèn)管理界面。
管理界面端口是15672,tcp連接的端口是5672。
賬號(hào)密碼都是guest?
RabbitMQ控制臺(tái)使用。
在控制臺(tái)可以看見(jiàn)有一個(gè)Overview概覽,Connection連接,channels通道,Exchanges交換機(jī),Queues,和Admin,Admin中可以管理用戶和虛擬機(jī)等?
?這里新建了一個(gè)超級(jí)用戶yhy和一個(gè)虛擬機(jī)itcast授權(quán)給yhy。
有了管理員權(quán)限就可以用新用戶的賬號(hào)密碼登錄了。
RabbitMQ快速入門——生產(chǎn)者
需求:
在idea中創(chuàng)建一個(gè)新的空工程,添加兩個(gè)maven模塊。?
?然后再在兩個(gè)工程里面分別導(dǎo)入rabbitMQ的依賴和編譯的版本插件。
<dependencies>
<!--rabbitmq的java客戶端-->
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.6.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<!--編譯插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
??
有基本架構(gòu)圖和簡(jiǎn)單工作模式的圖可得以下流程。因?yàn)楹?jiǎn)單模式中沒(méi)有交換機(jī),所以這里不涉及交換機(jī)的創(chuàng)建。
//發(fā)送消息
public class producer {
public static void main(String[] args) throws IOException, TimeoutException {
//1.創(chuàng)建連接工廠
ConnectionFactory factory=new ConnectionFactory();
//2.設(shè)置參數(shù)
factory.setHost("XXX.XX.XXX.XXX"); //設(shè)置ip地址。默認(rèn)為127.0.0.1
factory.setPort(5672); //端口 默認(rèn)值5672
factory.setVirtualHost("/itcast"); //設(shè)置虛擬機(jī) 默認(rèn)值/
factory.setUsername("yhy"); //用戶名,默認(rèn)值guest
factory.setPassword("XXXXXX"); //密碼,默認(rèn)值guest
//3.創(chuàng)建連接Connection
Connection connection = factory.newConnection();
//4.創(chuàng)建Channel
Channel channel = connection.createChannel();
//5.創(chuàng)建隊(duì)列Queue
/*
queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)
參數(shù):
1.queue:隊(duì)列名稱
2.durable:是否持久化,當(dāng)mq重啟之后,還在
3.exclusive:
*是否獨(dú)占。只能有一個(gè)消費(fèi)者監(jiān)聽(tīng)這隊(duì)列
*當(dāng)Connection關(guān)閉時(shí),是否刪除隊(duì)列
4.autoDelete: 是否自動(dòng)刪除。當(dāng)沒(méi)有Consumer時(shí),自動(dòng)刪除掉
5.arguments:參數(shù)。
*/
//如果沒(méi)有一個(gè)名叫hello_yhy的隊(duì)列,則會(huì)自動(dòng)創(chuàng)建一個(gè)
channel.queueDeclare("hello_yhy",true,false,false,null);
//6.發(fā)送消息
/*
basicPublish(String exchange, String routingKey, AMQP.BasicProperties props, byte[] body)
參數(shù):
1.exchange:交換機(jī)名稱。簡(jiǎn)單模式下交換機(jī)會(huì)使用默認(rèn)的""。
2.routerKey:路由名稱。
3.props:配置信息
4.body:發(fā)送消息數(shù)據(jù)
*/
String body="hello rabbitmq!!!";
channel.basicPublish("","hello_yhy",null,body.getBytes());
//7.釋放資源
channel.close();
connection.close();
}
}
?在控制臺(tái)中可以看見(jiàn)現(xiàn)在沒(méi)有一個(gè)隊(duì)列。
?運(yùn)行完之后可以看見(jiàn)hello_yhy隊(duì)列出現(xiàn)了。
?但是沒(méi)有新的Connection和channel出現(xiàn),因?yàn)樽詈箨P(guān)閉了,如果代碼最后不關(guān)閉就會(huì)出現(xiàn)。
然后程序不同就會(huì)顯示一直running。
?
?
RabbitMQ快速入門——消費(fèi)者
與生產(chǎn)者非常類似。?
但是由上圖可知,創(chuàng)建channel的參數(shù)雖然一樣,但是是不同的channel.
在寫生產(chǎn)者時(shí)已經(jīng)有一個(gè)隊(duì)列了,所以再創(chuàng)建一次也沒(méi)有問(wèn)題
目前隊(duì)列中有兩條消息。
public class consumer {
public static void main(String[] args) throws IOException, TimeoutException {
//1.創(chuàng)建連接工廠
ConnectionFactory factory=new ConnectionFactory();
//2.設(shè)置參數(shù)
factory.setHost("XXX.XX.XXX.XXX"); //設(shè)置ip地址。默認(rèn)為127.0.0.1
factory.setPort(5672); //端口 默認(rèn)值5672
factory.setVirtualHost("/itcast"); //設(shè)置虛擬機(jī) 默認(rèn)值/
factory.setUsername("yhy"); //用戶名,默認(rèn)值guest
factory.setPassword("XXXXXX"); //密碼,默認(rèn)值guest
//3.創(chuàng)建連接Connection
Connection connection = factory.newConnection();
//4.創(chuàng)建Channel
Channel channel = connection.createChannel();
//5.創(chuàng)建隊(duì)列Queue
/*
queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)
參數(shù):
1.queue:隊(duì)列名稱
2.durable:是否持久化,當(dāng)mq重啟之后,還在
3.exclusive:
*是否獨(dú)占。只能有一個(gè)消費(fèi)者監(jiān)聽(tīng)這隊(duì)列
*當(dāng)Connection關(guān)閉時(shí),是否刪除隊(duì)列
4.autoDelete: 是否自動(dòng)刪除。當(dāng)沒(méi)有Consumer時(shí),自動(dòng)刪除掉
5.arguments:參數(shù)。
*/
//如果沒(méi)有一個(gè)名叫hello_yhy的隊(duì)列,則會(huì)自動(dòng)創(chuàng)建一個(gè)
channel.queueDeclare("hello_yhy",true,false,false,null);
/*
* basicConsume(String queue, boolean autoAck, Consumer callback)
* 參數(shù):
* 1.隊(duì)列名稱
* 2.autoAck:是否自動(dòng)確認(rèn)
* 3.callback:回調(diào)對(duì)象
* */
//6.接收消息
Consumer consumer=new DefaultConsumer(channel){
/*
* 回調(diào)方法,當(dāng)收到消息后,會(huì)自動(dòng)執(zhí)行該方法
* 1.consumerTag:標(biāo)識(shí)
* 2.envelope :獲取一些信息,交換機(jī),路由key...
* 3.properties: 配置信息
* 4.body: 數(shù)據(jù)
* */
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("consumerTag:"+consumerTag);
System.out.println("Exchange:"+envelope.getExchange());
System.out.println("RoutingKey:"+envelope.getRoutingKey());
System.out.println("properties:"+properties);
System.out.println("body:"+new String(body));
}
};
channel.basicConsume("hello_yhy",true,consumer);
//不需要關(guān)閉資源
}
}
運(yùn)行消費(fèi)者代碼之后
?可以看見(jiàn)雀氏取出了兩條消息。并且控制臺(tái)看見(jiàn)已經(jīng)沒(méi)有消息了。
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-567281.html
小結(jié)?
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-567281.html
到了這里,關(guān)于消息隊(duì)列——RabbitMQ基本概念+容器化部署和簡(jiǎn)單工作模式程序的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!