示例#1
0
        /// <summary>
        /// 订阅消息
        /// </summary>
        /// <param name="receiveMessageFun">接收消息回调</param>
        /// <param name="isAutoAck">是否自动应答,如果为否,则需要在回调里返回true</param>
        public void Subscribe(Func <byte[], bool> receiveMessageFun, bool isAutoAck = false)
        {
            if (receiveMessageFun == null)
            {
                return;
            }
            var consumer = new EventingBasicConsumer(channel);

            consumer.Received += (o, e) =>
            {
                if (e.Body.IsEmpty)
                {
                    // 如果自动回答,则什么都不用干
                    if (isAutoAck)
                    {
                        return;
                    }
                    channel.BasicAck(e.DeliveryTag, false);
                    return;
                }

                bool   isAck  = true;
                string logMsg = $"{GetLogTitleMsg()}.接收到消息";
                log.DebugAsync(logMsg, null, tags: GetLogTags());

                var data = e.Body.ToArray();
                try
                {
                    isAck = receiveMessageFun(data);
                }
                catch (Exception ex)
                {
                    var busEx = AmqpUtil.BuilderBusinessException(ex, $"字节数组数据转换为Base64:{Convert.ToBase64String(data)}", amqpQueue, log, ex.Message);
                    isAck = ExceptionHandle.Handle(busEx);

                    logMsg = $"{GetLogTitleMsg()}.输入参数isAutoAck:{isAutoAck},业务处理发生异常(返回应答为{isAck})";
                    log.ErrorAsync(logMsg, ex, tags: GetLogTags());
                }

                // 如果自动回答,则什么都不用干
                if (isAutoAck)
                {
                    return;
                }

                // 如果业务端返回应答,则返回MQ已成功处理,否则返回未处理成功,需要将该消息放回队列进行重试
                if (isAck)
                {
                    channel.BasicAck(e.DeliveryTag, false);
                }
                else
                {
                    channel.BasicNack(e.DeliveryTag, false, true);
                }
            };

            channel.BasicConsume(amqpQueue.Queue.Name, isAutoAck, consumer);
        }
示例#2
0
        /// <summary>
        /// 订阅消息
        /// </summary>
        /// <param name="receiveMessageFun">接收消息回调</param>
        /// <param name="receiveMessageType">接收消息类型</param>
        /// <param name="isAutoAck">是否自动应答,如果为否,则需要在回调里返回true</param>
        public void Subscribe(Func <object, bool> receiveMessageFun, Type receiveMessageType, bool isAutoAck = false)
        {
            if (receiveMessageFun == null)
            {
                return;
            }
            Subscribe((byte[] x) =>
            {
                object data = null;
                try
                {
                    data = BytesSerialization.Deserialize(x, receiveMessageType);
                }
                catch (MessagePackSerializationException)
                {
                    // 如果messagepack反序列失败,则使用json反列化
                    try
                    {
                        data = jsonSerialization.Deserialize(x, receiveMessageType);
                    }
                    catch (Exception ex)
                    {
                        string logMsg = $"{GetLogTitleMsg()}.输入参数isAutoAck:{isAutoAck},jsonSerialization.Deserialize发生异常(返回应答为true),认为是不符合业务规范的数据,应删除消息";
                        log.ErrorAsync(logMsg, ex, tags: GetLogTags());

                        // 反序列异常则返回true
                        return(true);
                    }
                }
                catch (Exception ex)
                {
                    string logMsg = $"{GetLogTitleMsg()}.输入参数isAutoAck:{isAutoAck},BytesSerialization.Deserialize发生异常(返回应答为true),认为是不符合业务规范的数据,应删除消息";
                    log.ErrorAsync(logMsg, ex, tags: GetLogTags());

                    // 反序列异常则返回true
                    return(true);
                }

                try
                {
                    return(receiveMessageFun(data));
                }
                catch (Exception ex)
                {
                    var busEx = AmqpUtil.BuilderBusinessException(ex, data, amqpQueue, log, ex.Message);
                    var isAck = ExceptionHandle.Handle(busEx);

                    string logMsg = $"{GetLogTitleMsg()}.输入参数isAutoAck:{isAutoAck},业务处理发生异常(返回应答为{isAck})";
                    log.ErrorAsync(logMsg, ex, tags: GetLogTags());

                    return(isAck);
                }
            }, isAutoAck);
        }
 /// <summary>
 /// 构造方法
 /// </summary>
 /// <param name="amqpConfigReader">AMQP配置读取</param>
 /// <param name="connectionFactory">连接工厂</param>
 public AmqpRpcClientMethodBase(IAmqpConfigReader amqpConfigReader, IAmqpConnectionFactory connectionFactory)
 {
     if (amqpConfigReader == null)
     {
         this.amqpConfigReader = AmqpUtil.GetConfigReader(amqpConfigReader);
     }
     else
     {
         this.amqpConfigReader = amqpConfigReader;
     }
     this.connectionFactory = connectionFactory;
 }
