golang rabbitmq实践 (二 实现简单的消息收发)

1:驱动

  本来打算自己写一个驱动的,后来发现github上面已经有了,那我就直接拿现成的了, 驱动采用 github.com/streadway/amqp ,直接import就可以啦!

2:exchange and queue

  在上一篇文章中,我们已经创建好virtualhost 、exchange and queue,所以我们先定义这些常量

  

const (
    queueName = "push.msg.q"
    exchange  = "t.msg.ex"
    mqurl ="amqp://shi:[email protected]:5672/test"
)
var conn *amqp.Connectionvar channel *amqp.Channel
 

3:错误处理

  

func failOnErr(err error, msg string) {
	if err != nil {
		log.Fatalf("%s:%s", msg, err)
		panic(fmt.Sprintf("%s:%s", msg, err))
	}
}

4:连接mq

func mqConnect() {
    var err error
    conn, err = amqp.Dial(mqurl)
    failOnErr(err, "failed to connect tp rabbitmq")

    channel, err = conn.Channel()
    failOnErr(err, "failed to open a channel")
}

5:push

  先上代码:

func push() {

    if channel == nil {
        mqConnect()
    }
    msgContent := "hello world!"

    channel.Publish(exchange, queueName, false, false, amqp.Publishing{
        ContentType: "text/plain",
        Body:        []byte(msgContent),
    })
}

  其实是很简单的,调用 channel函数的Publish方法,传入exchange name 和 queue name,最后一个参数是消息内容,ContentType我们设置为text/plain, 为文本类型,body是消息内容,要传入字节数组,这样就完成了一条消息的push,接下来我们再看receive

6:receive

代码:

func receive() {
    if channel == nil {
        mqConnect()
    }

    msgs, err := channel.Consume(queueName, "", true, false, false, false, nil)
    failOnErr(err, "")

    forever := make(chan bool)

    go func() {
        //fmt.Println(*msgs)
        for d := range msgs {
            s := BytesToString(&(d.Body))
            count++
            fmt.Printf("receve msg is :%s -- %d\n", *s, count)
        }
    }()

    fmt.Printf(" [*] Waiting for messages. To exit press CTRL+C\n")
    <-forever
}

  通过调用channel.Consume函数返回一个接受消息的chan类型管道,然后range 这个chan,接收到的数据是[]byte,转换为string后输出

  <-forever  这个是为了控制当前线程不退出

7:入口main

  

func main() {
    go func() {
        for {
            push()
            time.Sleep(1 * time.Second)
        }
    }()
    receive()
    fmt.Println("end")
    close()
}

  for 循环保证每秒发送一条消息到mq,这个地方采用协程保证不阻塞主线程。receive函数不能采用协程,不然主线程就退出了。close函数是释放连接对象,但是在这个例子中是没有起效的,因为线程永远都不会自动退出,只能认为的CTRL+C 或者程序死掉,系统重启

8:执行:

切换到go文件目录执行

go run main.go

//运行日志

receve msg is :hello world! -- 1246
receve msg is :hello world! -- 1247
receve msg is :hello world! -- 1248
receve msg is :hello world! -- 1249
receve msg is :hello world! -- 1250
receve msg is :hello world! -- 1251
receve msg is :hello world! -- 1252
receve msg is :hello world! -- 1253
receve msg is :hello world! -- 1254
receve msg is :hello world! -- 1255
receve msg is :hello world! -- 1256
receve msg is :hello world! -- 1257
receve msg is :hello world! -- 1258
receve msg is :hello world! -- 1259
receve msg is :hello world! -- 1260
receve msg is :hello world! -- 1261
receve msg is :hello world! -- 1262
receve msg is :hello world! -- 1263
receve msg is :hello world! -- 1264
receve msg is :hello world! -- 1265
receve msg is :hello world! -- 1266

9:全部代码

package main

import (
    "fmt"
    "log"
    "bytes"
    "time"
    "github.com/streadway/amqp"
)

var conn *amqp.Connection
var channel *amqp.Channel
var count = 0

const (
    queueName = "push.msg.q"
    exchange  = "t.msg.ex"
    mqurl ="amqp://shi:[email protected]:5672/test"
)

func main() {
    go func() {
        for {
            push()
            time.Sleep(1 * time.Second)
        }
    }()
    receive()
    fmt.Println("end")
    close()
}

func failOnErr(err error, msg string) {
    if err != nil {
        log.Fatalf("%s:%s", msg, err)
        panic(fmt.Sprintf("%s:%s", msg, err))
    }
}

func mqConnect() {
    var err error
    conn, err = amqp.Dial(mqurl)
    failOnErr(err, "failed to connect tp rabbitmq")

    channel, err = conn.Channel()
    failOnErr(err, "failed to open a channel")
}

func close() {
    channel.Close()
    conn.Close()
}

//连接rabbitmq server
func push() {

    if channel == nil {
        mqConnect()
    }
    msgContent := "hello world!"

    channel.Publish(exchange, queueName, false, false, amqp.Publishing{
        ContentType: "text/plain",
        Body:        []byte(msgContent),
    })
}

func receive() {
    if channel == nil {
        mqConnect()
    }

    msgs, err := channel.Consume(queueName, "", true, false, false, false, nil)
    failOnErr(err, "")

    forever := make(chan bool)

    go func() {
        //fmt.Println(*msgs)
        for d := range msgs {
            s := BytesToString(&(d.Body))
            count++
            fmt.Printf("receve msg is :%s -- %d\n", *s, count)
        }
    }()

    fmt.Printf(" [*] Waiting for messages. To exit press CTRL+C\n")
    <-forever
}

