C# EasyNetQ-如何重试失败的消息&;是否在邮件正文/标题中保留RetryCount?

C# EasyNetQ-如何重试失败的消息&;是否在邮件正文/标题中保留RetryCount?,c#,error-handling,rabbitmq,message-queue,easynetq,C#,Error Handling,Rabbitmq,Message Queue,Easynetq,我正在使用EasyNetQ,需要在原始队列上重试失败的消息。问题是:即使我成功地增加了TriedCount变量(在每个消息体中),当EasyNetQ在异常后将消息发布到默认错误队列时,更新的TriedCount不在消息体中!可能是因为它只是将原始消息转储到错误队列中,而没有使用者的更改 更新的TriedCount适用于正在进行的重新发布,但在通过EasyNetQ软管或EasyNetQ管理客户端重新发布时不起作用。生成的文本文件没有更新TriedCount public interface IMs

我正在使用EasyNetQ,需要在原始队列上重试失败的消息。问题是:即使我成功地增加了TriedCount变量(在每个消息体中),当EasyNetQ在异常后将消息发布到默认错误队列时,更新的TriedCount不在消息体中!可能是因为它只是将原始消息转储到错误队列中,而没有使用者的更改

更新的TriedCount适用于正在进行的重新发布,但在通过EasyNetQ软管或EasyNetQ管理客户端重新发布时不起作用。生成的文本文件没有更新TriedCount

public interface IMsgHandler<T> where T: class, IMessageType
{
    Task InvokeMsgCallbackFunc(T msg);
    Func<T, Task> MsgCallbackFunc { get; set; }
    bool IsTryValid(T msg, string refSubscriptionId); // Calls callback only 
                                                      // if Retry is valid
}

public interface IMessageType
{
    int MsgTypeId { get; }

    Dictionary<string, TryInfo> MsgTryInfo {get; set;}

}

public class TryInfo
{   
    public int TriedCount { get; set; }

    /*Other information regarding msg attempt*/
}

public bool SubscribeAsync<T>(Func<T, Task> eventHandler, string subscriptionId)
{
    IMsgHandler<T> currMsgHandler = new MsgHandler<T>(eventHandler, subscriptionId);
    // Using the msgHandler allows to add a mediator between EasyNetQ and the actual callback function
    // The mediator can transmit the retried msg or choose to ignore it
    return _defaultBus.SubscribeAsync<T>(subscriptionId, currMsgHandler.InvokeMsgCallbackFunc).Queue != null;
}
这可以工作,但只会再次发布到错误队列,而不会发布到原始队列。另外,我不知道在这个阶段如何在消息体中添加/更新重试信息

我已经浏览了库以向消息添加标题,但我不知道正文中的计数是否没有更新,标题中的计数如何更新/为什么更新


有没有办法不借助高级总线(在这种情况下,我可能会使用RabbitMQ.Net客户机本身)来持久化TriedCount?

为了防止它对其他人有帮助,我最终实现了我自己的(而不是实现整个系统,这似乎是一种过激行为)。我之所以在正文(而不是标题)中添加重试信息,是因为EasyNetQ不处理标题中的复杂类型(无论如何都不是现成的)。因此,使用字典可以为不同的消费者提供更多的控制。我在创建总线时注册自定义序列化程序,如下所示:

