RabbmitMq初步了解和创造连接

就算笔记写的再差,也要自己写, 写了感觉就是自己的,其他优秀的资料看到最多,感觉也不是自己的

第一步,创建连接和通道

第二步,声明交换机

channel.ExchangeDeclare(exchange: EXCHANGE_NAME, type: exchange_type);
 
public static void ExchangeDeclare(this IModel model, string exchange, string type, bool durable = false, bool autoDelete = false, IDictionary<string, object> arguments = null)
        {
            model.ExchangeDeclare(exchange, type, durable, autoDelete, arguments);
        }

声明方法的五个参数

 string exchange :名称

string type, 类型,参考我上一篇文章

bool durable ,是否持久化,durable设置为true表示持久化,反之是非持久化,持久化的可以将交换器存盘,在服务器重启的时候会从盘里重新加载数据,因此数据不会丢失 

bool autoDelete ,是否自动删除,设置为TRUE则表是自动删除,自删除的前提是至少有一个队列或者交换器与这交换器绑定,之后所有与这个交换器绑定的队列或者交换器都与此解绑,一般都设置为fase 

IDictionary<string, object> arguments ,alternate-exchange等一些结构化参数

第三步绑定队列

声明队列

 if (!IsFanout)
                {
                    this.channel.QueueDeclare(queue: queueName,
//队列名称
                                     durable: true,
//是否持久化, 队列的声明默认是存放到内存中的,如果rabbitmq重启会丢失,如果想重启之后还存在就要使队列持久化,保存到Erlang自带的Mnesia数据库中,当rabbitmq重启之后会读取该数据库
                                     exclusive: false,
//是否排外的,有两个作用,一:当连接关闭时connection.close()该队列是否会自动删除;二:该队列是否是私有的private,如果不是排外的,可以使用两个消费者都访问同一个队列,没有任何问题,如果是排外的,会对当前队列加锁,其他通道channel是不能访问的,如果强制访问会报异常:com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=405, reply-text=RESOURCE_LOCKED - cannot obtain exclusive access to locked queue 'queue_name' in vhost '/', class-id=50, method-id=20)一般等于true的话用于一个队列只能有一个消费者来消费的场景
                                     autoDelete: false,
//是否自动删除,当最后一个消费者断开连接之后队列是否自动被删除,可以通过RabbitMQ Management,查看某个队列的消费者数量,当consumers = 0时队列就会自动删除
                                     arguments: null);
//队列中的消息什么时候会自动被删除?
                }
                else
                {
                    queueName = channel.QueueDeclare().QueueName;
                    routingKey = "";
                }

绑定队列 

  public static void QueueBind(this IModel model, string queue, string exchange, string routingKey, IDictionary<string, object> arguments = null)
        {
            model.QueueBind(queue, exchange, routingKey, arguments);
        }

queue:队列名
exchange:交换机
routingKey:路由key
arguments 

 

 

 第四步 流量设置

  void BasicQos(uint prefetchSize, ushort prefetchCount, bool global);

配置Basic内容类的QoS参数。
第一个参数是可接收消息的大小的  0不受限制
第二个参数是处理消息最大的数量  1 那如果接收一个消息,但是没有应答,则客户端不会收到下一个消息,消息只会在队列中阻塞
第三个参数则设置了是不是针对整个Connection的,因为一个Connection可以有多个Channel,如果是false则说明只是针对于这个Channel的。
 basic.qos是针对channel进行设置的,也就是说只有在channel建立之后才能发送basic.qos信令。

在rabbitmq的实现中,每个channel都对应会有一个rabbit_limiter进程,当收到basic.qos信令后,在rabbit_limiter进程中记录信令中prefetch_count的值,同时记录的还有该channel未ack的消息个数。

第五步,发送者类型

// 1种  
EventingBasicConsumer consumer = new EventingBasicConsumer(this.channel);
// 2.种 
BasicGetResult result = channel.BasicGet(queue:"routingKey",autoAck:true);


EventingBasicConsumer是基于长连接,发布订阅模式的消费方式,节省资源且实时性好,这是开发中最常用的消费模式。
在一些需要消费者主动获取消息的场合,我们可以使用Get方式,Get方式是基于短连接的,请求响应模式的消费方式,也就是说只有消费者这边主动请求时才获取数据

 第六步 处理接收到的信息


// 订阅事件
 consumer.Received += (model, bdea) =>
                {
                  
                };

第七步,消费者处理

 public static string BasicConsume(this IModel model, string queue, bool autoAck, IBasicConsumer consumer)
        {
            return model.BasicConsume(queue, autoAck, "", noLocal: false, exclusive: false, null, consumer);
        }

queue 队列名

autoAck 是否自动确认消息,true自动确认,false 不自动要手动调用,建立设置为false
consumer 发送者方式

具体实现 

  //  Func<RbtMessage, bool> func,
        public void BindReceiveMqMsg(Func<RbtMessage, bool> func, ICallbackFunction function, string routingKey, string EXCHANGE_NAME = null, string exchange_type = null)
        {
            try
            {

                

                //创建与指定端点的连接。
                connection = RbtMQConnection._connectionFactory.CreateConnection();
                //创建并返回新的频道,会话和模型。
                channel = connection.CreateModel();

                bool IsFanout = false;//广播方式
                if (exchange_type == ExchangeType.Fanout)
                {
                    //广播方式
                    IsFanout = true;
                    EXCHANGE_NAME = EXCHANGE_NAME ?? "mst_exchange_fanout";
                }
                else
                {
                    EXCHANGE_NAME = EXCHANGE_NAME ?? "mst_exchange_topic";
                    exchange_type = ExchangeType.Topic;
                }

                channel.ExchangeDeclare(exchange: EXCHANGE_NAME, type: exchange_type);

                if (!IsFanout)
                {
                    this.channel.QueueDeclare(queue: routingKey,//队列名称
                                     durable: true,
                                     arguments: null);
                }
                else
                {
                    routingKey = channel.QueueDeclare().QueueName;
                        
                }
                channel.QueueBind(routingKey, EXCHANGE_NAME, IsFanout ? EXCHANGE_NAME : "");


               
                EventingBasicConsumer consumer = new EventingBasicConsumer(this.channel);
              
                consumer.Received += (model, bdea) =>
                {
                    byte[] body = bdea.Body.ToArray();
                    string message = Encoding.UTF8.GetString(body);
                    if (message == null || message.Length == 0)
                    {
                        this.channel.BasicAck(deliveryTag: bdea.DeliveryTag, multiple: false);
                        return;
                    }

                    RbtMessage mqMsg = JsonConvert.DeserializeObject<RbtMessage>(message);

                    function.ProcessMsgAsync(mqMsg);
                  
                    bool result = true;
                    if (func != null)
                    {
                        result = func(mqMsg);
                    }
                    if (result)
                    {
                     
                        channel.BasicAck(deliveryTag: bdea.DeliveryTag, multiple: false);
                    }
                };
                channel.BasicConsume(queue: routingKey, autoAck: false, consumer: consumer);

            }
            catch (Exception ex)
            {
                // MstCore.Pub.MstPub.Logs("RabbitMQ出错:" + ex.ToString());
            }
        }

rabbmitmq能写的还有很多,但工作的原因,怕不写就忘了,而且现在也只是了解调的阶段。所以虽然笔记是流水账,也要记录下来

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值