1:RabbitMQ是个啥?(专业术语参考自网络)

     RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)。

  RabbitMQ服务器是用Erlang语言编写的,Erlang是专门为高并发而生的语言,而集群和故障转移是构建在开发电信平台框架上的。所有主要的编程语言均有与代理接口通讯的客户端库

2:使用RabbitMQ有啥好处?

RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。
AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。
AMQP协议更多用在企业系统内,对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。
RabbitMQ的可靠性是非常好的,数据能够保证百分之百的不丢失。可以使用镜像队列,它的稳定性非常好。所以说在我们互联网的金融行业。

对数据的稳定性和可靠性要求都非常高的情况下,我们都会选择RabbitMQ。当然没有kafka性能好,但是要比AvtiveMQ性能要好很多。也可以自己做一些性能的优化。

RabbitMQ可以构建异地双活架构,包括每一个节点存储方式可以采用磁盘或者内存的方式,

3:RabbitMq的安装以及环境搭建等:

   网络上有很多关于怎么搭建配置RabbitMq服务环境的详细文章,也比较简单,这里不再说明,本人是Docker上面的pull RabbitMq 镜像来安装的!

3.1:运行容器的命令如下:

docker run -d –hostname Log –restart=always –name rabbitmq -p 5672:5672 -p 15672:15672 -e RABBITMQ_DEFAULT_USER=log_user -e RABBITMQ_DEFAULT_PASS=331QQFEG123 rabbitmq:3-management

4:RabbitMq的使用场景主要有哪些,啥时候用或者不用?

4.1什么时候使用MQ?

1)数据驱动的任务依赖

2)上游不关心多下游执行结果

3)异步返回执行时间长

4.2什么时候不使用MQ?

需要实时关注执行结果 (eg:同步调用)

5:具体C#怎么使用RabbitMq?下面直接上code和测试截图了(Demo环境是.NetCore3.1控制台+Docker上的RabbitMQ容器来进行的)

6:sample模式,就是简单地队列模式,一进一出的效果差不多,测试截图:

1734768 20201016155159467 1349024480 - C#使用RabbitMq队列(Sample,Work,Fanout,Direct等模式的简单使用)

 1734768 20201016171448189 56748368 - C#使用RabbitMq队列(Sample,Work,Fanout,Direct等模式的简单使用)

Code:

 1 //简单生产端 ui调用者
 2 
 3 using System;
 4 namespace RabbitMqPublishDemo
 5 {
 6     using MyRabbitMqService;
 7     using System.Runtime.CompilerServices;
 8 
 9     class Program
10     {
11         static void Main(string[] args)
12         {
13                 //就是简单的队列,生产者
14                 Console.WriteLine("====RabbitMqPublishDemo====");
15                 for (int i = 0; i < 500; i++)
16                 {
17                     ZrfRabbitMqHelper.PublishSampleMsg("smapleMsg", $"nihaifengge:{i}");
18                 }
19                 Console.WriteLine("生成完毕!");
20                 Console.ReadLine();
21         }
22     }
23 }
24 
25 /// <summary>
26 /// 简单生产者 逻辑
27 /// </summary>
28 /// <param name="queueName"></param>
29 /// <param name="msg"></param>
30 public static void PublishSampleMsg(string queueName, string msg)
31 {
32 
33     using (IConnection conn = connectionFactory.CreateConnection())
34     {
35         using (IModel channel = conn.CreateModel())
36         {
37             channel.QueueDeclare(queue: queueName, durable: false, exclusive: false, autoDelete: false, arguments: null);
38             var msgBody = Encoding.UTF8.GetBytes(msg);
39             channel.BasicPublish(exchange: "", routingKey: queueName, basicProperties: null, body: msgBody);
40         }
41     }
42 }
43         
44 
45 //简单消费端
46 using System;
47 
48 namespace RabbitMqConsumerDemo
49 {
50     using MyRabbitMqService;
51     using System.Runtime.InteropServices;
52 
53     class Program
54     {
55         static void Main(string[] args)
56         {
57             Console.WriteLine("====RabbitMqConsumerDemo====");
58             ZrfRabbitMqHelper.ConsumeSampleMsg("smapleMsg", isBasicNack: true, handleMsgStr: handleMsgStr =>
59             {
60                 Console.WriteLine($"订阅到消息:{DateTime.Now}:{handleMsgStr}");
61             });
62             Console.ReadLine();
63         }
64     }
65 }
66 
67      #region 简单生产者后端逻辑
68         /// <summary>
69         /// 简单消费者
70         /// </summary>
71         /// <param name="queueName">队列名称</param>
72         /// <param name="isBasicNack">失败后是否自动放到队列</param>
73         /// <param name="handleMsgStr">有就自己对字符串的处理,如果要存储到数据库请自行扩展</param>
74         public static void ConsumeSampleMsg(string queueName, bool isBasicNack = false, Action<string> handleMsgStr = null)// bool ifBasicReject = false, 
75         {
76             Console.WriteLine("ConsumeSampleMsg Waiting for messages....");
77             IConnection conn = connectionFactory.CreateConnection();
78             IModel channel = conn.CreateModel();
79             channel.QueueDeclare(queue: queueName, durable: false, exclusive: false, autoDelete: false, arguments: null);
80             var consumer = new EventingBasicConsumer(channel);
81             consumer.Received += (sender, ea) =>
82             {
83                 byte[] bymsg = ea.Body.ToArray();
84                 string msg = Encoding.UTF8.GetString(bymsg);
85                 if (handleMsgStr != null)
86                 {
87                     handleMsgStr.Invoke(msg);
88                 }
89                 else
90                 {
91                     Console.WriteLine($"{DateTime.Now}->收到消息:{msg}");
92                 }
93             };
94             channel.BasicConsume(queueName, autoAck: true, consumer);
95         }
96         #endregion
97         
98         

