RabbitMQ

一、”Hello World!”

1、简介:

RabbitMQ是一种消息中间件,主要思想很简单:接收消息并转发。你可以将它设想为一个邮局:你往里面发送邮件并确保邮件能实际运达,RabbitMQ好比这里的邮箱、邮局和邮递员的角色。

RabbitMQ和邮局的一个主要区别是,RabbitMQ仅仅接收、存储、转发这些数据包裹——message。

先来看下RabbitMQ中的一些关键术语:

a)、生产(者):除了发送什么意义都没有。一个发送消息的应用就是一个生产者,使用如下描述:

b)、队列:储存消息的“容器”,可以储存任意多的message——本质上是一个无限长度的缓冲区,多个生产者可以将消息发送至同一队列,多个消费者也可以从同一队列中接收消息。队列使用如下描述,”queue_name”是该队列的名称:

c)、消费(者):一个消费者就好比一个用来等待接收消息的程序。使用如下来描述:

2、”Hello World!”(使用Go RabbitMQ客户端)

这节我们将使用Go写两个小程序:一个生产者用来发送单一消息,一个消费者用来接收这些消息并打印。图示如下:

备注:这里使用“amqp”包,自行安装:
go get github.com/streadway/amqp

发送:

首先创建一个send.go和receiver.go分别用来发送和接收,发送方会链接RabbitMQ服务器、发送消息然后退出。

在send.go,首先导入相关包:

package main

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

再加一个出错处理类:

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

连接到服务器:

conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")  //一般默认端口5672
failOnError(err, "Failed to connect to RabbitMQ")
defer conn.Close()

这里的conn对象是抽象了底层的socket链接,在conn的基础上我们可以创建多个channel(通道,一个conn可以创建多个channel,使用channel节省了tcp资源,后续的很多操作如:队列声明、消息声明发送、交换器声明等都是在channel基础上操作的),接下来是产生一个channel:

ch, err := conn.Channel()
failOnError(err, "Failed to open a channel")
defer ch.Close()

为了发送消息到队列,我们还应该声明一个队列,并将消息发送给它:

q, err := ch.QueueDeclare(
"hello", // name 队列名称
false, // durable 是否持久化,默认为false
false, // delete when unused 队列无订阅时是否自动删除队列
false, // exclusive 是否队列私有,私有后仅有一个应用可以连接
false, // no-wait
nil, // arguments
)
failOnError(err, "Failed to declare a queue") body := "hello" //消息主体
err = ch.Publish( //发送消息
"", // exchange //指定消息发送的交换器名称
q.Name, // routing key //路由键
false, // mandatory
false, // immediate
amqp.Publishing {
ContentType: "text/plain", //消息类型:文本消息
Body: []byte(body), //消息体,理论上可以发送任意类型数据,因为是byte类型
})
failOnError(err, "Failed to publish a message")

至此发送方代码完毕!

接收:

接收跟发送不同的是,接收端一直运行监听发送端消息发送并打印输出,接收端的模型如下:

在这里,我们仍然使用send.go中的逻辑执行,首先是链接服务器,其次是声明channel和队列(可以防止接收端启动时发送端还没有启动的情况),主要代码如下:

conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
failOnError(err, "Failed to connect to RabbitMQ")
defer conn.Close() ch, err := conn.Channel()
failOnError(err, "Failed to open a channel")
defer ch.Close() q, err := ch.QueueDeclare(
"hello", // name
false, // durable
false, // delete when usused
false, // exclusive
false, // no-wait
nil, // arguments
)
failOnError(err, "Failed to declare a queue")

这里声明的队列名称就是send.go中声明的队列,然后从该队列中读取消息并打印:

msgs, err := ch.Consume(
q.Name, // queue
"", // consumer
true, // auto-ack
false, // exclusive
false, // no-local
false, // no-wait
nil, // args
)
failOnError(err, "Failed to register a consumer") forever := make(chan bool) go func() {
for d := range msgs {
log.Printf("Received a message: %s", d.Body)
}
}()
log.Printf(" [*] Waiting for messages. To exit press CTRL+C")
<-forever

