第五课 实战go语言改造php仿优酷-RabbitMQ改造项目

第五课 实战go语言改造php仿优酷-RabbitMQ改造项目

tags:

  • Beego
  • 慕课网

categories:

  • RabbitMQ
  • 五种工作模式

第一节 消息队列介绍

1.1 消息队列的好处

  1. 跨语言的,支持PHP,GO,JAVA,C# ,Python …
  2. 解耦
  3. 异步
  4. 削峰

1.2 消息队列的应用场景

  1. 跨系统间的调用(比如:发短信,防止由于第三方平台原因导致我们系统的逻辑问题)
  2. 系统内的异步调用 比如发邮件功能
  3. 消息驱动的场景 当满足一个条件后,触发一系列的操作
  4. 跨语言之间的调用

1.3消息队列的相关术语

  1. Producer生产者 发送消息到队列
  2. Consumer消费者 从队列中取出消息消费掉
  3. Queue 存储消息的容器 队列 消息的载体
  4. Channel消息通道 RabbitMQ建立连接 连接中可以有多个通道
  5. Exchange交换机 决定消息按照什么规则发送到哪个队列中
  6. Routing Key 交换机通过它来确定发送到哪个队列中

1.4消息队列的工作模式

  1. 简单模式
    在这里插入图片描述

  2. 工作模式 高并发时容易导致同一个消息到两个消费者手中(可以加唯一键值解决)
    在这里插入图片描述

  3. 订阅模式 每个队列的消息都是一样的 E代表交换机
    在这里插入图片描述

  4. 路由模式 根据routing key发送到不同的消息队列中
    在这里插入图片描述

  5. 主题模式 根据routing key分类,发送到不同的消息队列中
    在这里插入图片描述

第二节 简单模式和work工作模式

2.1 封装接受端和发送端

  1. 实现发送端,不断向MQ中发送自增数字
  2. 实现接收端,接受消息然后打印到命令行中
  3. 启动两个接收端,争抢消息(启动两个客户端即可)
  4. services/mq/Mq.go
package mq

import (
	"bytes"
	"fmt"

	"github.com/streadway/amqp"
)

type Callback func(msg string)

func Connect() (*amqp.Connection, error) {
   
	conn, err := amqp.Dial("amqp://guest:guest@127.0.0.1:5672/")
	return conn, err
}

//发送端函数
func Publish(exchange string, queueName string, body string) error {
   
	//建立连接
	conn, err := Connect()
	if err != nil {
   
		return err
	}
	defer conn.Close()

	//创建通道channel
	channel, err := conn.Channel()
	if err != nil {
   
		return err
	}
	defer channel.Close()

	//创建队列
	q, err := channel.QueueDeclare(
		queueName,
		true, // 是否持久化
		false,
		false,
		false,
		nil,
	)
	if err != nil {
   
		return err
	}

	//发送消息
	err = channel.Publish(exchange, q.Name, false, false, amqp.Publishing{
   
		DeliveryMode: amqp.Persistent,
		ContentType:  "text/plain",
		Body:         []byte(body),
	})
	return err
}

//接受者方法
func Consumer(exchange string, queueName string, callback Callback) {
   
	//建立连接
	conn, err := Connect()
	defer conn.Close()
	if err != nil {
   
		fmt.Println(err)
		return
	}

	//创建通道channel
	channel, err := conn.Channel()
	defer channel.Close()
	if err != nil {
   
		fmt.Println(err)
		return
	}
	//创建queue
	q, err := channel.QueueDeclare(
		queueName,
		true,
		false,
		false,
		false,
		nil,
	)
	if err != nil {
   
		fmt.Println(err)
		return
	}

	msgs, err := channel.Consume(q.Name, "", false, false, false, false, nil)
	if err != nil {
   
		fmt.Println(err)
		return
	}
	forever := make(chan bool)
	go func() {
   
		for d := range msgs {
   
			s := BytesToString(&(d.Body))
			callback(*s)
			d.Ack(false)
		}
	}()
	fmt.Printf("Waiting for messages")
	<-forever
}

func BytesToString(b *[]byte) *string {
   
	s := bytes.NewBuffer(*b)
	r := s.String()
	return &r
}

2.2 简单发送和工作模式实现

  1. controllers/mqDemo不断的发送数据到队列fyouku_demo中
package controllers

import (
	"demo/services/mq"
	"strconv"
	"time"

	"github.com/astaxie/beego"
)

type MqDemoController struct {
   
	beego.Controller
}

//简单模式和work工作模式 push方法
// @router /mq/push [*]
func (this *MqDemoController) GetMq() {
   
	go func() {
   
		count := 0
		for {
   
			// 交换机名字为空 队列名为fyouku_demo 信息
			mq.Publish("", "fyouku_demo", "hello"+strconv.Itoa(count))
			count++
			time.Sleep(1 * time.Second)
		}
	}()
	this.Ctx.WriteString("hello")
}
  1. 接受端代码实现。这里需要单独go run (启动一个是简单模式,两个是工作模式)
package main

import (
	"demo/services/mq"
	"fmt"
)

func main() {
   
	mq.Consumer("", "fyouku_demo", callback)
}

func callback(s string) {
   
	fmt.Printf("msg is :%s\n", s)
}

2.3 持久化和手动应答

  1. 必须发送端和接受端都设置为持久化才可以。
// 发送端
	//创建队列
	q, err := channel.QueueDeclare(
		queueName,
		true, // 是否持久化
		false,
		
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值