ServiceStack RedisMessageQueueClient:错误没有返回到ReplyTo地址,也没有使用RetryAttempts?

Posted

技术标签:

【中文标题】ServiceStack RedisMessageQueueClient:错误没有返回到ReplyTo地址,也没有使用RetryAttempts?【英文标题】:ServiceStack RedisMessageQueueClient: Errors are not returned to the ReplyTo address, nor is the RetryAttempts used? 【发布时间】:2021-10-27 22:04:36 【问题描述】:

我正在使用RedisMessageQueueClient,如下所示:

    public TResponse SendSync<TRequest, TResponse>(TRequest request, int? timeoutMilliseconds = null)
        where TRequest : CoreRequest 
        where TResponse : CoreRequest
    
        IMessage responseMessage = null;
        using (var mqClient = MqClientFactory.Instance.CreateMessageQueueClient())
        
            // mqClient is ServiceStack.Messaging.RedisMessageQueueClient

            var uniqueCallbackQ = $"mq:c1:request.GetType().Name:Guid.NewGuid():N";
            var clientMsg = new Message<TRequest>(request)
            
                ReplyTo = uniqueCallbackQ,
                RetryAttempts = 0
            ;
    
            mqClient.Publish(clientMsg);
    
            TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds.HasValue ? timeoutMilliseconds.Value : 120000);
    
            //Blocks thread on client until reply message is received
            responseMessage = mqClient.Get<TResponse>(uniqueCallbackQ, timeout);
    
            if(responseMessage?.Body == null)
            
                throw new TimeoutException($"Request request.GetType().Name from Assembly.GetEntryAssembly().GetName().Name has timed out!");
            
    
        
        return responseMessage?.Body as TResponse;
    

由于某种原因,在我的代码中产生了一个错误(这是我实际上试图找到的),根据this SO post,该错误应该返回到回复地址:

如果您使用明确的回复地址,则任何错误都将发送到 那个 ReplyTo 地址而不是 DLQ。

在这种情况下,我使用的是 ReplyTo,如下所示:

但是,当我浏览 Redis 时,我看到请求以 DLQ 结尾,而不是回复地址。在下图中,我们看到:

    ReplyTo地址设置好了,和上面的代码一样 RetryAttempts 在代码中为 0,但在 DQL 转储中为 2;我还看到失败的请求被重新发送了 2 次。 MqServer 是使用_mqServer = new RedisMqServer(_redisClientManager, retryCount: 2) 创建的,但我希望我可以使用上面的代码覆盖它?我也改成了_mqServer = new RedisMqServer(_redisClientManager, retryCount: 0),但还是重试了两次。

.NET 5.0、ServiceStack.Redis.Core 5.10.4、Visual Studio 2019

【问题讨论】:

【参考方案1】:

failed Error Responses are sent to the ReplyMq:

using (var mqFactory = appHost.TryResolve<IMessageFactory>())

    var request = new ThrowGenericError  Id = 1 ;

    using (var mqProducer = mqFactory.CreateMessageProducer())
    using (var mqClient = mqFactory.CreateMessageQueueClient())
    
        var requestMsg = new Message<ThrowGenericError>(request)
        
            ReplyTo = $"mq:request.GetType().Name.replyto"
        ;
        mqProducer.Publish(requestMsg);

        var msg = mqClient.Get<ErrorResponse>(requestMsg.ReplyTo, null);
        mqClient.Ack(msg);

        Assert.That(msg.GetBody().ResponseStatus.ErrorCode, Is.EqualTo("ArgumentException"));
    

失败的响应会立即发送到ReplyTo,即不会重试,因此不清楚您的 DLQ 消息来自何处。

【讨论】:

您好!第一的;关于重试问题的任何想法?谢谢。 @Ted 什么重试问题?不应重试回复消息。 很奇怪,因为它确实重试发送 ActorLogin 两次,所以总共 3 次,不管是否设置了 ReplyTo... 我会做更多调查,如果问题仍然存在,我会创建一个小型复制项目并在此处更新。 这似乎是问题所在:我覆盖了public virtual object OnAfterExecute(IRequest req, object requestDto, object response),并且那里发生了异常,那么上述问题似乎发生了;错误最终出现在 DLQ 中,并且没有返回给发送者(在当前实现中,base.OnAfterExecute(...) 是方法中的最后一行,因此由于异常而没有执行。我在这里正确吗?如果是,是这是预期的行为? @Ted 潜在地 OnAfterExecute() 不会因为 Service impls 中的异常而触发,它本身也不应该抛出异常。尝试调试到 fx 以确认,这里是 code path for Exceptions with ReplyTo messages,如果它最终出现在 DLQ 中,则它没有采用预期的代码路径。

以上是关于ServiceStack RedisMessageQueueClient:错误没有返回到ReplyTo地址,也没有使用RetryAttempts?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ServiceStack 5.0 项目中使用来自 ServiceStack 4.0 的服务模型?

具有模式的 ServiceStack IRedisClient ScanAllKeys 未按预期返回结果 (ServiceStack 5.7.0)

ServiceStack:添加 Blazor 支持?

ServiceStack.OrmLite 调用存储过程

哪个 Canoe 版本与链接中为 REDIS 客户端实现提供的 soln 兼容 https://github.com/ServiceStack/ServiceStack.Redis

解决ServiceStack.Redis的6000次限制问题