1 回答
TA贡献1936条经验 获得超6个赞
编辑
如果您使用显式ReplyTo地址,则任何错误都将发送到该 ReplyTo 地址而不是 DLQ。
如果您的 Response DTO 具有ResponseStatus属性,则 Exception 将填充在 Response DTO 的 ResponseStatus 中,否则您可以使用通用ErrorResponseDTO读取异常信息,例如:
var requestMsg = new Message<ThrowVoid>(request)
{
ReplyTo = $"mq:{request.GetType().Name}.replyto"
};
mqProducer.Publish(requestMsg);
var msg = mqClient.Get<ErrorResponse>(requestMsg.ReplyTo, null);
mqClient.Ack(msg);
msg.GetBody().ResponseStatus.ErrorCode //= InvalidOperationException
我无法仅使用正常的 ServiceStack 类来重现此问题,如在所有 MQ 服务器中按预期工作的提交所见。
我在下面提取了使用ServiceStack 的 RabbitMQ 服务器的代码:
public class ThrowVoid
{
public string Content { get; set; }
}
public class TestMqService : Service
{
public void Any(ThrowVoid request)
{
throw new InvalidOperationException("this is an invalid operation");
}
}
public class AppHost : AppSelfHostBase
{
public AppHost(Func<IMessageService> createMqServerFn)
: base(nameof(TestMqService), typeof(TestMqService).Assembly) {}
public override void Configure(Container container)
{
var mqServer = new RabbitMqServer { RetryCount = 1 };
container.Register<IMessageService>(c => mqServer);
mqServer.RegisterHandler<ThrowVoid>(ExecuteMessage);
AfterInitCallbacks.Add(appHost => mqServer.Start());
}
}
发送消息的位置:
using (var mqFactory = appHost.TryResolve<IMessageFactory>())
{
var request = new ThrowVoid { Content = "Test" };
using (var mqProducer = mqFactory.CreateMessageProducer())
using (var mqClient = mqFactory.CreateMessageQueueClient())
{
mqProducer.Publish(request);
var msg = mqClient.Get<ThrowVoid>(QueueNames<ThrowVoid>.Dlq, null);
mqClient.Ack(msg);
Assert.That(msg.Error.ErrorCode, Is.EqualTo("InvalidOperationException"));
}
}
无法确定您的问题是什么,因为很多实现隐藏在您自己的自定义类之后,但我建议从一个像上面这样的小型独立示例开始,该示例确实有效,然后慢慢添加您的自定义代码以识别是什么造成它。
尽管我建议不要使用继承来隐藏 DTO 中的属性,但 DTO 是用于定义服务合同的声明性模型,将它们的属性隐藏在继承之后会使阅读它的人更难确切知道每个服务接受和返回的内容。继承对于定义可重用的功能很有用,但 DTO 是声明性的,应该没有实现,所以你基本上是添加了不必要的耦合来隐藏显式的服务契约,从而更难通过查看服务契约来推断每个服务的作用.
- 1 回答
- 0 关注
- 190 浏览
添加回答
举报