至此,所有代码书写完毕,完整版代码如下:

发送:

package main

import (
"fmt"
"log" "github.com/streadway/amqp"
) func failOnError(err error, msg string) {
if err != nil {
log.Fatalf("%s:%s", msg, err)
panic(fmt.Sprintf("%s:%s", msg, err))
}
} func main() {
//链接rabbitMQ服务器
conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
failOnError(err, "fail to connect to rabbitmq server")
defer conn.Close() //声明一个channel
ch, err := conn.Channel()
failOnError(err, "fail to open a channel")
defer ch.Close() //根据channel声明一个队列
q, err := ch.QueueDeclare("queue_name", false, false, false, false, nil)
failOnError(err, "fail to define a queue") //使用channel直接发送消息至队列
body := "hello queue!"
err = ch.Publish("", q.Name, false, false, amqp.Publishing{
ContentType: "text/plain",
Body: []byte(body),
})
failOnError(err, "fail to publish the message")
}

接收:

// rabbitmq_1.receiver project main.go
package main import (
"fmt"
"log" "github.com/streadway/amqp"
) func main() {
//链接RabbitMQ服务器
conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
failOnError(err, "Failed to connect to RabbitMQ")
defer conn.Close() //声明一个channel
ch, err := conn.Channel()
failOnError(err, "failed to open a channel")
defer ch.Close() //使用channel声明一个队列
q, err := ch.QueueDeclare("queue_name", false, false, false, false, nil)
failOnError(err, "failed to declare a queue") //注册一个消费者
msgs, err := ch.Consume(q.Name, "", true, false, false, false, nil)
failOnError(err, "failed to register a consumer") //定义一个never型chan,用于防止进程退出
var forever chan bool = make(chan bool, )
//开启一个channel,实时打印channel中的消息
go func() {
for d := range msgs {
log.Printf("received a message:%s", d.Body)
}
}() log.Printf("press Ctrl+c to exit!")
<-forever
} func failOnError(err error, msg string) {
if err != nil {
log.Fatalf("%s: %s", msg, err)
panic(fmt.Sprintf("%s: %s", msg, err))
}
}

然后我们使用RabbitMQ自带的管理工具查看mq运行情况:

首先要开启管理工具:
rabbitmq-plugins enable rabbitmq_management

然后浏览器访问地址:http://localhost:15672/,这里输入默认用户名密码:guest/guest,进去后界面如下:

												

rabbitmq消息队列——"Hello World!"的更多相关文章

  1. RabbitMQ消息队列(一): Detailed Introduction 详细介绍

     http://blog.csdn.net/anzhsoft/article/details/19563091 RabbitMQ消息队列(一): Detailed Introduction 详细介绍 ...

  2. RabbitMQ消息队列1: Detailed Introduction 详细介绍

    1. 历史 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求,虽然在同步消息通讯的世界里有 ...

  3. (转)RabbitMQ消息队列(九):Publisher的消息确认机制

    在前面的文章中提到了queue和consumer之间的消息确认机制:通过设置ack.那么Publisher能不到知道他post的Message有没有到达queue,甚至更近一步,是否被某个Consum ...

  4. (转)RabbitMQ消息队列(七):适用于云计算集群的远程调用(RPC)

    在云计算环境中,很多时候需要用它其他机器的计算资源,我们有可能会在接收到Message进行处理时,会把一部分计算任务分配到其他节点来完成.那么,RabbitMQ如何使用RPC呢?在本篇文章中,我们将会 ...

  5. (转)RabbitMQ消息队列(六):使用主题进行消息分发

    在上篇文章RabbitMQ消息队列(五):Routing 消息路由 中,我们实现了一个简单的日志系统.Consumer可以监听不同severity的log.但是,这也是它之所以叫做简单日志系统的原因, ...

  6. (转)RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)

    上篇文章中,我们把每个Message都是deliver到某个Consumer.在这篇文章中,我们将会将同一个Message deliver到多个Consumer中.这个模式也被成为 "pub ...

  7. RabbitMQ消息队列应用

    RabbitMQ消息队列应用 消息通信组件Net分布式系统的核心中间件之一,应用与系统高并发,各个组件之间解耦的依赖的场景.本框架采用消息队列中间件主要应用于两方面:一是解决部分高并发的业务处理:二是 ...

  8. RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)

    上篇文章中,我们把每个Message都是deliver到某个Consumer.在这篇文章中,我们将会将同一个Message deliver到多个Consumer中.这个模式也被成为 "pub ...

  9. RabbitMQ消息队列(九):Publisher的消息确认机制

    在前面的文章中提到了queue和consumer之间的消息确认机制:通过设置ack.那么Publisher能不到知道他post的Message有没有到达queue,甚至更近一步,是否被某个Consum ...

  10. 使用EasyNetQ组件操作RabbitMQ消息队列服务

    RabbitMQ是一个由erlang开发的AMQP(Advanved Message Queue)的开源实现,是实现消息队列应用的一个中间件,消息队列中间件是分布式系统中重要的组件,主要解决应用耦合, ...

