RabbitMQ学习之:(四)回头看刚才写的程序 (转贴+我的评论)
转自:http://lostechies.com/derekgreer/2012/03/18/rabbitmq-for-windows-hello-world-review/
我的心得:
1. 在创建ConnectFactory时,我们可以传入主机名、端口号、用户名/密码、虚拟Host等参数。
2. 也可以使用ampq://用户名:密码@主机名:端口号/%2f
3. Channel是轻量级的TCP/IP连接, 而Connection是非常Expensive的。
4. 消息不是直接发到Queue的,而是Producer通过Exchange来发送的。
5. 每当声明一个Queue时,会自动绑定到默认的Exchange上。而且不能解绑、不能删除、不能显式声明,只能用来发消息。
RabbitMQ for Windows: Hello World Review
This is the third installment to the series: RabbitMQ for Windows. In the last installment, we discussed some basic messaging concepts and created our first RabbitMQ application. In this installment, we’ll be taking a closer look at our Hello World application to help round out our understanding of the basic concepts involved.
Hello World Review
In the previous installment, we walked through creating a Hello World example. Let’s review the Producer and Consumer code again:
Producer
class Program
{
static void Main(string[] args)
{
var connectionFactory = new ConnectionFactory();
IConnection connection = connectionFactory.CreateConnection();
IModel channel = connection.CreateModel();
channel.QueueDeclare("hello-world-queue", false, false, false, null);
byte[] message = Encoding.UTF8.GetBytes("Hello, World!");
channel.BasicPublish(string.Empty, "hello-world-queue", null, message);
Console.WriteLine("Press any key to exit");
Console.ReadKey();
channel.Close();
connection.Close();
}
}
Consumer
class Program
{
static void Main(string[] args)
{
var connectionFactory = new ConnectionFactory();
IConnection connection = connectionFactory.CreateConnection();
IModel channel = connection.CreateModel();
channel.QueueDeclare("hello-world-queue", false, false, false, null);
BasicGetResult result = channel.BasicGet("hello-world-queue", true);
if (result != null)
{
string message = Encoding.UTF8.GetString(result.Body);
Console.WriteLine(message);
}
Console.WriteLine("Press any key to exit");
Console.ReadKey();
channel.Close();
connection.Close();
}
}
In both the Producer and Consumer projects, we started our Main() method by establishing a Connection to the RabbitMQ server. We then created a Channel to establish a line of communication with the server and declared a Queue to send and receive our messages. In our Producer, we called BasicPublish() to place a message on the queue. In our Consumer, we called BasicGet() to retrieve a message from the queue and print the message to the console. In both the Producer and Consumer projects, we ended the Main() method by closing the channel and connection to the server.
Establishing the Connection
Let’s first discuss how our example connects to the RabbitMQ server. In our example, we’re establishing a connection using the default connection settings.
var connectionFactory = new ConnectionFactory();
This assumes we have a RabbitMQ server running on our local development machine. To connect to this instance, the ConnectionFactory uses a default host name of “localhost” and a default port of 5672. A user name and password must also be provided to connect to the server. When not specified, the ConnectionFactory uses a default user name and password of “guest”. The “guest” user was pre-configured with full administrator rights when we first installed our instance of RabbitMQ. The final parameter of interest is the Virtual Host. RabbitMQ utilizes virtual hosts (i.e. virtual instances of RabbitMQ) to allow multiple projects or teams to manage and secure their own set of queues from within a single RabbitMQ installation.
When we first installed RabbitMQ, a default virtual host named “/” was created. The ConnectionFactory uses this virtual host when one is not specified.
Specified explicitly, we might have configured these default values as follows:
var connectionFactory = new ConnectionFactory
{
HostName = "localhost",
Port = 5672,
UserName = "guest",
Password = "guest",
VirtualHost = "/"
};
IConnection connection = connectionFactory.CreateConnection();
RabbitMQ also supports the AMQP URI Specification which allows these parameters to be specified as a single URI. Using the URI option, we need to percent-encode the virtual host as “%2f”. The following is how me might have established our connection using the amqp URI:
var connectionFactory = new ConnectionFactory {Uri = "amqp://guest:guest@localhost:5672/%2f"};
IConnection connection = connectionFactory.CreateConnection();
Creating a Channel
After establishing a connection with the server, the next step we take in both the Producer and Consumer projects is to create a Channel.
IModel channel = connection.CreateModel();
A channel is a light-weight connection used by RabbitMQ to enable multiple communication sessions through a single TCP/IP connection. Operating systems have a limit to the number of TCP/IP connections that can be opened simultaneously, and creating these connections can be relatively expensive. Through the use of channels, we are free to create as many virtual connections with the server as we want without incurring this overhead or being limited by the number of available TCP/IP connections.
Channels are intended to be used for sequencing communication with the server such as declaring queues or the sending and receiving of messages. A single channels should not be used by multiple threads simultaneously. For this reason, it is recommended that channels simply not be shared across threads.
Declaring the Queue
After opening a channel within our connection, the next step we take is to declare a Queue.
channel.QueueDeclare("hello-world-queue", false, false, false, null);
A queue can be thought of as a sort of “mailbox”. Messages put in the mailbox sit there until a recipient retrieves the mail.
In our example, we named our queue “hello-world-queue”. The queue name (along with the RabbitMQ host name and port number) serves as a sort of “mailbox address”. When we publish the encoded string “Hello, World!”, it is placed in the queue named “hello-world-queue’ and awaits until a consumer retrieves and acknowledges the message.
Before discussing the parameters used in our call to QueueDeclare, it will be helpful to take a short detour and discuss how our message actually gets routed from the Producer to the Consumer.
Message Routing
When looking at our example, it appears as though the Producer sends our message directly to the “hello-world-queue”. What actually occurs, however, is that the message is routed to the “hello-world-queue” through an Exchange.
When using RabbitMQ, messages aren’t actually published to a queue, but rather are published to an exchange which then routes messages to queues. An exchange can be thought as a “post office”. Just as we don’t generally put mail directly in a recipient’s mailbox, in RabbitMQ we don’t publish messages directly to a queue.
To receive messages, a queue must first have an exchange binding established. Part of establishing the binding includes specifying which messages should be routed to the queue.[PunCha:这里我没看懂,收消息和Exchange有什么关系?] In most cases, this is achieved by specifying a routing key which serves as a filter for which messages are delivered to which queues.
The following diagram depicts how messages are published in RabbitMQ:
The reason our code looks like it sends messages directly to the queue is due to the fact that we’re taking advantage of a convenience provided by theRabbitMQ server(是server定义的). Whenever a queue is declared, it is automatically bound to a default exchange with a routing key equal to the queue name. Messages published to the default exchange with a routing key equal to the value of a declared queue name are routed to the associated queue.
In addition to being implicitly bound to all queues, the default exchange also cannot be unbound, deleted, or explicitly declared through code. The only operation that is allowed is the publishing of messages.
Queue Parameters
Returning to our discussion of queue declaration, the parameters used in our call to QueueDeclare() creates our queue as a non-durable, non-exclusive, non-auto-deleted queue.
The durability flag pertains to what happens to our queue if the server is restarted. Queues marked as durable will be recreated upon a server restart, while non-durable queues will not be.
The exclusive flag pertains to whether a queue can be declared by more than one channel. Since messages are actually published to exchanges, not queues, there may be cases where you only want a single client instance to be capable of declaring a queue bound to a particular exchange (for example, when using queues to facilitate an RPC call).
Lastly, the auto-delete flag pertains to whether the queue is automatically deleted once all consumers are removed. This flag can be a little misleading since we might suppose setting this to true would cause our “hello-world-queue” to be automatically deleted after our application exists. In fact, it wouldn’t be.
There are two different approaches to receiving messages: pulling and pushing. With the pull API, messages are retrieved on demand through a call to BasicGet(). This is the method used in our example. With the pull API, available messages are delivered to a local queue when a Consumer is bound to the channel. When setting the auto-delete flag to true, a queue will be deleted once it detects that all consumers have been removed. While we named the project which receives messages from our queue “Consumer”, the pull API doesn’t actually declare a consumer to retrieve messages. Therefore, the server is never alerted to the fact that the queue is no longer being used.
Publishing the Message
The last noteworthy point in our Producer project is the parameters to our call to BasicPublish().
channel.BasicPublish(string.Empty, "hello-world-queue", null, message);
The first parameter is the name of the exchange to publish the message to. An empty string is the designation for the default exchangediscussed earlier in the section on message routing. The second parameter is the routing key. As previously discussed, all queues are bound to the default exchange using a routing key equal to the value of the bound queue name. The third parameter is an instance of IBasicProperties. This class is used to associate a number of properties with the message, such as the message encoding, content-type, and durability. We’ll take a look at some of the uses of this class further in our series. Lastly, the fourth parameter is the byte array representing the message body.
Getting the Message
The last noteworthy point in our Consumer project is the parameters to our call to BasicGet().
BasicGetResult result = channel.BasicGet("hello-world-queue", true);
The first parameter is the queue to pull a message from which should be self-explanatory. The second parameter is a flag which controls the auto-acknowledgement of the message.
When a message is retrieved from a queue with an auto-acknowledge flag set to false, the server holds the message in an unacknowledged state until an acknowledgement or rejection of the message is received on the open channel (note that messages must be accepted or rejected on the same channel they were received on). This is useful when a consumer needs to ensure the message is processed successfully before it’s fully removed from the server. If the channel is closed without receiving an acknowledgment, the message will be requeued and delivered to the next consumer (using pull or get). In the event that a consumer determines it can’t process the message, it can reject the message with a flag indicating whether to requeue the message or not.
Conclusion
That’s it for our Hello World example review. Next time, we’ll take a look at the four basic exchange types.
RabbitMQ学习之:(四)回头看刚才写的程序 (转贴+我的评论)的更多相关文章
- com学习(四)——用 ATL 写第一个组件
建立 ATL 工程 步骤2.1:建立一个工作区(WorkSpace). 步骤2.2:在工作区中,建立一个 ATL 工程(Project).示例程序叫 Simple1,并选择DLL方式,见图一. 图一. ...
- 【DM642学习笔记四】flash烧写过程——错误记录…
(欢迎批评指正) 一,打开.cdd配置文件时出错: 解决:在FlashBurn配置窗口中,Conversion Cmd一栏可不用管: 菜单Program—Download FBTC,load ...
- RabbitMQ学习之:(六)Direct Exchange (转贴+我的评论)
From: http://lostechies.com/derekgreer/2012/04/02/rabbitmq-for-windows-direct-exchanges/ RabbitMQ fo ...
- RabbitMQ学习系列四-EasyNetQ文档跟进式学习与实践
EasyNetQ文档跟进式学习与实践 https://www.cnblogs.com/DjlNet/p/7603554.html 这里可能有人要问了,为什么不使用官方的nuget包呐:RabbitMQ ...
- rabbitmq学习(四) —— 发布订阅
为了说明这种模式,我们将建立一个简单的日志系统.这个系统将由两个程序组成,第一个将发出日志消息,第二个将接收并处理日志消息.在我们的日志系统中,每一个运行的接收程序的副本都会收到日志消息. 交换器(E ...
- rabbitMQ学习笔记(四) 发布/订阅消息
前面都是一条消息只会被一个消费者处理. 如果要每个消费者都处理同一个消息,rabbitMq也提供了相应的方法. 在以前的程序中,不管是生产者端还是消费者端都必须知道一个指定的QueueName才能发送 ...
- RabbitMQ学习笔记四:RabbitMQ命令(附疑难问题解决)
本来今天是想做RabbitMQ之优先级队列的,但是,在RabbitMQ Server创建queue时,增加优先级的最大值,头脑发热写了9999999,导致电脑内存直接飙到100%,只能重启电脑,并卸载 ...
- rabbitMQ学习(四)
按照routing key接收信息 发送端: public class EmitLogDirect { private static final String EXCHANGE_NAME = &quo ...
- rabbitmq学习(四):利用rabbitmq实现远程rpc调用
一.rabbitmq实现rpc调用的原理 ·rabbitmq实现rpc的原理是:客户端向一个队列中发送消息,并注册一个回调的队列用于接收服务端返回的消息,该消息需要声明一个叫做correaltionI ...
随机推荐
- 《浏览器工作原理与实践》<02>TCP协议:如何保证页面文件能被完整送达浏览器?
前言: 在衡量 Web 页面性能的时候有一个重要的指标叫“FP(First Paint)”,是指从页面加载到首次开始绘制的时长.这个指标直接影响了用户的跳出率,更快的页面响应意味着更多的 PV.更高的 ...
- h5 特效
地址:http://www.cnblogs.com/sun927/p/5842852.html 几个别人总结的css3炫酷效果,有需要直接拿来用即可,包括以下几个效果: 1.悬浮时放大 2.悬浮时转一 ...
- Mac安装chromedriver和geckodriver
DY@MacBook-Pro bin$brew install chromedriver Error: No available formula with the name "chromed ...
- redis.conf 文件解释
# Redis示例配置文件 # 注意单位问题:当需要设置内存大小的时候,可以使用类似1k.5GB.4M这样的常见格式: # # 1k => 1000 bytes # 1kb => 1024 ...
- RHEL8 创建本地YUM存储库
yum 的好处及本地yum的好处不在本文讨论范畴,本文针对rhel8中的新功能yum做简要介绍和配置,在 RHEL 8中分为两个存储库: BaseOS 应用程序流(AppStream) BaseOS中 ...
- [译] 优化 WEBPACK 以更快地构建 REACT
原文地址:OPTIMIZING WEBPACK FOR FASTER REACT BUILDS 原文作者:Jonathan Rowny 译文出自:掘金翻译计划 本文永久链接:https://githu ...
- Android: samil语法指令集-基于dex文件结构的寄存器虚拟机
Smali文件结构解 Smali文件与java中的类是一一对应的,包括内部类和匿名内部类也会生成对应的smali文件(典型的比如实现某个接口的匿名内部类),所以你会看到.smali文件比.java ...
- xftp传输文件失败
迁移yii项目的时候,需要手动传输runtime文件夹.但是发现总是传输失败,后来得知是因为xftp必须是root用户才能传输成功. 或者把传输的目标文件夹权限修改为777. 修改目标文件夹的属主和属 ...
- 【Python之路】特别篇--组合搜索功能实现
组合搜索: 根据特定标签内容,返回符合的数据. 效果图: 设计规划: 一.数据库表划分: 1.方向表,(运维自动化,Python开发,..) 2.分类表,(Python,Java,C#,.) 3.多对 ...
- assert 笔记
目录 什么是assert? assert使用 assert错误使用 什么是assert? Python 的 assert 语句是一个 debug 的好工具,主要用于测试一个条件是否满足.如果测试的条件 ...