簡單模擬MQ的作用 – 完成異步通訊

如圖顯示:有了RabbitMQ,你就可以和三個妹子同時進行短信聊天,就不需要為無法同時和三個妹子語音聊天而苦惱
MQ存在的意義 (解決同步通訊的存在的缺點)

如圖所示:當用戶完成了支付功能,我們需要倉儲服務對應商品數量減1,當我們的支付服務頻繁呼叫倉儲服務之后,倉儲服務掛掉了,這個時候支付服務想再調倉儲服務就調不了,然后支付服務也阻塞在這里了,然后系統崩了,
同步存在的問題
初探MQ的作用
1. 服務解耦合

2. 性能提升,吞吐量提高

3. 服務沒有強依賴,不擔心級聯失敗問題

ps:概念啥的,誰想看啊
我們直接進入RabbitMQ的使用
安裝RabbitMQ
PS:默認你們安裝好了docker在自己的虛擬機或者自己的服務器上面了
docker pull rabbitmq:3-management(遠程安裝,版本可以自主選擇)
--------------------------------------
也可以在自己電腦上面下載rabbitmq.tar,然后上傳到你的虛擬機或者服務器,然后
docker load -i mq.tar
---------------------------
接下來,我們就可以使用docker運行我們的RabbitMQ了
docker run \
-e RABBITMQ_DEFAULT_USER=xxx \
-e RABBITMQ_DEFAULT_PASS=xxx\
--name mq \
--hostname mq1 \
-p 15672:15672 \ (注意:這是管理頁面埠)
-p 5672:5672 \ (注意:這是通訊埠)
-d \ (后臺運行)
rabbitmq:3-management
別直接復制上面的運行指令直接運行了,xxx,xxx這兩個你自主設定一下,把括號和括號里面的內容洗掉一下
祝你好運
登錄管理頁面( ip地址:15672 )


如果你能登錄進去說明你的安裝配置都沒有問題了,恭喜你,
整合RabbitMQ到專案里面
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

我們可以創建一個普通的maven專案為父專案,把依賴放在里面,再創建兩個springboot子專案,分別作為訊息的發布者和訊息的消費者
ps:需要這個專案檔案的可加qq:2338244917
然后我們在連個子專案中連接上我們的RabbitMQ
spring:
rabbitmq:
host: 47.98.251.192 # ip地址(你們懂的)
port: 5672 # 這個你就別填15672了,那個是登錄管理面板使用的
username: xxx
password: xxx
virtual-host: / # 虛擬主機地址:可以在管理面板創建,不然就和我一樣
// 我們可以在專案publisher的測驗類里面測驗和學習
@Autowired
private RabbitTemplate rabbitTemplate; //注入物件
@Test
public void test01() {
String queueName = "simple.queue";//佇列名
String msg = "hello spring amqp!";//發送的資訊
rabbitTemplate.convertAndSend(queueName,msg);
}
//我們在consumer專案里面創建一個listeber包,然后寫一個類
//使用注解@RabbitListener,然后填出正確佇列名,
//我們String msg的型別要和訊息發布的型別一致
@RabbitListener(queues = "simple.queue")
public void listenSimpleMessage(String msg) {
System.out.println("消費者接收到simple.queue的訊息:"+msg);
}
通過上面的操作,我們就可以讓我們的消費者時刻消費發布者的訊息了

上面的例子,我們就會出現一個問題,假設:我們有兩個消費者(我們可以按照上面的多做一個@RabbitListener(queues=“xxx.xxx”))就行了,這個時候,我們的發布者發送50條資訊,消費者我們搞連個來消費這些訊息,一個1秒處理50條,一個1秒處理20條,
這樣,這兩個消費者處理一樣數量的訊息
原因是因為要一個處理完,下一個才能處理,這樣有個亂用,我們要能者多勞
spring:
rabbitmq:
host: 47.98.251.199
username: root
password: 922815
port: 5672
virtual-host: /
listener:
simple:
prefetch: 1 # 每次取一條訊息,處理完成才能獲取下一條訊息
在consumer專案配置一下就可以解決這個問題了
最后聊一聊交換機(Exchange)
交換機不儲存訊息

