前言
最近在跟慕课做一个秒杀商城的小项目,接触了RabbitMQ
虽然平时是在Python中实现消息队列,但是不得不说RabbitMQ香呀
今天也是除夕,在这个祝大家新年快乐,发个小水文章吧QAQ
安装开始
$ brew install rabbitmq
$ vim ~/.zshrc
$ rabbitmq-server
$ rabbitmq-plugins list
$ rabbitmq-plugins enable rabbitmq_management
$ rabbitmq-plugins enable rabbitmq_tracing
$ rabbitmq-plugins disable rabbitmq_tracing
$ rabbitmq-server -detached
$ rabbitmqctl status
$ rabbitmqctl stop
打好基础
这些都是很基本的概念,你得明白什么是什么就好了
因为作为工具,首先要会用起来,会采用囫囵吞枣的模式学习
随着后面的深入,慢慢了解特点吧
概念 | 描述 |
---|
Channel | 生产者publish或是消费者subscribe一个队列都是通过信道来通信的 | Exchange | exchange的作用就是类似路由器,服务器会根据路由键将消息从交换器路由到队列上去 | Queue | 队列收到的消息将发送给消费者 | Binding | 建立链接交换的绑定信息 | VirtualHost | 不同的隔离区,防止污染 | Connection | 建立的链接 |
工作模式 | 描述 |
---|
simple | 最简单的收发模式 | work | 资源的竞争 | publish/subscribe | 共享资源 | routing | 只能匹配上路由key对应的消息队列,对应的消费者才能消费消息 | topic | routing的一种模糊匹配 |
代码实现
功能仓库文件
const MQURL = "amqp://guest:guest@127.0.0.1:5672/"
type RabbitMQ struct {
conn *amqp.Connection
channel *amqp.Channel
QueueName string
Exchange string
Key string
Mqurl string
}
func NewRabbitMQ(queueName string, exchange string, key string) *RabbitMQ {
return &RabbitMQ{QueueName: queueName, Exchange: exchange, Key: key, Mqurl: MQURL}
}
func (r *RabbitMQ) Destroy() {
r.channel.Close()
r.conn.Close()
}
func (r *RabbitMQ) failOnErr(err error, message string) {
if err != nil {
log.Printf("%s:%s", message, err)
panic(fmt.Sprintf("%s:%s", message, err))
}
}
func NewRabbitMQSimple(queueName string) *RabbitMQ {
rabbitmq := NewRabbitMQ(queueName, "", "")
var err error
rabbitmq.conn, err = amqp.Dial(rabbitmq.Mqurl)
rabbitmq.failOnErr(err, "failed to connect rabbitmq!")
rabbitmq.channel, err = rabbitmq.conn.Channel()
rabbitmq.failOnErr(err, "failed to open a channel")
return rabbitmq
}
func (r *RabbitMQ) PublishSimple(message string) {
_, err := r.channel.QueueDeclare(
r.QueueName,
false,
false,
false,
false,
nil,
)
if err != nil {
fmt.Println(err)
}
r.channel.Publish(
r.Exchange,
r.QueueName,
false,
false,
amqp.Publishing{
ContentType: "text/plain",
Body: []byte(message),
})
}
func (r *RabbitMQ) ConsumeSimple() {
q, err := r.channel.QueueDeclare(
r.QueueName,
false,
false,
false,
false,
nil,
)
if err != nil {
fmt.Println(err)
}
msg, err := r.channel.Consume(
q.Name,
"",
true,
false,
false,
false,
nil,
)
if err != nil {
fmt.Println(err)
}
forever := make(chan bool)
go func() {
for d := range msg {
log.Printf("Received a message: %s", d.Body)
}
}()
log.Printf(" [*] Waiting for messages. To exit press CTRL+C")
<-forever
}
func NewRabbitMQPubSub(exchangeName string) *RabbitMQ {
rabbitmq := NewRabbitMQ("", exchangeName, "")
var err error
rabbitmq.conn, err = amqp.Dial(rabbitmq.Mqurl)
rabbitmq.failOnErr(err, "failed to connect rabbitmq!")
rabbitmq.channel, err = rabbitmq.conn.Channel()
rabbitmq.failOnErr(err, "failed to open a channel")
return rabbitmq
}
func (r *RabbitMQ) PublishPub(message string) {
err := r.channel.ExchangeDeclare(
r.Exchange,
"fanout",
true,
false,
false,
false,
nil,
)
r.failOnErr(err, "Failed to declare an exchange")
err = r.channel.Publish(
r.Exchange,
"",
false,
false,
amqp.Publishing{
ContentType: "text/plain",
Body: []byte(message),
})
}
func (r *RabbitMQ) ReceiveSub() {
err := r.channel.ExchangeDeclare(
r.Exchange,
"fanout",
true,
false,
false,
false,
nil,
)
r.failOnErr(err, "Failed to declare an exchange")
q, err := r.channel.QueueDeclare(
"",
false,
false,
true,
false,
nil,
)
r.failOnErr(err, "Failed to declare a queue")
err = r.channel.QueueBind(
q.Name,
"",
r.Exchange,
false,
nil)
message, err := r.channel.Consume(
q.Name,
"",
true,
false,
false,
false,
nil,
)
forever := make(chan bool)
go func() {
for d := range message {
log.Printf("Received a message: %s", d.Body)
}
}()
fmt.Println("退出请按 CTRL+C\n")
<-forever
}
func NewRabbitMQRouting(exchangeName string, routingKey string) *RabbitMQ {
rabbitmq := NewRabbitMQ("", exchangeName, routingKey)
var err error
rabbitmq.conn, err = amqp.Dial(rabbitmq.Mqurl)
rabbitmq.failOnErr(err, "failed to connect rabbitmq!")
rabbitmq.channel, err = rabbitmq.conn.Channel()
rabbitmq.failOnErr(err, "failed to open a channel")
return rabbitmq
}
func (r *RabbitMQ) PublishRouting(message string) {
err := r.channel.ExchangeDeclare(
r.Exchange,
"direct",
true,
false,
false,
false,
nil,
)
r.failOnErr(err, "Failed to declare an exchange")
err = r.channel.Publish(
r.Exchange,
r.Key,
false,
false,
amqp.Publishing{
ContentType: "text/plain",
Body: []byte(message),
})
}
func (r *RabbitMQ) ReceiveRouting() {
err := r.channel.ExchangeDeclare(
r.Exchange,
"direct",
true,
false,
false,
false,
nil,
)
r.failOnErr(err, "Failed to declare an exchange")
q, err := r.channel.QueueDeclare(
"",
false,
false,
true,
false,
nil,
)
r.failOnErr(err, "Failed to declare a queue")
err = r.channel.QueueBind(
q.Name,
r.Key,
r.Exchange,
false,
nil)
message, err := r.channel.Consume(
q.Name,
"",
true,
false,
false,
false,
nil,
)
forever := make(chan bool)
go func() {
for d := range message {
log.Printf("Received a message: %s", d.Body)
}
}()
fmt.Println("退出请按 CTRL+C\n")
<-forever
}
func NewRabbitMQTopic(exchangeName string, routingKey string) *RabbitMQ {
rabbitmq := NewRabbitMQ("", exchangeName, routingKey)
var err error
rabbitmq.conn, err = amqp.Dial(rabbitmq.Mqurl)
rabbitmq.failOnErr(err, "failed to connect rabbitmq!")
rabbitmq.channel, err = rabbitmq.conn.Channel()
rabbitmq.failOnErr(err, "failed to open a channel")
return rabbitmq
}
func (r *RabbitMQ) PublishTopic(message string) {
err := r.channel.ExchangeDeclare(
r.Exchange,
"topic",
true,
false,
false,
false,
nil,
)
r.failOnErr(err, "Failed to declare an exchange")
err = r.channel.Publish(
r.Exchange,
r.Key,
false,
false,
amqp.Publishing{
ContentType: "text/plain",
Body: []byte(message),
})
}
func (r *RabbitMQ) ReceiveTopic() {
err := r.channel.ExchangeDeclare(
r.Exchange,
"topic",
true,
false,
false,
false,
nil,
)
r.failOnErr(err, "Failed to declare an exch"+
"ange")
q, err := r.channel.QueueDeclare(
"",
false,
false,
true,
false,
nil,
)
r.failOnErr(err, "Failed to declare a queue")
err = r.channel.QueueBind(
q.Name,
r.Key,
r.Exchange,
false,
nil)
message, err := r.channel.Consume(
q.Name,
"",
true,
false,
false,
false,
nil,
)
forever := make(chan bool)
go func() {
for d := range message {
log.Printf("Received a message: %s", d.Body)
}
}()
fmt.Println("退出请按 CTRL+C\n")
<-forever
}
各个模式实现
因为不确定包的位置
所以报红简单写一下引入上面的仓库文件就好了
- 简单模式
func main() {
rabbitmq := RabbitMQ.NewRabbitMQSimple("Simple")
rabbitmq.PublishSimple("Hello world!")
fmt.Println("发送成功!")
}
func main() {
rabbitmq := RabbitMQ.NewRabbitMQSimple("Simple")
rabbitmq.ConsumeSimple()
}
- 工作模式
func main() {
rabbitmq := RabbitMQ.NewRabbitMQSimple("Simple")
for i := 0; i <= 100; i++ {
rabbitmq.PublishSimple("Hello world!" + strconv.Itoa(i))
time.Sleep(1 * time.Second)
fmt.Println(i)
}
}
func main() {
rabbitmq := RabbitMQ.NewRabbitMQSimple("Simple")
rabbitmq.ConsumeSimple()
}
func main() {
rabbitmq := RabbitMQ.NewRabbitMQSimple("Simple")
rabbitmq.ConsumeSimple()
}
- 发布模式
func main() {
rabbitmq := RabbitMQ.NewRabbitMQPubSub("newProduct")
for i := 0; i < 100; i++ {
rabbitmq.PublishPub("订阅模式生产第" + strconv.Itoa(i) + "条" + "数据")
fmt.Println("订阅模式生产第" + strconv.Itoa(i) + "条" + "数据")
time.Sleep(1 * time.Second)
}
}
func main() {
rabbitmq := RabbitMQ.NewRabbitMQPubSub("newProduct")
rabbitmq.ReceiveSub()
}
func main() {
rabbitmq := RabbitMQ.NewRabbitMQPubSub("newProduct")
rabbitmq.ReceiveSub()
}
- 路由模式
func main() {
One := RabbitMQ.NewRabbitMQRouting("ex", "one")
Two := RabbitMQ.NewRabbitMQRouting("ex", "two")
for i := 0; i <= 10; i++ {
One.PublishRouting("Hello one!" + strconv.Itoa(i))
Two.PublishRouting("Hello Two!" + strconv.Itoa(i))
time.Sleep(1 * time.Second)
fmt.Println(i)
}
}
func main() {
One := RabbitMQ.NewRabbitMQRouting("ex", "one")
One.ReceiveRouting()
}
func main() {
Two := RabbitMQ.NewRabbitMQRouting("ex", "two")
Two.ReceiveRouting()
}
- 话题模式
func main() {
One := RabbitMQ.NewRabbitMQTopic("exTopic", "topic.one")
Two := RabbitMQ.NewRabbitMQTopic("exTopic", "topic.two")
for i := 0; i <= 10; i++ {
One.PublishTopic("Hello topic one!" + strconv.Itoa(i))
Two.PublishTopic("Hello topic Two!" + strconv.Itoa(i))
time.Sleep(1 * time.Second)
fmt.Println(i)
}
}
func main() {
One := RabbitMQ.NewRabbitMQTopic("exTopic", "#")
One.ReceiveTopic()
}
func main() {
Two := RabbitMQ.NewRabbitMQTopic("exTopic", "*.two")
Two.ReceiveTopic()
}
|