_defaultBus = RabbitHutch.CreateBus(currentConnString, serviceRegister => serviceRegister.Register<IErrorMessageSerializer>(serviceProvider => new RetryEnabledErrorMessageSerializer<IMessageType>(givenSubscriptionId)));
\u defaultBus=RabbitHutch.CreateBus(currentConnString,serviceRegister=>serviceRegister.Register(serviceProvider=>new-RetryEnabledErrorMessageSerializer(givenSubscriptionId));
刚刚实现了Serialize方法,如下所示:

 public class RetryEnabledErrorMessageSerializer<T> : IErrorMessageSerializer where T : class, IMessageType
 {
        public string Serialize(byte[] messageBody)
        {
             string stringifiedMsgBody = Encoding.UTF8.GetString(messageBody);
             var objectifiedMsgBody = JObject.Parse(stringifiedMsgBody);

             // Add/update RetryInformation into objectifiedMsgBody here
             // I have a dictionary that saves <key:consumerId, val: TryInfoObj>

             return JsonConvert.SerializeObject(objectifiedMsgBody);
        }
  }
public类RetryEnabledErrorMessageSerializer:IErrorMessageSerializer其中T:class,IMessageType
{
公共字符串序列化(字节[]messageBody)
{
string stringifiedMsgBody=Encoding.UTF8.GetString(messageBody);
var objectifiedsgbody=JObject.Parse(stringifiedMsgBody);
//在ObjectiveDMSGBody中添加/更新重试信息
//我有一本节省时间的字典
返回JsonConvert.SerializeObject(ObjectiveIDSGBody);
}
}
实际重试由简单的控制台应用程序/windows服务通过EasyNetQ管理API定期完成:

            var client = new ManagementClient(AppConfig.BaseAddress, AppConfig.RabbitUsername, AppConfig.RabbitPassword);
            var vhost = client.GetVhostAsync("/").Result;
            var aliveRes = client.IsAliveAsync(vhost).Result;
            var errQueue = client.GetQueueAsync(Constants.EasyNetQErrorQueueName, vhost).Result;
            var crit = new GetMessagesCriteria(long.MaxValue, Ackmodes.ack_requeue_false);
            var errMsgs = client.GetMessagesFromQueueAsync(errQueue, crit).Result;
            foreach (var errMsg in errMsgs)
            {
                var innerMsg = JsonConvert.DeserializeObject<Error>(errMsg.Payload);
                var pubInfo = new PublishInfo(innerMsg.RoutingKey, innerMsg.Message);
                pubInfo.Properties.Add("type", innerMsg.BasicProperties.Type);
                pubInfo.Properties.Add("correlation_id", innerMsg.BasicProperties.CorrelationId);
                pubInfo.Properties.Add("delivery_mode", innerMsg.BasicProperties.DeliveryMode);
                var pubRes = client.PublishAsync(client.GetExchangeAsync(innerMsg.Exchange, vhost).Result,
                     pubInfo).Result;
            }
var client=new ManagementClient(AppConfig.BaseAddress、AppConfig.RabbitUsername、AppConfig.RabbitPassword);
var vhost=client.GetVhostAsync(“/”).Result;
var aliveRes=client.IsAliveAsync(vhost).Result;
var errQueue=client.GetQueueAsync(Constants.EasyNetQErrorQueueName,vhost).Result;
var crit=new GetMessagesCriteria(long.MaxValue,Ackmodes.ack_requeue_false);
var errMsgs=client.GetMessagesFromQueueAsync(errQueue,crit).Result;
foreach(errMsgs中的var errMsg)
{
var innerMsg=JsonConvert.DeserializeObject(errMsg.Payload);
var PublishInfo=新的PublishInfo(innerMsg.RoutingKey,innerMsg.Message);
添加(“type”,innerMsg.BasicProperties.type);
添加(“correlation_id”,innerMsg.BasicProperties.CorrelationId);
添加(“交付模式”,innerMsg.BasicProperties.DeliveryMode);
var pubRes=client.PublishAsync(client.GetExchangeAsync(innerMsg.Exchange,vhost).Result,
结果;
}
我的消费者自己知道是否启用了重试功能,因此它可以选择处理重试消息或忽略它。一旦被忽略,msg显然不会再次尝试;这就是EasyNetQ的工作原理

            var client = new ManagementClient(AppConfig.BaseAddress, AppConfig.RabbitUsername, AppConfig.RabbitPassword);
            var vhost = client.GetVhostAsync("/").Result;
            var aliveRes = client.IsAliveAsync(vhost).Result;
            var errQueue = client.GetQueueAsync(Constants.EasyNetQErrorQueueName, vhost).Result;
            var crit = new GetMessagesCriteria(long.MaxValue, Ackmodes.ack_requeue_false);
            var errMsgs = client.GetMessagesFromQueueAsync(errQueue, crit).Result;
            foreach (var errMsg in errMsgs)
            {
                var innerMsg = JsonConvert.DeserializeObject<Error>(errMsg.Payload);
                var pubInfo = new PublishInfo(innerMsg.RoutingKey, innerMsg.Message);
                pubInfo.Properties.Add("type", innerMsg.BasicProperties.Type);
                pubInfo.Properties.Add("correlation_id", innerMsg.BasicProperties.CorrelationId);
                pubInfo.Properties.Add("delivery_mode", innerMsg.BasicProperties.DeliveryMode);
                var pubRes = client.PublishAsync(client.GetExchangeAsync(innerMsg.Exchange, vhost).Result,
                     pubInfo).Result;
            }