7:Work模式

1734768 20201016155229602 173070822 - C#使用RabbitMq队列(Sample,Work,Fanout,Direct等模式的简单使用)

1734768 20201016155240751 1799800069 - C#使用RabbitMq队列(Sample,Work,Fanout,Direct等模式的简单使用)

 1 //就如下的code, 多次生产,3个消费者都可以自动开始消费
 2 
 3 //生产者
 4 using System;
 5 namespace RabbitMqPublishDemo
 6 {
 7     using MyRabbitMqService;
 8     using System.Runtime.CompilerServices;
 9     class Program
10     {
11         static void Main(string[] args)
12         {
13             for (int i = 0; i < 500; i++)
14             {
15                 ZrfRabbitMqHelper.PublishWorkQueueModel("workqueue", $" :发布消息成功{i}");
16             }
17             Console.WriteLine("工作队列模式 生成完毕......!");          
18             Console.ReadLine();
19         }
20     }
21 }
22 
23 //生产者后端逻辑
24 public static void PublishWorkQueueModel(string queueName, string msg)
25         {
26             using (var connection = connectionFactory.CreateConnection())
27             using (var channel = connection.CreateModel())
28             {
29                 channel.QueueDeclare(queue: queueName, durable: true, exclusive: false, autoDelete: false, arguments: null);
30                 var body = Encoding.UTF8.GetBytes(msg);
31                 var properties = channel.CreateBasicProperties();
32                 properties.Persistent = true;
33 
34                 channel.BasicPublish(exchange: "", routingKey: queueName, basicProperties: properties, body: body);
35                 Console.WriteLine($"{DateTime.Now},SentMsg: {msg}");
36             }
37         }
38 
39 //work消费端
40 using System;
41 
42 namespace RabbitMqConsumerDemo
43 {
44     using MyRabbitMqService;
45     using System.Runtime.InteropServices;
46     class Program
47     {
48         static void Main(string[] args)
49         {
50             Console.WriteLine("====Work模式开启了====");
51             ZrfRabbitMqHelper.ConsumeWorkQueueModel("workqueue", handserMsg: msg =>
52             {
53                 Console.WriteLine($"work模式获取到消息{msg}");
54             });
55             Console.ReadLine();
56         }
57     }
58 }
59 
60 //work后端逻辑
61        public static void ConsumeWorkQueueModel(string queueName, int sleepHmao = 90, Action<string> handserMsg = null)
62         {
63             var connection = connectionFactory.CreateConnection();
64             var channel = connection.CreateModel();
65 
66             channel.QueueDeclare(queue: queueName, durable: true, exclusive: false, autoDelete: false, arguments: null);
67             channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);
68 
69             var consumer = new EventingBasicConsumer(channel);
70             Console.WriteLine(" ConsumeWorkQueueModel Waiting for messages....");
71 
72             consumer.Received += (sender, ea) =>
73             {
74                 var body = ea.Body.ToArray();
75                 var message = Encoding.UTF8.GetString(body);
76                 if (handserMsg != null)
77                 {
78                     if (!string.IsNullOrEmpty(message))
79                     {
80                         handserMsg.Invoke(message);
81                     }
82                 }
83                 channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);
84             };
85             channel.BasicConsume(queue: queueName, autoAck: false, consumer: consumer);
86         }

8:Fanout