FanoutExchange
作用: 當我們訊息的發送者發送訊息成功之后,我們的FanoutExchange就會讓系結在它上面的佇列queue全部都能消費到每一個訊息
//consumer專案下
package cn.itcast.mq.cofig;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FanoutConfig {
//宣告FanoutExchange交換機
@Bean
public FanoutExchange fanoutExchange() {
return new FanoutExchange("lin.fanout");
}
//宣告第一個佇列
@Bean
public Queue fanoutQueue1() {
return new Queue("fanout.queue1");
}
//系結佇列1和交換機
@Bean
public Binding bindingQueue1(Queue fanoutQueue1,FanoutExchange fanoutExchange) {
return BindingBuilder
.bind(fanoutQueue1)
.to(fanoutExchange);
}
//宣告第二個佇列
@Bean
public Queue fanoutQueue2() {
return new Queue("fanout.queue2");
}
//系結佇列2和交換機
@Bean
public Binding bindingQueue2(Queue fanoutQueue2,FanoutExchange fanoutExchange) {
return BindingBuilder
.bind(fanoutQueue2)
.to(fanoutExchange);
}
//...略,以相同方式宣告第n個佇列,并完成系結
}
//publisher專案
@Test
public void testSendFanoutExchange() {
//交換機名稱
String exchangeName = "lin.fanout";
//訊息
String message = "Hello Everyone!";
//發送訊息
rabbitTemplate.convertAndSend(exchangeName,"",message);
}
前面的代碼是在consumer專案里面的,后面的代碼是publisher專案的代碼
DirectExchange
作用: 我們可以通過DirectExchange(路由交換機),通過發送資訊時,系結routingKey來指定我們發送給哪個訊息佇列消費
//consumer專案下
@RabbitListener(bindings = @QueueBinding(
value = @Queue(name = "direct.queue1"),
exchange = @Exchange(name = "lin.direct",type = ExchangeTypes.DIRECT),
key = {"red","blue"}
))
public void listenDirectQueue1(String msg) {
System.out.println("消費者接收到direct.queue1訊息:["+msg+"]");
}
//publisher專案下
@Test
public void testSendDirectExchange1() {
//交換機名稱
String exchangeName = "lin.direct";
//訊息
String message = "Hello yellow!";
//發送訊息
rabbitTemplate.convertAndSend(exchangeName,"yellow",message);
}
TopicExchange
作用: 這玩意的作用相當于把訊息佇列分類

#:代表0個或者1個單詞,*:代表1個單詞
@RabbitListener(bindings = @QueueBinding(
value = @Queue(name = "topic.queue1"),
exchange = @Exchange(name = "lin.topic",type = ExchangeTypes.TOPIC),
key = "china.#"
))
public void listenTopicQueue2(String msg) {
System.out.println("消費者接收到topic.queue1的訊息:["+msg+"]");
}
//publisher專案
@Test
public void testSendTopicExchange1() {
//交換機名字
String exchangeName = "lin.topic";
//訊息
String msg = "Hello,topicExchange!";
//發送
rabbitTemplate.convertAndSend(exchangeName,"china.news",msg);
}
ps:最后的最后渴望變成天使
大家別走,聽我bb完最后一個知識點,b完我就下班了
SpringAMQP-訊息轉換器
它的作用就是,當我們訊息的發布者發布一個訊息是一個物件給rabbitMQ的時候,我們jdk有它一套方式,這方式不但性能不行,還不安全,我們要取代它
引入依賴
<!--jackson-databind-->
<!--我們在父專案依賴里面引入,這樣我們學習的時候就能讓子專案也能用了-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
注入@Bean
這個@Bean我們可以在springboot專案入口那個類里面注入
當然在配置類里面注入也可以
//這玩意就是覆寫jdk編碼格式的
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
//上面是為了避免你們導錯包
@Bean
public MessageConverter jsonMessageConverter() {
return new Jackson2JsonMessageConverter();
}
我們簡單來使用一下它
@RabbitListener(queues = "object.queue")
public void listenObjectQueue(Map<String,Object> msg) {
System.out.println("接收到object.queue的訊息:"+msg);
}
@Test
public void testSendDirectExchange5() {
//佇列名字
String queryName = "object.queue";
//訊息
Map<String,Object> msg = new HashMap<>();
msg.put("name","柳巖");
msg.put("age",21);
rabbitTemplate.convertAndSend(queryName,msg);
}
好了,到此淺談RabbitMQ就告一段落了
感謝能看到這里還不走的讀者
要是還能給我點個贊就更加感謝了
如有問題,可以聯系qq:2338244917
作者:隨風
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/302744.html
標籤:其他
