代码改变世界

RabbitMQ系列之“Hello,World”

2011-07-27 11:52  雪中风筝  阅读(746)  评论(0编辑  收藏  举报

这篇文章中通过一个简单的Hello,world程序来实现消息的发送和接收

这个是建立的一个获取连接和关闭连接的类

 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using RabbitMQ.Client;
6
7 namespace Binqsoft.RabbitMQ.Client
8 {
9 public class BSConnection
10 {
11 //return a connection to the RabbitMQServer using specify port
12 public IConnection GetConnection(string hostName,string userName,string Password,int Port)
13 {
14 ConnectionFactory factory = new ConnectionFactory();
15 factory.HostName = hostName;
16 factory.UserName = userName;
17 factory.Password = Password;
18 factory.Protocol = Protocols.DefaultProtocol;
19 factory.Port = Port;
20
21 IConnection conn = factory.CreateConnection();
22 return conn;
23 }
24
25
26 //return a conntion to the server use default Protocol:AMQP 0-9-1 Port:5672
27 public IConnection GetConnection(string hostName, string username, string Password)
28 {
29 ConnectionFactory factory = new ConnectionFactory();
30 factory.HostName = hostName;
31 factory.UserName = username;
32 factory.Password = Password;
33 factory.Protocol = Protocols.DefaultProtocol;
34
35
36 IConnection conn = factory.CreateConnection();
37 return conn;
38 }
39
40
41 public IConnection GetConnection(string hostName)
42 {
43 ConnectionFactory factory = new ConnectionFactory();
44 factory.HostName = hostName;
45 factory.UserName = ConnectionFactory.DefaultUser;
46 factory.Password = ConnectionFactory.DefaultPass;
47 factory.Protocol = Protocols.DefaultProtocol;
48
49
50 IConnection conn = factory.CreateConnection();
51 return conn;
52 }
53
54 public void CloseConnection(IConnection conn)
55 {
56 conn.Close();
57 }
58 }
59 }

连接服务器发送消息:

 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using RabbitMQ.Client;
6 using Binqsoft.RabbitMQ.Client;
7 using System.IO;
8
9 namespace Binqsoft.RabbitMQ.Client
10 {
11 class Program
12 {
13 private const string QUEUE_NAME = "hello_queue";
14
15 static void Main(string[] args)
16 {
17 IConnection conn = null;
18
19 string message = "Hello,World";
20 byte[] body = System.Text.Encoding.UTF8.GetBytes(message);
21
22 BSConnection BSConn = new BSConnection();
23
24 try
25 {
26 conn = BSConn.GetConnection("localhost");
27 }
28 catch(IOException ex)
29 {
30 Console.WriteLine(ex.Message);
31 }
32
33 if (null == conn)
34 {
35 Console.WriteLine("Fail to connect to the server!");
36 }
37 else
38 {
39 Console.WriteLine("Connect to the server success!");
40 IModel channel = conn.CreateModel();
41 channel.QueueDeclare(QUEUE_NAME, true, false, false, null);
42
43 channel.BasicPublish("", QUEUE_NAME, null, body);
44
45 Console.WriteLine(string.Format("the message {0} already send sucess!!!", message));
46
47 BSConn.CloseConnection(conn);
48 }
49 }
50
51
52 }
53 }

运行结果:

  

这个时候消息已经发送到RabbitMQServer 的hello_queue队列里边了。

下面建立一个简单的Consumer用来接收队列中的消息:

 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using RabbitMQ.Client;
6 using Binqsoft.RabbitMQ.Client;
7 using System.IO;
8 using RabbitMQ.Client.Events;
9
10 namespace Binqsoft.RabbitMQ.Consumer
11 {
12 class Program
13 {
14 private const string QUEUE_NAME = "hello_queue";
15
16 static void Main(string[] args)
17 {
18 IConnection conn = null;
19 BSConnection bsconn = new BSConnection();
20
21 try
22 {
23 conn = bsconn.GetConnection("localhost");
24 }
25 catch (IOException ex)
26 {
27 Console.WriteLine(ex.Message);
28 }
29
30 if (null == conn)
31 {
32 Console.WriteLine("Failed to connect the server !!");
33 }
34 else
35 {
36 Console.WriteLine("Connect to the server success!!");
37 bool noAck = false;
38 IModel channel = conn.CreateModel();
39 //创建一个队列,防止consumer先启动导致找不到队列的情况,RabbitMQServer对于具有相同名称的队列只会生成一个
40 //如果用户试图创建具有相同名称但是参数不同的Queue,Rabbit会报错
41 channel.QueueDeclare(QUEUE_NAME, true, false, false, null);
42
43 BasicGetResult result = channel.BasicGet(QUEUE_NAME, noAck);
44
45 if (null == result)
46 {
47 Console.WriteLine("No message aviliable in the queue");
48 }
49 else
50 {
51 byte[] body = result.Body;
52 string message = System.Text.Encoding.UTF8.GetString(body);
53 Console.WriteLine("receive the message is " + message);
54 channel.BasicAck(result.DeliveryTag, false);
55 }
56 }
57 }
58 }
59 }

这里有个知识点是需要解释下的,即RabbitMQ中的Message Acknowlegement(确认消息),那么什么是Message Ack呢?RabbitMQ中有一个ACk的开关,默认是开启的。如果用户关闭这个ACK开关,那么当Producer将消息发送到server以后,这个消息是

存储在内存中的(假设用户没有做消息持久化),一旦Consumer从服务器获取消息,如果这个消息非常大,需要执行很长的时间,在接收消息的过程中,consumer挂掉或者崩溃,那么这些消息就会丢失。因为这种情况下服务将消息发送到接收者哪里后会马上删除这些消息。这种情况不是我们想要的,我们想要的情况是,如果在接受过程中,接收者crash掉,这些消息会仍然存在server中,server会重新发送这些消息到另外的接收者。

那么这个时候就需要开启Ack开关。怎么样开启呢?

我在代码里设置了一个noAck的变量默认为flase(也就是打开开关)

 BasicGetResult result = channel.BasicGet(QUEUE_NAME, noAck);

以上代码的第二个参数就是指定是否要开启ack.

这个时候服务器端会等待接收者发送信息接收并处理完成的确认请求

channel.BasicAck(result.DeliveryTag, false);

服务器端接收到这个请求以后,RabbitMQServer会自动删除队列里的这条消息,如果没有收到请求,RabbitMQServer就不会删除这条消息,然后会重新发送消息到其他的接收者。

接收到的结果:

  

That‘s All