1734768 20201016155318840 280333966 - C#使用RabbitMq队列(Sample,Work,Fanout,Direct等模式的简单使用)

 

 

1734768 20201016155329201 162185563 - C#使用RabbitMq队列(Sample,Work,Fanout,Direct等模式的简单使用)

 Code:

 1 //同一个消息会被多个订阅者消费
 2 
 3 //发布者
 4 using System;
 5 
 6 namespace RabbitMqPublishDemo
 7 {
 8     using MyRabbitMqService;
 9     using System.Runtime.CompilerServices;
10 
11     class Program
12     {
13         static void Main(string[] args)
14         {
15 
16             #region 发布订阅模式,带上了exchange
17             for (int i = 0; i < 500; i++)
18             {
19                 ZrfRabbitMqHelper.PublishExchangeModel("exchangemodel", $"发布的消息是:{i}");
20             }
21             Console.WriteLine("发布ok!");
22             #endregion
23             Console.ReadLine();
24         }
25     }
26 }
27 //发布者的后端逻辑 我在这里选择了扇形: ExchangeType.Fanout
28    public static void PublishExchangeModel(string exchangeName, string message)
29         {
30             using (var connection = connectionFactory.CreateConnection())
31             using (var channel = connection.CreateModel())
32             {
33                 channel.ExchangeDeclare(exchange: exchangeName, type: ExchangeType.Fanout);
34                 var body = Encoding.UTF8.GetBytes(message);
35                 channel.BasicPublish(exchange: exchangeName, routingKey: "", basicProperties: null, body: body);
36                 Console.WriteLine($" Sent {message}");
37             }
38         }
39 
40 
41 //订阅者
42 using System;
43 namespace RabbitMqConsumerDemo
44 {
45     using MyRabbitMqService;
46     using System.Runtime.InteropServices;
47     class Program
48     {
49         static void Main(string[] args)
50         {
51 
52             #region 发布订阅模式 Exchange
53             ZrfRabbitMqHelper.SubscriberExchangeModel("exchangemodel", msg =>
54             {
55                 Console.WriteLine($"订阅到消息:{msg}");
56             });
57             #endregion
58             Console.ReadLine();
59         }
60     }
61 }
62 
63 //订阅者后端的逻辑
64  public static void SubscriberExchangeModel(string exchangeName, Action<string> handlerMsg = null)
65         {
66             var connection = connectionFactory.CreateConnection();
67             var channel = connection.CreateModel();
68 
69             channel.ExchangeDeclare(exchange: exchangeName, type: ExchangeType.Fanout);//Fanout 扇形分叉
70 
71             var queueName = channel.QueueDeclare().QueueName;
72             channel.QueueBind(queue: queueName,
73                               exchange: exchangeName,
74                               routingKey: "");
75 
76             Console.WriteLine(" Waiting for msg....");
77 
78             var consumer = new EventingBasicConsumer(channel);
79             consumer.Received += (model, ea) =>
80             {
81                 var body = ea.Body.ToArray();
82                 var message = Encoding.UTF8.GetString(body);
83                 if (handlerMsg != null)
84                 {
85                     if (!string.IsNullOrEmpty(message))
86                     {
87                         handlerMsg.Invoke(message);
88                     }
89                 }
90                 else
91                 {
92                     Console.WriteLine($"订阅到消息:{message}");
93                 }
94             };
95             channel.BasicConsume(queue: queueName,  autoAck: true, consumer: consumer);
96         }

9:Direct

1734768 20201016155424615 1663603943 - C#使用RabbitMq队列(Sample,Work,Fanout,Direct等模式的简单使用)

 

 

1734768 20201016155434065 1466838982 - C#使用RabbitMq队列(Sample,Work,Fanout,Direct等模式的简单使用)

 1734768 20201016155443078 1718249592 - C#使用RabbitMq队列(Sample,Work,Fanout,Direct等模式的简单使用)