示例#4
0
        /// <summary>
        /// 订阅消息
        /// </summary>
        /// <typeparam name="T">接收类型</typeparam>
        /// <param name="receiveMessageFun">接收消息回调</param>
        /// <param name="isAutoAck">是否自动应答,如果为否,则需要在回调里返回true</param>
        public void Subscribe <T>(Func <T, bool> receiveMessageFun, bool isAutoAck = false)
        {
            Subscribe((byte[] x) =>
            {
                if (receiveMessageFun != null)
                {
                    T data = default(T);
                    try
                    {
                        data = BytesSerialization.Deserialize <T>(x);
                    }
                    catch (Exception ex)
                    {
                        string logMsg = $"{GetLogTitleMsg()}.输入参数isAutoAck:{isAutoAck},BytesSerialization.Deserialize发生异常(返回应答为true),认为是不符合业务规范的数据,应删除消息";
                        log.ErrorAsync(logMsg, ex, tags: GetLogTags());

                        // 反序列异常则返回true
                        return(true);
                    }

                    try
                    {
                        return(receiveMessageFun(data));
                    }
                    catch (Exception ex)
                    {
                        var busEx = AmqpUtil.BuilderBusinessException(ex, data, amqpQueue, log, ex.Message);
                        var isAck = ExceptionHandle.Handle(busEx);

                        string logMsg = $"{GetLogTitleMsg()}.输入参数isAutoAck:{isAutoAck},业务处理发生异常(返回应答为{isAck})";
                        log.ErrorAsync(logMsg, ex, tags: GetLogTags());

                        return(isAck);
                    }
                }

                return(true);
            }, isAutoAck);
        }
示例#5
0
        /// <summary>
        /// 订阅消息
        /// </summary>
        /// <param name="receiveMessageFun">接收消息回调</param>
        /// <param name="isAutoAck">是否自动应答,如果为否,则需要在回调里返回true</param>
        public void Subscribe(Func <string, bool> receiveMessageFun, bool isAutoAck = false)
        {
            Subscribe((byte[] x) =>
            {
                if (receiveMessageFun != null)
                {
                    string msg = null;
                    try
                    {
                        msg = Encoding.UTF8.GetString(x);
                    }
                    catch (Exception ex)
                    {
                        string logMsg = $"{GetLogTitleMsg()}.输入参数isAutoAck:{isAutoAck},Encoding.UTF8.GetString发生异常,返回应答:true";
                        log.ErrorAsync(logMsg, ex, tags: GetLogTags());

                        return(true);
                    }

                    try
                    {
                        return(receiveMessageFun(msg));
                    }
                    catch (Exception ex)
                    {
                        var busEx = AmqpUtil.BuilderBusinessException(ex, msg, amqpQueue, log, ex.Message);
                        var isAck = ExceptionHandle.Handle(busEx);

                        string logMsg = $"{GetLogTitleMsg()}.输入参数isAutoAck:{isAutoAck},业务处理发生异常(返回应答为{isAck})";
                        log.ErrorAsync(logMsg, ex, tags: GetLogTags());

                        return(isAck);
                    }
                }

                return(true);
            }, isAutoAck);
        }