随机推荐

  1. codeIgniter 文件路径的问题

    学习CI的时候,发现一个问题,求指点. 整个项目的头部文件共用,CSS.JS 等文件都一起引入.在以下路径下都没问题. 首页      -- http://localhost/citest/index ...

  2. Win7 64位 VS2015环境使用SDL2-2.0.4

    之前在VS中使用SDL2,如果只链接SDL2.lib,会提示 error LNK2019: unresolved external symbol _main referenced in functio ...

  3. iOS 应用中有页面加载gif动画,从后台进入前台时就消失了

    解决办法: 在Appdelegate.m 里面有一个从后台进入前台所响应的方法,可以在该方法里post 一个通知,在加载动画里的页面接受通知,响应一定的方法即可 #pragma -mark 当程序进入 ...

  4. Win7下硬盘安装Linux双系统

    Win7下硬盘安装CentOS6.2 一.准备工作:划出磁盘空闲空间和准备安装文件  参考文献: [Win7下硬盘安装Linux总结(CentOS)]来源:Linux社区  作者:lixianlin ...

  5. android开机过程简单描述

    1 开机引导bootloader,相当于电脑开机启动bios 2 引导过后可以进入三种模式:fastboot, recovery, linux kernel.前两种跟版本升级相关,正常开机进入linu ...

  6. 天气预报API(五):城市代码--“新编码”和“旧编码” 对比

    参考一些博客.文章 来查找 测试 接口,后来发现两套城市编码标准,有点想法,故拿来对比分析. 注:新旧编码是个人主观叫法,只是为了方便称呼,可能有不当之处,请留言更正. 暂且称 中国天气网等网站使用的 ...

  7. oracle中用户删除不了,ORA-01940提示 “无法删除当前已连接用户”

    Oracle删除用户的提示无法删除当前已连接用户两种解决方法如下: 1.先锁定用户.然后查询进程号,最后删除对应的进程.在删除对应的用户 SQL>alter user XXX account l ...

  8. DVDstore 数据库基准测试

    1 DVDStore介绍 DVDstore 是一个电子商务测试应用,模拟多用户登陆在线系统,搜索DVD,购买DVD.多用来用作测试数据库性能或者其他的压力测试. 2 快速浏览测试步骤 (a)  安装数 ...

  9. TortoiseSVN客户端使用说明

    TortoiseSVN客户端使用说明 TortoiseSVN不是一个独立的窗口程序,而是集成在windows右键菜单中,下面对TortoiseSVN的菜单项做简要的说明.01.SVN Checkout ...

  10. 【C-分支结构】

    一.关系运算符 双目运算符 自左向右结合 关系运算符的优先级低于算术运算符,高于赋值运算符 <(小于) <=(小于或等于) >(大于) >=(大于或等于) ==(等于) !=( ...