func BytesToString(b *[]byte) *string {
    s := bytes.NewBuffer(*b)
    r := s.String()
    return &r
}
时间: 2024-08-27 05:27:11

golang rabbitmq实践 (二 实现简单的消息收发)的相关文章

golang rabbitmq实践(啰嗦)

1:背景简介 我是一个.net一线开发,今年6月份离开帝都来到魔都,后入职于莫江互联网在线教育公司.现刚刚转正,在这短短的三个月的时间,莫江给我的是职业路上颠覆性变化. .net技术迷 => nodejs/java/golang 在此之前,我认为我会在.net平台坚定不移的走下,因为我是如此的喜欢C#语言,认为它是那么优美简介,vs ide号称宇宙神器,coding如此happy,but 当我们每周技术讨论例会上,我才真正的认识到我自己原来就是井底之蛙 2:C#和其他我所接触的语言对比 网上关于

golang rabbitmq实践 (一 rabbitmq配置)

1:环境选择 系统为ubuntu 15.04 ,我装在虚拟机里面的 2:rabbitmq tabbitmq 3.5.4  download url : http://www.rabbitmq.com/ 3:安装 在Ubuntu环境下,建议直接下载deb安装包,可以再ubuntu软件包管理中直接安装,并且安装其他依赖包 4:启动 如果是deb包直接安装的话,默认是直接启动的,也可以通过 sudo  rabbitmq-server start 启动.如果提示 node with name "rabb

转: RabbitMQ实现中AMQP与MQTT消息收发异同

转自:http://www.cnblogs.com/lucifer1997/p/9438186.html 实现了AMQP与MQTT(至多一次)后,用多个队列以topic exchange的方式用相同交换机监听同一个主题(topic),发现情况存在不同,觉得有点意思,所以记录了下来. 用2个MQTT(分别记作A.B).2个AMQP(分别记作C.D)同时监听一个topic, 然后向这个topic先以MQTT的方式发送4条消息(分别记作1.2.3.4), 再以AMQP方式发送4条消息(分别记作5.6.

RabbitMQ系列二(构建消息队列)

从AMQP协议可以看出,MessageQueue.Exchange和Binding构成了AMQP协议的核心.下面我们就围绕这三个主要组件,从应用使用的角度全面的介绍如何利用RabbitMQ构建消息队列以及使用过程中的注意事项. 声明MessageQueue: 在RabbitMQ中,无论是生产者发送消息还是消费者接收消息,都首先需要声明一个MessageQueue.这就存在一个问题,是生产者声明还是消费者声明呢?要解决这个问题,首先要明确: 1)消费者是无法订阅或者获取不存在的MessageQue

RabbitMQ事务和Confirm发送方消息确认——深入解读

引言 根据前面的知识(深入了解RabbitMQ工作原理及简单使用.Rabbit的几种工作模式介绍与实践)我们知道,如果要保证消息的可靠性,需要对消息进行持久化处理,然而消息持久化除了需要代码的设置之外,还有一个重要步骤是至关重要的,那就是保证你的消息顺利进入Broker(代理服务器),如图所示: 正常情况下,如果消息经过交换器进入队列就可以完成消息的持久化,但如果消息在没有到达broker之前出现意外,那就造成消息丢失,有没有办法可以解决这个问题? RabbitMQ有两种方式来解决这个问题: 通

初识RabbitMQ系列之一:简单介绍

一:RabbitMQ是什么? 众所周知,MQ是Message  Queue(消息队列)的意思,RabbitMQ就是众多MQ框架其中的一款,开源实现了AMQP协议(官网:http://www.amqp.org/),也就是说RabbitMQ是一个开源的消息队列框架. 他用于在分布式系统中存储转发消息,在易用性.扩展性.高可用性等方面都非常的优秀.是当前最主流的消息中间件之一. RabbitMQ的官网:http://www.rabbitmq.com 二:RabbitMQ优势&劣势? 优势: 1:安装部

RabbitMQ(二) ——工作队列

RabbitMQ(二) --工作队列 (转载请附上本文链接--linhxx) 一.概述 工作队列模式(work queue),是有多个消费者的情况下,可以共同消费队列内的内容,加快消息处理速度.这是RabbitMQ的基本工作模式. 二.使用方式 和上一篇中的生产和消费消息的方式一样,就是需要多在cli进程中打开一个消费者的php文件.即需要打开3个php,一个是生产者的php文件,两个消费者的php文件(或多个php文件). 三.工作机制 3.1 轮询(Round-robin dispatchi

Golang 高效实践之并发实践

前言 在我前面一篇文章Golang受欢迎的原因中已经提到,Golang是在语言层面(runtime)就支持了并发模型.那么作为编程人员,我们在实践Golang的并发编程时,又有什么需要注意的点呢?下面我会跟大家详细的介绍一些在实际生产编程中很容易踩坑的知识点. CSP 在介绍Golang的并发实践前,有必要先介绍简单介绍一下CSP理论.CSP,全称是Communicating sequential processes,翻译为通信顺序进程,又翻译为交换消息的顺序程序,用来描述并发性系统的交互模式.

一个基于RabbitMQ的可复用的事务消息方案

原文:一个基于RabbitMQ的可复用的事务消息方案 前提# 分布式事务是微服务实践中一个比较棘手的问题,在笔者所实施的微服务实践方案中,都采用了折中或者规避强一致性的方案.参考Ebay多年前提出的本地消息表方案,基于RabbitMQ和MySQL(JDBC)做了轻量级的封装,实现了低入侵性的事务消息模块.本文的内容就是详细分析整个方案的设计思路和实施.环境依赖如下: JDK1.8+ spring-boot-start-web:2.x.x.spring-boot-start-jdbc:2.x.x.