Unbuntu20 installs RabbitMQ and go language to integrate rabbitmq to realize the effect of real-time monitoring

Install RabbitMQ on Ubuntu20.04

RabbitMQ official website: https://www.rabbitmq.com/

1. Preparation before installation

sudo apt-get update -y
sudo apt-get install curl gnupg -y

2. Install the RabbitMQ signing key

curl -fsSL https://github.com/rabbitmq/signing-keys/releases/download/2.0/rabbitmq-release-signing-key.asc | sudo apt-key add -

3. Install apt HTTPS transport

sudo apt-get install apt-transport-https

4. Add the Bintray repository that provides the latest RabbitMQ and Erlang versions

Create the bintray.erlang.list file in the /etc/apt/sources.list.d directory, and enter the following content in the file (here Ubuntu20.04, Erlang version 23.x is taken as an example)

deb https://dl.bintray.com/rabbitmq-erlang/debian focal erlang-23.x

The content entered into the file in this step varies according to the version of Ubuntu and Erlang. The relationship and selection of the versions are introduced below

In the above input content, focal represents Ubuntu20.04, and the specific corresponding relationship is as follows
insert image description here

Among them, erlang-23.x represents the 23.x version of Erlang

Then save the file and exit

5. Install the Erlang package

sudo apt-get update -y

sudo apt-get install -y erlang-base 
                    erlang-asn1 erlang-crypto erlang-eldap erlang-ftp erlang-inets 
                    erlang-mnesia erlang-os-mon erlang-parsetools erlang-public-key 
                    erlang-runtime-tools erlang-snmp erlang-ssl 
                    erlang-syntax-tools erlang-tftp erlang-tools erlang-xmerl

Specify a valid package

sudo apt-get update -y

Create a new erlang file in the /etc/apt/preferences.d directory and enter the following content

Package: erlang*
Pin: release o=Bintray
Pin-Priority: 1000

Execute the following command

sudo apt-cache policy

Change the erlang file in the /etc/apt/preferences.d directory to the following content (here erlang chooses version 23.0.3-1)

Package: erlang*
Pin: version 1:23.0.3-1
Pin-Priority: 1000

Package: esl-erlang
Pin: version 1:22.3.4.1
Pin-Priority: 1000

6. Modify the rabbitmq file in the /etc/apt/preferences.d/ directory and add the following content

Package: rabbitmq-server
Pin: version 1:3.8.7
Pin-Priority: 1000

7. Install RabbitMQ

Execute the following command

sudo apt-get update -y
sudo apt-get install rabbitmq-server -y --fix-missing

8. Verify RabbitMQ installation

start up

 //启动管理界面和外部监控系统
sudo rabbitmq-plugins enable rabbitmq_management
// 启动RabbitMQ
sudo service rabbitmq-server start

9. Visit the page to view the effect

Visit http://localhost:15672/ in the browser, the password and user name are guest
insert image description here
here because I have established a queue, so there will be a message.

9. The four commands used by RabbitMQ are summarized as follows

// Start
sudo service rabbitmq-server start
// Restart
sudo service rabbitmq-server restart
// Stop
sudo service rabbitmq-server stop
// View status
sudo service rabbitmq-server status

go language integration rabbitmq (manual ack)

ready bag

We use the package under github.com/streadway/amqp . Here I use the form of gomod to manage the package, so download the package according to the mod mode.

producer, producer.go

package main

import (
	"github.com/streadway/amqp"
	"log"
	"reflect"
	"strconv"
	"time"
)

//初始化全局变量,方便复用
var connection *amqp.Connection
var ch *amqp.Channel
var queue amqp.Queue
var c chan int
var confirms chan amqp.Confirmation

/**
初始化函数,默认在main方法前执行
 */
func init()  {
    
    
	var err error
	//建立连接
	connection, err = amqp.Dial("amqp://guest:guest@ip:5672/")
	if nil != err {
    
    
		log.Fatalf("connect the rabbitmqProducer error: %s",err)
	}
	//设置通道
	ch, err = connection.Channel()


	if nil != err {
    
    
		log.Fatalf("connect the channel error: %s",err)
	}
	//开启确认机制
	 ch.Confirm(false)
	confirms = ch.NotifyPublish(make(chan amqp.Confirmation, 1)) // 处理确认逻辑


	//定义队列
	queue, _ = ch.QueueDeclare("guet-block-1",false,false,
		false,false,nil)

	if nil != err {
    
    
		log.Fatalf("create the queue error: %s",err)
	}
}

/**
因为channel通道隔一段时间会被关闭,需要重连,否则手动ack会报错。
*/
func reconnectRabbitmq() () {
    
    
	var err error
	//建立连接
	connection, err = amqp.Dial("amqp://guest:guest@ip:5672/")
	if nil != err {
    
    
		log.Fatalf("connect the rabbitmqProducer error: %s",err)
	}
	//设置通道
	ch, err = connection.Channel()

	if nil != err {
    
    
		log.Fatalf("connect the channel error: %s",err)
	}
	//开启确认机制
	ch.Confirm(false)
	// 处理确认逻辑
	confirms = ch.NotifyPublish(make(chan amqp.Confirmation, 1)) 

	//定义队列
	queue, _ = ch.QueueDeclare("guet-block-1",false,false,
		false,false,nil)

	if nil != err {
    
    
		log.Fatalf("create the queue error: %s",err)
	}
}

func main(){
    
    
	//模拟阻塞
	c = make(chan int)
	go producer("")
	<- c
}

/**
msg是需要的消息内容,可以是json或其他内容。入参可以加上发送内容的类型,如:ContentType: "text/plain"
 */
