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 ...
随机推荐
- navicat for mysql 下载安装教程
Navicat是一套快速.可靠并价格相当便宜的数据库管理工具,专为简化数据库的管理及降低系统管理成本而设.它的设计符合数据库管理员.开发人员及中小企业的需要.Navicat 是以直觉化的图形用户界面而 ...
- Mysql(三):表操作
一 存储引擎介绍 存储引擎即表类型,mysql根据不同的表类型会有不同的处理机制 详见:http://www.cnblogs.com/6324TV/p/8481061.html 二 表介绍 表相当于文 ...
- kubernetes之node隔离与恢复
需求: 在硬件升级, 硬件维护等情况下, 我们需要将某些node隔离, kubectl cordon <node_name> #禁止pod调度到该节点上, 在其上运行的pod并不会自动停止 ...
- Vue入门(四)——Axios向SpringMVC传数据
在实际业务需求中,经常会出现前台传表单或者对象到后台,后台Handler接受并转换成对应的POJO以供业务代码使用 此时在SpringMVC框架中就要用到@RequestBody注解,该注解用于将请求 ...
- docker 查看系统进程pid
docker inspect -f '{{.State.Pid}} {{.Id}}' $(docker ps -a -q)
- 基于Ajax技术的前后端Json数据交互方式实现
前言 使用浏览器访问网站是日常生活中必不可少的一件事情,当我们在浏览器地址栏中输入网址后会看到网站的内容,那么这个过程中发生了什么?下面简单介绍下浏览器访问网站过程. 第一步:浏览器向DNS服务器发起 ...
- BZOJ 3630: [JLOI2014]镜面通道 (网络流 +计算几何)
水能流过的地方光都能达到 呵呵.jpg 那就是裸的最小割(割开上边界和下边界)了- 判矩形和圆相交的时候就用圆心对矩形求一次点到矩形的最近距离(类似KD树的预估函数). CODE #include & ...
- python--openCV--图像处理
安装 pip3 install opencv-python 图像处理: import cv2 #导入opencv库 import numpy as np img = cv2.imread(" ...
- [Python自学] day-19 (1) (FBV和CBV、路由系统)
一.获取表单提交的数据 在 [Python自学] day-18 (2) (MTV架构.Django框架)中,我们使用过以下方式来获取表单数据: user = request.POST.get('use ...
- switch语句分析
1.关于switch语句 如果if语句中表达式是判断是否等于一个常量时,可以用switch语句来代替 if(表达式 == 常量1) { ...