示例#6
0
        /// <summary>
        /// 接收消息
        /// </summary>
        /// <param name="receiveMessageFun">接收消息回调</param>
        public void Receive(Func <byte[], byte[]> receiveMessageFun)
        {
            channel.QueueDeclare(queue: amqpQueue.Queue.Name, durable: amqpQueue.Persistent, exclusive: false, autoDelete: amqpQueue.Queue.AutoDelQueue, arguments: null);
            if (amqpQueue.Queue.Qos != null)
            {
                channel.BasicQos(0, amqpQueue.Queue.Qos.GetValueOrDefault(), false);
            }

            channel.QueueBind(amqpQueue.Queue.Name, amqpQueue.ExchangeName, amqpQueue.Queue.Name);

            var consumer = new EventingBasicConsumer(channel);

            channel.BasicConsume(queue: amqpQueue.Queue.Name, autoAck: false, consumer: consumer);

            consumer.Received += (model, ea) =>
            {
                // 错误返回信息
                BasicReturnInfo errorReturn = null;

                // 返回给客户端的数据
                byte[] outData = null;

                // 关联ID
                string           correlationId = null;
                IBasicProperties props         = null;
                IBasicProperties replyProps    = null;
                try
                {
                    props      = ea.BasicProperties;
                    replyProps = channel.CreateBasicProperties();
                    replyProps.CorrelationId = props.CorrelationId;
                    correlationId            = props.CorrelationId;

                    byte[] inData = ea.Body.IsEmpty ? null : ea.Body.ToArray();
                    try
                    {
                        outData = receiveMessageFun(inData);
                    }
                    catch (Exception ex)
                    {
                        var busEx = AmqpUtil.BuilderBusinessException(ex, null, amqpQueue, log, ex.Message);
                        ExceptionHandle.Handle(busEx);

                        log.ErrorAsync("RpcServer回调业务处理出现异常", ex, typeof(RabbitRpcServer).Name, correlationId);

                        errorReturn = new BasicReturnInfo();
                        errorReturn.SetFailureMsg("业务处理出现异常", ex.Message);

                        outData = Encoding.UTF8.GetBytes(JsonUtil.SerializeIgnoreNull(errorReturn));
                    }
                }
                catch (Exception ex)
                {
                    log.ErrorAsync("RpcServer接收消息处理出现异常", ex, typeof(RabbitRpcServer).Name, correlationId);

                    errorReturn = new BasicReturnInfo();
                    errorReturn.SetFailureMsg("RpcServer接收消息处理出现异常", ex.Message);

                    outData = Encoding.UTF8.GetBytes(JsonUtil.SerializeIgnoreNull(errorReturn));
                }
                finally
                {
                    if (props != null && replyProps != null)
                    {
                        channel.BasicPublish(exchange: amqpQueue.ExchangeName, routingKey: props.ReplyTo, basicProperties: replyProps, body: outData);
                        channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);
                    }
                }
            };
        }
 /// <summary>
 /// 构造方法
 /// </summary>
 /// <param name="symmetricalEncryption">加密</param>
 /// <param name="appConfig">应用配置</param>
 /// <param name="amqpConfigReader">配置读取</param>
 public RabbitConnectionFactory(ISymmetricalEncryption symmetricalEncryption = null, IAppConfiguration appConfig = null, IAmqpConfigReader amqpConfigReader = null)
     : base(symmetricalEncryption, appConfig)
 {
     this.amqpConfigReader = AmqpUtil.GetConfigReader(amqpConfigReader);
 }