public ConsumerExecutionContext( Func <byte[], MessageProperties, MessageReceivedInfo, Task> onMessageHandler, MessageReceivedInfo info, MessageProperties properties, byte[] body, IBasicConsumer consumer) { Preconditions.CheckNotNull(onMessageHandler, "userHandler"); Preconditions.CheckNotNull(info, "info"); Preconditions.CheckNotNull(properties, "properties"); Preconditions.CheckNotNull(body, "body"); Preconditions.CheckNotNull(consumer, "consumer"); OnMessageHandler = onMessageHandler; Info = info; Properties = properties; Body = body; Consumer = consumer; }
/// <summary> /// 发布(执行),等同于 执行Onclick方法(执行委托所关联的方法) /// 生产者发布带有事务确认的操作 /// 正确理解的理解方式是,通道(model)要执行的方法,相当于model.pubishAction()。此处分开写了,model一个参数,publishAction一个参数。 /// </summary> /// <param name="model">通道对象</param> /// <param name="publishAction">要执行的方法,参数就是model通道。</param> /// <returns></returns> public override void Publish(IModel model, byte[] body, MessageProperties messageProperties, Action <IModel, byte[], MessageProperties> publishAction) { base.SetModel(model); ulong sequenceNumber = model.NextPublishSeqNo; Timer timer = null; timer = new Timer(state => { //改为记录日志的方式处理超时结果。wangyunpeng。2017-8-24 (state as Timer).Dispose(); this._dictionary.Remove(sequenceNumber); ConsoleLogger.ErrorWrite("生产者发布消息超时。 序列号: {0}", sequenceNumber); EventBus.Instance.Publish(new ConfirmedMessageTimeOutEvent(body, messageProperties, new MessageConfirmedTimeOutInfo(sequenceNumber, string.Format("生产者确认超时后,{0}秒后等待来自序列号为{1}的ACK或NACK ", this._timeoutSeconds, sequenceNumber)))); }, timer, this._timeoutSeconds * 1000, Timeout.Infinite); //在执行生产者发布消息之前,增加对这个消息的事务操作,包括事务成功和事务失败的处理。 this._dictionary.Add(sequenceNumber, new ConfirmActions { OnAck = () => { timer.Dispose(); ConsoleLogger.InfoWrite("生产者发布的消息通过服务器的确认。序列号: {0}", sequenceNumber); EventBus.Instance.Publish(new ConfirmedMessageEvent(body, messageProperties, new MessageConfirmedInfo(sequenceNumber, true))); }, OnNack = () => { timer.Dispose(); ConsoleLogger.ErrorWrite("生产者发布的消息未通过服务器的确认。序列号: {0}", sequenceNumber); EventBus.Instance.Publish(new ConfirmedMessageEvent(body, messageProperties, new MessageConfirmedInfo(sequenceNumber, false))); }, Cancel = () => timer.Dispose(), Body = body, MessageProperties = messageProperties, PublishAction = publishAction }); publishAction(model, body, messageProperties);//真正执行生产者发布消息的操作。RabbitAdvancedBus.Publish.cs文件this._publisher.Publish(......) }
/// <summary> /// 消费者处理交付。IBasicConsumer接口自动完成调用。 /// </summary> /// <param name="consumerTag"></param> /// <param name="deliveryTag"></param> /// <param name="redelivered"></param> /// <param name="exchange"></param> /// <param name="routingKey"></param> /// <param name="properties"></param> /// <param name="body"></param> public void HandleBasicDeliver(string consumerTag, ulong deliveryTag, bool redelivered, string exchange, string routingKey, IBasicProperties properties, byte[] body) { ConsoleLogger.DebugWrite("HandleBasicDeliver on consumer: {0}, deliveryTag: {1}", consumerTag, deliveryTag); if (this._disposed) { // this message's consumer has stopped, so just return ConsoleLogger.InfoWrite("Consumer has stopped running. Consumer '{0}' on queue '{1}'. Ignoring message", this.ConsumerTag, queue.Name); return; } if (this._onMessage == null) { ConsoleLogger.ErrorWrite("User consumer callback, 'onMessage' has not been set for consumer '{0}'. Please call InternalConsumer.StartConsuming before passing the consumer to basic.consume", this.ConsumerTag); return; } var messageReceivedInfo = new MessageReceivedInfo(consumerTag, deliveryTag, redelivered, exchange, routingKey, queue.Name); var messsageProperties = new MessageProperties(properties); var context = new ConsumerExecutionContext(this._onMessage, messageReceivedInfo, messsageProperties, body, this); this._consumerDispatcher.QueueAction(() => this._handlerRunner.InvokeOnMessageHandler(context)); }
/// <summary> /// 发布消息 /// </summary> /// <param name="exchange"></param> /// <param name="routingKey"></param> /// <param name="mandatory">当mandatory标志位设置为true时,如果exchange根据自身类型和消息routeKey无法找到一个符合条件的queue,那么会调用basic.return方法将消息返还给生产者;当mandatory设为false时,出现上述情形broker会直接将消息扔掉。</param> /// <param name="immediate">当immediate标志位设置为true时,如果exchange在将消息route到queue(s)时发现对应的queue上没有消费者,那么这条消息不会放入队列中。当与消息routeKey关联的所有queue(一个或多个)都没有消费者时,该消息会通过basic.return方法返还给生产者。</param> /// <param name="messageProperties"></param> /// <param name="body"></param> /// <returns></returns> public void Publish(IExchange exchange, string routingKey, bool mandatory, bool immediate, MessageProperties messageProperties, byte[] body) { Preconditions.CheckNotNull(exchange, "exchange"); this.Publish(exchange.Name, routingKey, mandatory, immediate, messageProperties, body); }
/// <summary> /// 发布消息 /// </summary> /// <param name="exchange"></param> /// <param name="routingKey"></param> /// <param name="messageProperties"></param> /// <param name="body"></param> public void Publish(IExchange exchange, string routingKey, MessageProperties messageProperties, byte[] body) { this.Publish(exchange, routingKey, false, false, messageProperties, body); }
/// <summary> /// 发布消息 /// http://www.sjsjw.com/kf_jiagou/article/023563ABA032194.asp /// </summary> /// <param name="exchange"></param> /// <param name="routingKey"></param> /// <param name="mandatory">当mandatory标志位设置为true时,如果exchange根据自身类型和消息routeKey无法找到一个符合条件的queue,那么会调用basic.return方法将消息返还给生产者;当mandatory设为false时,出现上述情形broker会直接将消息扔掉。</param> /// <param name="immediate">当immediate标志位设置为true时,如果exchange在将消息route到queue(s)时发现对应的queue上没有消费者,那么这条消息不会放入队列中。当与消息routeKey关联的所有queue(一个或多个)都没有消费者时,该消息会通过basic.return方法返还给生产者。</param> /// <param name="messageProperties"></param> /// <param name="body"></param> /// <returns></returns> private void PublishAsync(string exchange, string routingKey, bool mandatory, bool immediate, MessageProperties messageProperties, byte[] body) { Preconditions.CheckNotNull(exchange, "exchange"); Preconditions.CheckShortString(routingKey, "routingKey"); Preconditions.CheckNotNull(body, "body"); this._clientCommandDispatcher.Invoke(x => { IBasicProperties basicProperties = null; if (messageProperties != null) { basicProperties = x.CreateBasicProperties(); messageProperties.CopyTo(basicProperties); } this._publisher.Publish(x, body, messageProperties, (m, b, p) => m.BasicPublish(exchange, routingKey, mandatory, immediate, basicProperties, body)); }).Wait(); ConsoleLogger.DebugWrite("Published to exchange: '{0}', routing key: '{1}', correlationId: '{2}'", exchange, routingKey, messageProperties == null ? "null" : messageProperties.CorrelationId); }
/// <summary> /// 发布消息 /// </summary> /// <param name="exchange"></param> /// <param name="routingKey"></param> /// <param name="mandatory">当mandatory标志位设置为true时,如果exchange根据自身类型和消息routeKey无法找到一个符合条件的queue,那么会调用basic.return方法将消息返还给生产者;当mandatory设为false时,出现上述情形broker会直接将消息扔掉。</param> /// <param name="immediate">当immediate标志位设置为true时,如果exchange在将消息route到queue(s)时发现对应的queue上没有消费者,那么这条消息不会放入队列中。当与消息routeKey关联的所有queue(一个或多个)都没有消费者时,该消息会通过basic.return方法返还给生产者。</param> /// <param name="messageProperties"></param> /// <param name="body"></param> public void Publish(string exchange, string routingKey, bool mandatory, bool immediate, MessageProperties messageProperties, byte[] body) { try { this.PublishAsync(exchange, routingKey, mandatory, immediate, messageProperties, body); } catch (AggregateException aggregateException) { throw aggregateException.InnerException; } }
/// <summary> /// 发布(执行),等同于 执行Onclick方法(执行委托所关联的方法) /// 正确理解的理解方式是,通道(model)要执行的方法,相当于model.pubishAction()。此处分开写了,model一个参数,publishAction一个参数。 /// </summary> /// <param name="model">通道对象</param> /// <param name="publishAction">要执行的方法,参数就是model通道。</param> /// <returns></returns> public override void Publish(IModel model, byte[] body, MessageProperties messageProperties, Action <IModel, byte[], MessageProperties> publishAction) { base.SetModel(model); publishAction(model, body, messageProperties); }
/// <summary> /// 发布(执行),等同于 执行Onclick方法(执行委托所关联的方法) /// 正确理解的理解方式是,通道(model)要执行的方法,相当于model.pubishAction()。此处分开写了,model一个参数,publishAction一个参数。 /// </summary> /// <param name="model">通道对象</param> /// <param name="publishAction">要执行的方法,参数就是model通道。</param> /// <returns></returns> public abstract void Publish(IModel model, byte[] body, MessageProperties messageProperties, Action <IModel, byte[], MessageProperties> publishAction);