func producer(msg string)  {
    
    
	//此处msg均写死。
	for i := 0; i < 300; i++ {
    
    
		msg = strconv.Itoa(i)
		//通过反射拿到channel结构体的closed字段值
		closed := getClosed(*ch)
		if closed == 1 {
    
    
			log.Printf("重连。。。。。。。。。。。。。。。。。")
			//0:channel未关闭,1:channel已关闭,为了不报错,我们重新建立连接
			reconnectRabbitmq()
		}
		//发布消息
		//exchange, key string, mandatory, immediate bool, msg Publishing
		err :=ch.Publish("",queue.Name,false,false,amqp.Publishing{
    
    
			Body: []byte(msg),
		})
		if(err != nil){
    
    
			log.Panic("send mesg error %v",msg)
		}
		// 生产者是否confirm成功
		isSuccess := confirmOne(confirms)
		//未成功需要重新调用
		if ! isSuccess{
    
    
			//log.Printf("重发======================== ",msg)
			//通过反射拿到channel结构体的closed字段值
			closed := getClosed(*ch)
			if closed == 1 {
    
    
				log.Printf("重连。。。。。。。。。。。。。。。。。")
				//0:channel未关闭,1:channel已关闭,为了不报错,我们重新建立连接
				reconnectRabbitmq()
			}
			//发布消息
			//exchange, key string, mandatory, immediate bool, msg Publishing
			err :=ch.Publish("",queue.Name,false,false,amqp.Publishing{
    
    
				Body: []byte(msg),
			})
			if(err != nil){
    
    
				log.Panic("send mesg error %v",msg)
			}
		}
		log.Printf("发送的数据为:%s ",msg)
		//间隔三秒发一次信息
		time.Sleep(time.Duration(3)*time.Second)
	}
	c <- 0
}

func getClosed(ch amqp.Channel) int64 {
    
    

	d :=reflect.ValueOf(ch)
	// 根据名字查找字段并转换为Int64
	i := d.FieldByName("closed").Int()
	return i
}

// 消息确认
func confirmOne(confirms <-chan amqp.Confirmation) bool{
    
    
	if confirmed := <-confirms; !confirmed.Ack {
    
    
		//log.Printf("confirmed delivery with delivery tag: %d", confirmed.DeliveryTag)
		return false
	}
	return true
}


Consumer consumer.go

package main

import (
	"github.com/streadway/amqp"
	"log"
	"reflect"
)
//初始化全局变量,方便复用
var connection *amqp.Connection
var ch *amqp.Channel
var queue amqp.Queue

var consumerMsg <-chan amqp.Delivery

/**
初始化函数,默认在main方法前执行
*/
func init()  {
    
    
	var err error
	//建立连接
	connection, err = amqp.Dial("amqp://guest:guest@ip:5672/")
	if nil != err {
    
    
		log.Fatalf("connect the rabbitmqConsumer error: %s",err)
	}
	//设置通道
	ch, err = connection.Channel()
	if nil != err {
    
    
		log.Fatalf("connect the channel error: %s",err)
	}
	//定义队列
	queue, _ = ch.QueueDeclare("guet-block",false,false,
		false,false,nil)

	if nil != err {
    
    
		log.Fatalf("create the queue error: %s",err)
	}

	consumerMsg, err = ch.Consume(queue.Name, "", false,
		false, false, false, nil)

	if nil != err {
    
    
		log.Fatalf("receive error %v", err)
	}
}

//因为channel通道隔一段时间会被关闭,需要重连,否则手动ack会报错。
func reconnectRabbitmq() () {
    
    
	var err error
	//建立连接
	connection, err = amqp.Dial("amqp://guest:guest@ip:5672/")
	if nil != err {
    
    
		log.Fatalf("connect the rabbit error: %v",err)
	}

	//defer connection.Close()

	//设置通道
	ch, err = connection.Channel()
	if nil != err {
    
    
		log.Fatalf("get connect fail: %v",err)
	}

	//defer ch.Close()

	//定义队列
	queue, _ = ch.QueueDeclare("guet-block", false, false,
		false, false, nil)
	//获取消息
	consumerMsg, err = ch.Consume(queue.Name, "", false,
		false, false, false, nil)
	if nil != err {
    
    
		log.Fatalf("receive error %v", err)
	}

}


func main() {
    
    

	// 创建一个channel
	c := make(chan int)
	log.Println("正在异步请求 consumer")
	go consumer()
	<- c
}


/**
消费者
 */
func consumer()  {
    
    
	//无限监听
	for  {
    
    
		select {
    
    
		case msg := <-consumerMsg:
			//channel被强制关闭,需要重新建立连接
			//通过反射拿到channel结构体的closed字段值
			closed := getClosed(*ch)
			if closed == 1 {
    
    
				//0:channel未关闭,1:channel已关闭,为了不报错,我们重新建立连接
				reconnectRabbitmq()
			}else {
    
    
				log.Printf("接受到的数据为 :%s\n",msg.Body)
				//手动ack,false:代表只对当前消息ack,ture,对这条消息前的所有的消息都ack
				if err := msg.Ack(false); err != nil {
    
    
					log.Fatalf("hand ack fail msg: ",err)
				}
			}


		}
	}
}

/**
反射获取channel关闭位标识位
 */
func getClosed(ch amqp.Channel) int64 {
    
    
	d :=reflect.ValueOf(ch)
	// 根据名字查找字段并转换为Int64
	i := d.FieldByName("closed").Int()
	return i
}

Simulation effect:

insert image description here
insert image description here
insert image description here
insert image description here

Guess you like

Origin blog.csdn.net/ydl1128/article/details/126794009