Code:

  1 //发布者
  2 using System;
  3 
  4 namespace RabbitMqPublishDemo
  5 {
  6     using MyRabbitMqService;
  7     using System.Runtime.CompilerServices;
  8 
  9     class Program
 10     {
 11         static void Main(string[] args)
 12         {
 13             #region 发布订阅 交换机路由模式 Direct
 14             string routerKeyValue = args[0].Split("=")[1];//如 abc.exe --name='qq'
 15             Console.WriteLine("开始发布中。。。");
 16             for (int i = 0; i < 20; i++)
 17             {
 18                 string msg = $"小明有{i}只宝剑";
 19                 ZrfRabbitMqHelper.ExchangeRoutersByDirectModelPublish(msg, routerKey: routerKeyValue);
 20 
 21                 //下面的为固定的写法
 22                 //ZrfRabbitMqHelper.ExchangeRoutersByDirectModelPublish(msg);
 23                 //ZrfRabbitMqHelper.ExchangeRoutersByDirectModelPublish($"你好我好大家好{i}", routerKey:"onlylog");
 24             }
 25             Console.WriteLine("这次发布完毕。。。");
 26             #endregion
 27             Console.ReadLine();
 28         }
 29     }
 30 }
 31 
 32 //发布者后端逻辑 发布订阅的路由模式 Direct
 33         /// <summary>
 34         /// 发布 Direct 路由模式 Direct
 35         /// </summary>
 36         /// <param name="message"></param>
 37         /// <param name="exchangeName"></param>
 38         /// <param name="routerKey"></param>
 39         public static void ExchangeRoutersByDirectModelPublish(string message, string exchangeName = "qqai", string routerKey = "insertToStudent")
 40         {
 41             using (IConnection connection = connectionFactory.CreateConnection())
 42             {
 43                 using (IModel channelmodel = connection.CreateModel())
 44                 {
 45                     channelmodel.ExchangeDeclare(exchange: exchangeName, type: ExchangeType.Direct);
 46                     byte[] bymsg = Encoding.UTF8.GetBytes(message);
 47                     channelmodel.BasicPublish(exchange: exchangeName, routingKey: routerKey, body: bymsg);
 48 
 49                     // ​byte[] bytemsg = Encoding.UTF8.GetBytes(message);
 50                     //  ​channelmodel.BasicPublish(exchange: exchangeName,routingKey: routerKey,basicProperties: null,body: bytemsg);
 51                 }
 52             }
 53         }
 54         
 55 //订阅者 Exchange Router路由 Director
 56 using System;
 57 
 58 namespace RabbitMqConsumerDemo
 59 {
 60     using MyRabbitMqService;
 61     using System.Runtime.InteropServices;
 62 
 63     class Program
 64     {
 65         static void Main(string[] args)
 66         {
 67             Console.WriteLine("开始消费中。。!");
 68             if (args.Length > 0)
 69             {
 70                 string routerKeyValue = args[0].Split("=")[1];
 71                 Console.WriteLine($"routerKey=>{routerKeyValue}");
 72                 if (!string.IsNullOrEmpty(routerKeyValue))
 73                     ZrfRabbitMqHelper.ExchangeRoutersByDirectModelConsumer(routerKey: routerKeyValue, handler: msg =>
 74                     {
 75                         Console.WriteLine($"拿到消息:{msg}");
 76                     });
 77                 else
 78                     Console.WriteLine("没有获取到routerKey !");
 79             }
 80             //else
 81             //{
 82             //    ZrfRabbitMqHelper.ExchangeRoutersByDirectModelConsumer(handler: msg =>
 83             //    {
 84             //        Console.WriteLine($"拿到消息:{msg}");
 85             //    });
 86             //}
 87             Console.ReadLine();
 88         }
 89     }
 90 }
 91 
 92 //订阅者 Exchange Router路由 Director 后端逻辑
 93        public static void ExchangeRoutersByDirectModelConsumer(string exchangeName = "qqai", string routerKey = "insertToStudent", Action<string> handler = null)
 94         {
 95             var connection = connectionFactory.CreateConnection();
 96             var channel = connection.CreateModel();
 97             channel.ExchangeDeclare(exchange: exchangeName, type: ExchangeType.Direct);
 98             var queueName = channel.QueueDeclare().QueueName;
 99             channel.QueueBind(queue: queueName, exchange: exchangeName, routingKey: routerKey);
100 
101             Console.WriteLine("wating for message...!");
102             var consumer = new EventingBasicConsumer(channel);
103             //(object sender, BasicDeliverEventArgs e)
104             consumer.Received += (sender, e) =>
105             {
106                 var bytedata = e.Body.ToArray();
107                 var getRoutekey = e.RoutingKey;
108                 string msg = Encoding.UTF8.GetString(bytedata);
109                 if (handler != null)
110                     handler.Invoke(msg);
111                 else
112                     Console.WriteLine($"路由{getRoutekey},订阅到消息{msg}!");
113             };
114             channel.BasicConsume(queue: queueName, autoAck: true, consumer);
115         }
116 

 需要完整的code,可以留言获取!

C#使用RabbitMq队列(Sample,Work,Fanout,Direct等模式的简单使用)

C#使用RabbitMq队列(Sample,Work,Fanout,Direct等模式的简单使用)插图

发表评论