分布式文件存储——使用RabbitMQ实现异步上传

使用RabbitMQ实现异步上传

mq异步模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K6OZdxl1-1660465839237)(C:/Users/86158/AppData/Roaming/Typora/typora-user-images/image-20220814094215320.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1S5Tg0v3-1660465839238)(C:/Users/86158/AppData/Roaming/Typora/typora-user-images/image-20220814094522497.png)]

rabbitmq介绍

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oj77y9EN-1660465839239)(C:/Users/86158/AppData/Roaming/Typora/typora-user-images/image-20220814095447187.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z0PpDvSV-1660465839239)(C:/Users/86158/AppData/Roaming/Typora/typora-user-images/image-20220814100132774.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g1wnqEWu-1660465839239)(C:/Users/86158/AppData/Roaming/Typora/typora-user-images/image-20220814100153389.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OpmMdDcj-1660465839240)(C:/Users/86158/AppData/Roaming/Typora/typora-user-images/image-20220814100400422.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y1ZNciU4-1660465839240)(C:/Users/86158/AppData/Roaming/Typora/typora-user-images/image-20220814100415737.png)]

安装rabbitmq

# 创建数据目录
mkdir /data/rabbitmq

# 启动mq
docker run -d --hostname rabbit-svr --name rabbit -p 5672:5672 -p 15672:15672 -p 25672:25672 -v /data/rabbitmq:/var/lib/rabbitmq rabbitmq:management

打开管理后台

http://ip:15672

账号: guest
密码: guest

代码演示

package mq

import "github.com/jyyds/filestore/common"

// 转移队列中消息载体的结构体格式
type TransferData struct {
	FileHash      string
	CurLocation   string
	DestLocation  string
	DestStoreType common.StoreType
}

生产者

package mq

import (
	"log"

	"github.com/jyyds/filestore/config"
	"github.com/streadway/amqp"
)

var conn *amqp.Connection
var channel *amqp.Channel

func initChannel() bool {
	//  1.判断channel是否已经创建过
	if channel != nil {
		return true
	}
	//  2.获取rabbitmq的一个连接
	conn, err := amqp.Dial(config.RabbitURL)
	if err != nil {
		log.Println(err.Error())
		return false
	}

	//  3.打开一个channel,用于消息的发布与接收
	channel, err = conn.Channel()
	if err != nil {
		log.Println(err.Error())
		return false
	}
	return true

}

// 发布消息
func Puublish(exchange, routingKey string, msg []byte) bool {
	// 1.判断channel是否正常
	if !initChannel() {
		return false
	}

	// 2.执行消息发布动作
	err := channel.Publish(
		exchange,
		routingKey,
		false,
		false,
		amqp.Publishing{
			ContentType: "text/plain",
			Body:        msg,
		},
	)
	if err != nil {
		log.Println(err.Error())
		return false
	}

	return true
}

	data := mq.TransferData{
			FileHash:      fileMeta.FileSha1,
			CurLocation:   fileMeta.Location,
			DestLocation:  ossPath,
			DestStoreType: cmn.StoreOSS,
		}
		pubData, _ := json.Marshal(data)
		suc := mq.Puublish(
			cfg.TransExchangeName,
			cfg.TransOSSRoutingKey,
			pubData,
		)

消费者

package mq

import "log"

var done chan bool

// 开始监听队列,获取信息
func StartConsume(qName, cName string, callBack func(msg []byte) bool) {
	// 1. 用过channel.Consume获取消息信道
	msgs, err := channel.Consume(
		qName,
		cName,
		true,
		false,
		false,
		false,
		nil,
	)
	if err != nil {
		log.Println(err.Error())
		return
	}

	// 2. 循环获取队列的消息

	go func() {
		for msg := range msgs {
			// 3.调用callback方法处理新的消息
			procssSuc := callBack(msg.Body)
			if !procssSuc {
				// TODO:将任务写到另外一个队列,用于异常情况的重试
			}
		}
	}()

	// done没有新的消息过来,会一直发生阻塞
	<-done

	// 关闭rabbitmq
	channel.Close()

}

package main

import (
	"bufio"
	"encoding/json"
	"log"
	"os"

	"github.com/jyyds/filestore/config"
	dblayer "github.com/jyyds/filestore/db"
	"github.com/jyyds/filestore/mq"
	"github.com/jyyds/filestore/store/oss"
)

func ProcessTransfer(msg []byte) bool {
	// 1. 解析msg
	pubData := mq.TransferData{}
	err := json.Unmarshal(msg, pubData)
	if err != nil {
		log.Println(err.Error())
		return false
	}

	// 2. 根据临时存储文件路径,创建文件句柄
	filed, err := os.Open(pubData.CurLocation)
	if err != nil {
		log.Println(err.Error())
		return false
	}

	// 3. 通过文件句柄将文件内容读出来并且上传到OSS

	err = oss.Bucket().PutObject(
		pubData.DestLocation,
		bufio.NewReader(filed),
	)
	if err != nil {
		log.Println(err.Error())
		return false
	}

	// 4. 更新文件的存储路径到文件表
	suc := dblayer.UpdateFileLocation(
		pubData.FileHash,
		pubData.DestLocation,
	)

	if !suc {
		log.Println(err.Error())
		return false
	}

	return true
}

func main() {
	log.Println("开始监听转移任务队列...")
	mq.StartConsume(
		config.TransOSSQueueName,
		"transfer_oss",
		ProcessTransfer,
	)
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值