这是我参与「第五届青训营 」伴学笔记创作活动的第 7 天
什么是消息队列
消息指的是两个应用间传递的数据。可能是对象也可能是字符串等多种数据类型。
“消息队列(Message Queue)”是在消息的传输过程中保存消息的容器。
在消息队列中,通常有生产者和消费者两个角色。生产者只负责发送数据到消息队列,谁从消息队列中取出数据处理,他不管。消费者只负责从消息队列中取出数据处理,他不管这是谁发送的数据。
为什么要使用
三大主要作用
- 解耦
多个系统都要调用相同的服务时候,有些服务不需要用到,而有些新增的系统又要加入这些服务,提升了耦合度,使用消息队列只需要把消息送进队列里,需要使用的系统从队列中取出即可,有效降低耦合。
- 异步
同时调用其它系统的服务时候,时间消耗会加倍,采用消息队列可以将其它系统的数据全部发送进消息队列,再由消息队列发出,大大提升性能。
- 削峰
可以起到一个缓冲的作用,防止短时间内大量请求导致数据库宕机系统崩溃,将数据发先发送至消息队列压积,然后拉去一定数量的数据进行处理,防止请求峰值时期大量的请求直接发送到数据库导致系统崩溃。
RabbitMQ的特点和组成
Messaging that just works — RabbitMQ
RabbitMQ采用Erlang进行设计开发,实现高级消息队列协。
作为开源的消息队列中间件,RabbitMQ具有许多特点,可靠性高,支持持久化操作,具有多种消息策略对消息进行分发,可以采用多台服务器搭建消息队列集群,支持各种常见语言Java、.NET、Go等,并且由可视化的管理界面。
具体特性可以看官网。
- Broker:消息队列服务进程。此进程包括两个部分:Exchange和Queue。
- Exchange:消息队列交换机。按一定的规则将消息路由转发到某个队列。
- Queue:消息队列,存储消息的队列。
- Producer:消息生产者。生产方客户端将消息同交换机路由发送到队列中。
- Consumer:消息消费者。消费队列中存储的消息
RabbitMQ的使用
还是建议使用Docker拉一个RabbitMQ的镜像到本地,然后每个应用都能使用这个镜像进行部署。
生产者P将数据发送到对消息队列,消费者将数据从消息队列中取出
- 一般使用
5672端口,要确保端口开放
- 发送
// 1. Connect
conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
failOnError(err, "Failed to connect to RabbitMQ")
defer conn.Close()
// 2. Open a channel
ch, err := conn.Channel()
failOnError(err, "Failed to open a channel")
defer ch.Close()
// 3. Declare
q, err := ch.QueueDeclare(
"hello", // name
false, // durable
false, // delete when unused
false, // exclusive
false, // no-wait
nil, // arguments
)
failOnError(err, "Failed to declare a queue")
body := "Hello World!"
// 4. Publisg
err = ch.Publish(
"", // exchange
q.Name, // routing key
false, // mandatory
false, // immediate
amqp.Publishing {
ContentType: "text/plain",
Body: []byte(body),
})
failOnError(err, "Failed to publish a message")
- 接收
// 1. Connect
conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
failOnError(err, "Failed to connect to RabbitMQ")
defer conn.Close()
// 2. Obtain a channel
ch, err := conn.Channel()
failOnError(err, "Failed to open a channel")
defer ch.Close()
// 3. Declare
q, err := ch.QueueDeclare(
"hello", // name
false, // durable
false, // delete when unused
false, // exclusive
false, // no-wait
nil, // arguments
)
failOnError(err, "Failed to declare a queue")
// 4. Receive
msgs, err := ch.Consume(
q.Name, // queue
"", // consumer
true, // auto-ack
false, // exclusive
false, // no-local
false, // no-wait
nil, // args
)
failOnError(err, "Failed to register a consumer")
forever := make(chan bool)
go func() {
for d := range msgs {
log.Printf("Received a message: %s", d.Body)
}
}()
log.Printf(" [*] Waiting for messages. To exit press CTRL+C")
<-forever
总结
- RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。
- AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。
- AMQP协议更多用在企业系统内,对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。
- RabbitMQ的可靠性是非常好的,数据能够保证百分之百的不丢失。可以使用镜像队列,它的稳定性非常好。所以说在我们互联网的金融行业。对数据的稳定性和可靠性要求都非常高的情况下,我们都会选择RabbitMQ
- RabbitMQ可以构建异地双活架构,包括每一个节点存储方式可以采用磁盘或者内存的方式。