RabbitMq笔记(2)
今天收获不少,记个笔记。
1 namespace RabbitMQTest 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 Consumer(); 8 //Console.WriteLine("方法————{0}",Thread.CurrentThread.ManagedThreadId); 9 10 //Thread thread = new Thread(Consumer); 11 //thread.Start(); 12 //Console.WriteLine("线程1————{0}", Thread.CurrentThread.ManagedThreadId); 13 //Thread tt = new Thread( 14 // () => { 15 // Consumer(); 16 // } 17 // ); 18 //tt.Start(); 19 20 Task task = new Task(Consumer); 21 task.Start(); 22 23 TaskFactory tf = new TaskFactory(); 24 Task t = tf.StartNew(Consumer); 25 //Console.WriteLine("线程2————{0}", Thread.CurrentThread.ManagedThreadId); 26 Console.ReadLine(); 27 } 28 29 private static void Consumer() 30 { 31 Console.WriteLine("线程开始,ID:" + Thread.CurrentThread.ManagedThreadId); 32 var factory = new ConnectionFactory() { HostName = "localhost" }; 33 using (var connection = factory.CreateConnection()) 34 using (var channel = connection.CreateModel()) 35 { 36 //声明queue 37 channel.QueueDeclare(queue: "hellos",//队列名 38 durable: false,//是否持久化 39 exclusive: false,//true:排他性,该队列仅对首次申明它的连接可见,并在连接断开时自动删除 40 autoDelete: false,//true:如果该队列没有任何订阅的消费者的话,该队列会被自动删除 41 arguments: null);//如果安装了队列优先级插件则可以设置优先级 42 43 string message = "Hello World!";//待发送的消息 44 var body = Encoding.UTF8.GetBytes(message); 45 for (int i = 0; i < 5; i++) 46 { 47 channel.BasicPublish(exchange: "",//exchange名称 48 routingKey: "hellos",//如果存在exchange,则消息被发送到名称为hello的queue的客户端 49 basicProperties: null, 50 body: body);//消息体 51 Console.WriteLine(" [x] Sent {0}", message); 52 } 53 } 54 } 55 } 56 }
1 namespace RabbitXiaoFei 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 //var factory = new ConnectionFactory() { HostName = "localhost", UserName = "ty2017", Password = "123456", VirtualHost = "log" }; 8 var factory = new ConnectionFactory() { HostName = "localhost" }; 9 using (var connection = factory.CreateConnection()) 10 using (var channel = connection.CreateModel()) 11 { 12 channel.QueueDeclare(queue: "hellos",//指定发送消息的queue,和生产者的queue匹配 13 durable: false,//耐用的,持久的 14 exclusive: false,//独有的;排外的;专一的 15 autoDelete: false,// 16 arguments: null); 17 18 //设置预取消息的数量为1个,消费完当前的消息后再去获取下一个消息 19 //就是有多个消费者去请求队列的时候,序号为奇数的会给第一个,为偶数的会给第二个 20 //但是如果第一个要耗费很长时间,那么第二个就得等,那就很消耗资源了 21 //要是每个Consumer处理完一个消息后再去获取下一个消息,这是多么理想呀! 22 channel.BasicQos(0, //设置0 23 1, //设置当前Consumer的预取数量为1个就行啦! 24 false); //设置false 25 26 var consumer = new EventingBasicConsumer(channel); 27 //注册接收事件,一旦创建连接就去拉取消息 28 consumer.Received += (obj, sss) => 29 { 30 var body = sss.Body; 31 var message = Encoding.UTF8.GetString(body); 32 Console.WriteLine(" [x] Received {0}", message); 33 }; 34 channel.BasicConsume(queue: "hellos", 35 autoAck:true,//Ack :确认 36 //和tcp协议的ack一样,为false则服务端必须在收到客户端的回执(ack)后才能删除本条消息 37 consumer: consumer); 38 Console.WriteLine(" Press [enter] to exit."); 39 Console.ReadLine(); 40 } 41 } 42 } 43 }
New 生产者
ConnectionFactory factory = new ConnectionFactory { UserName = "guest",//用户名 Password = "guest",//密码 HostName = "127.0.0.1",//rabbitmq ip //VirtualHost = "/" }; //创建连接 var connection = factory.CreateConnection(); //创建通道 var channel = connection.CreateModel(); //声明一个队列 (队列名字,是否持久化,是否自动删除队列,是否排外的,是否等待服务器返回) channel.QueueDeclare("queuename_zkb", false, false, false, null); Guid guid = new Guid(); var sendBytes = Encoding.UTF8.GetBytes(guid.ToString()); //发布消息 (交换器名称,路由键,是否为强制性, channel.BasicPublish("", "queuename_zkb", null, sendBytes); channel.Close(); connection.Close();
New 消费者
IConnectionFactory connFactory = new ConnectionFactory//创建连接工厂对象 { HostName = "127.0.0.1",//IP地址 //Port = 5672,//端口号 UserName = "guest",//用户账号 Password = "guest"//用户密码 }; using (IConnection conn = connFactory.CreateConnection()) { using (IModel channel = conn.CreateModel()) { String queueName = String.Empty; queueName = "queuename_zkb"; //声明一个队列 channel.QueueDeclare( queue: queueName,//消息队列名称 durable: false,//是否缓存 exclusive: false, autoDelete: false, arguments: null ); //创建消费者对象 var consumer = new EventingBasicConsumer(channel); consumer.Received += (model, ea) => { byte[] message = ea.Body;//接收到的消息 Console.WriteLine("接收到信息为:" + Encoding.UTF8.GetString(message)); ViewData["1212"] = Encoding.UTF8.GetString(message); //_logger.LogError("我是错误显示") }; //消费者开启监听 channel.BasicConsume(queue: queueName, autoAck: true, consumer: consumer); } }
这个是在多个消费者的时候用到的,假如发给A消费,那就发一条给他,然后收到A的确认消息时候,在发给n消费者。一定是收到A的确认消息
下面的这张图,这样就变成了:公平分发⭐⭐⭐⭐(不加这些code的是轮询分发)
假如来了一批活需要1和2处理,2的能力比1强,那么这两个消费者就都是每次只取一条信息,但是2的能力强,2就做的多,这也叫能者多劳
关于ConnectionFactory
看了几个用到ConnectionFactory这个类的项目,和在网上看的几个博客,都是与队列这样的需要提供HostUrl,username,pwd等等因素。
所以应该就是将这些打包进行链接而已。
public class RabbitBasic { public ConnectionFactory Factory; public RabbitBasic() { string host = System.Configuration.ConfigurationManager.AppSettings.Get("RabbitMQHost"); string pwd = System.Configuration.ConfigurationManager.AppSettings.Get("RabbitMQPwd"); string username = System.Configuration.ConfigurationManager.AppSettings.Get("RabbitMQUserName"); string vhost = System.Configuration.ConfigurationManager.AppSettings.Get("RabbitMQVirtualHost"); //实例化连接工厂 Factory = new ConnectionFactory() { HostName = host, Password = pwd, UserName = username, VirtualHost = vhost, }; } }
public class RabbitReceiver : RabbitBasic { public void Start() { var connection = Factory.CreateConnection();//这里就是已经链接上了RabbitMQ var channel = connection.CreateModel(); channel.QueueDeclare(queue: PickRelease, durable: true, exclusive: false, autoDelete: false, arguments: null); channel.BasicQos(0, 1, false);
}
}
这个RabbitReceiver就是继承了RabbitBasic这个类,就是可以使用父类中的Factory这个类。
拿来就可以用,这样这里就不用再写链接Rabbit的那一套操作了。
说白了,就是一个多个参数的链接对象进行下封装。
被继承的拿来用就好了。
注:一般链接数据库的那种字符串,一般就是直接一个字符串直接干。
RabbitMQ消息超时时间、队列消息超时时间、队列超时时间
人各有命,上天注定,有人天生为王,有人落草为寇。脚下的路,如果不是你自己的选择,那么旅程的终点在哪,也没人知道。你会走到哪,会遇到谁,都不一定。