【问题标题】:NServiceBus serialization problems - doesn't seem to honoring serializer configurationNServiceBus 序列化问题 - 似乎不尊重序列化程序配置
【发布时间】:2023-03-19 13:59:01
【问题描述】:

所以我开始遇到 NServiceBus 的这个问题,它显然会接受消息并序列化它们,但似乎无法反序列化它们以进行处理。我尝试以几种不同的方式在设置中设置序列化程序。以下是我从错误队列中提取的一些异常(堆栈顶部)。

// 不设置序列化器。似乎 NServiceBus 序列化为 XML(如文档所示)但尝试使用 NewtonSoft 进行反序列化

“NServiceBus.ExceptionInfo.StackTrace”: “NServiceBus.MessageDeserializationException:发生错误时 试图从传输消息中提取逻辑消息 7cc546df-09ca-493e-bb6d-a6ce00a6bb10 ---> Newtonsoft.Json.JsonReaderException:遇到意外的字符 解析值时:<. at newtonsoft.json.jsontextreader.parsevalue c: nservicebus.jsonmessageserializer.deserialize ...>


// 将序列化程序设置为正常的 NServiceBus JsonSerializer(如教程中所述)。好像不能反序列化 JObject,因为它没有在扫描中包含 Newtonsoft。但为什么是 它是 JObject 吗?

“NServiceBus.ExceptionInfo.StackTrace”: “NServiceBus.MessageDeserializationException:发生错误时 试图从传输消息中提取逻辑消息 ee5c8703-f509-40aa-a187-a6ce00a7fd1e ---> System.Exception: 不能 查找“Newtonsoft.Json.Linq.JObject”的元数据。\u000d\u000aEnsure 以下内容:\u000d\u000a1。 'Newtonsoft.Json.Linq.JObject' 是 包含在初始扫描中。 \u000d\u000a2。 “Newtonsoft.Json.Linq.JObject”实现“IMessage”、“IEvent” 或“ICommand”,或者,如果您不想实现 界面,您可以使用“不显眼模式”。\u000d\u000a at NServiceBus.Unicast.Messages.MessageMetadataRegistry.GetMessageMetadata(类型 messageType) 在 ...


// 将序列化程序设置为 NewtonSoftSerializer 它似乎 是相同的错误“NServiceBus.ExceptionInfo.StackTrace”: “NServiceBus.MessageDeserializationException:发生错误时 试图从传输消息中提取逻辑消息 603e07e7-7877-4d71-90b3-a6ce00a9370b ---> System.Exception: 不能 查找“Newtonsoft.Json.Linq.JObject”的元数据。\u000d\u000aEnsure 以下内容:\u000d\u000a1。 'Newtonsoft.Json.Linq.JObject' 是 包含在初始扫描中。 \u000d\u000a2。 “Newtonsoft.Json.Linq.JObject”实现“IMessage”、“IEvent” 或“ICommand”,或者,如果您不想实现 界面,您可以使用“不显眼模式”。\u000d\u000a at NServiceBus.Unicast.Messages.MessageMetadataRegistry.GetMessageMetadata(类型 messageType) 在 ...

这感觉就像几件事情中的一件或全部。根据我所看到的,我的想法是:

  • 由于某种原因,当我设置 json 序列化程序时,对象正在使用相同的方法进行序列化(不确定是什么)
  • 无论我设置什么序列化程序(或者即使我通过向反序列化程序添加相同的序列化程序来进行镜像),它都会尝试使用 Newtonsoft 对其进行反序列化

我认为可能有用的其他点:

  • 来自消息中包含的标头(来自错误队列):
    • 当我使用任一 json 序列化程序时,内容类型为 application/json,内部异常为 Newtonsoft.Json.JsonReaderException
    • 不设置序列化器时,内容类型为text/xml,内部异常为Newtonsoft.Json.JsonReaderException
  • 这是托管在 WebAPI 应用程序中
    • 也许这会影响序列化程序的选择?
  • 消息类位于共享 pcl 库中。我没有实现 IMessage (etc) 接口,而是在配置期间将它们包含在约定中(不显眼的模式)。
  • 这有一段时间工作正常,然后本周才开始抛出这些错误。我找不到任何与 NServiceBus 相关的更改。
  • 我曾经在使用命令时遇到过这个问题,但是当我为 NServiceBus 添加 Newtonsoft nuget 库时,命令 (Send()) 停止抛出此错误。但是现在事件 (Publish()) 仍然抛出相同的异常
  • 我在另一个线程中看到,有人建议查看消息中的 json 正文,以查看序列化的正文是否具有 $type 属性。它不是。

任何见解都会有所帮助。为什么序列化器不排队?

这里有一些杂项:

配置:

public static void Initialize(
  string endpointName, 
  string instanceDescriminator, 
  IWindsorContainer container)
{
    _endpointConfiguration = new EndpointConfiguration(ServiceEndpoint.Surveys);
    _endpointConfiguration.SendFailedMessagesTo("error");
    _endpointConfiguration.MakeInstanceUniquelyAddressable(instanceDescriminator);
    _endpointConfiguration.UseContainer<WindsorBuilder>(customizations =>
    {
        customizations.ExistingContainer(container);
    });

    _endpointConfiguration.UsePersistence<NHibernatePersistence, StorageType.Sagas>();
    _endpointConfiguration.UsePersistence<NHibernatePersistence, StorageType.Subscriptions>();
    _endpointConfiguration.UsePersistence<NHibernatePersistence, StorageType.Timeouts>();
    _endpointConfiguration.UsePersistence<NHibernatePersistence, StorageType.Outbox>();
    _endpointConfiguration.UsePersistence<NHibernatePersistence, StorageType.GatewayDeduplication>();
    _endpointConfiguration.EnableOutbox();
    _endpointConfiguration.UseTransport<SqlServerTransport>();
    _endpointConfiguration.EnableInstallers();

    NServiceBusConventions.SetDasConventions(_endpointConfiguration);
}

约定:

public static void SetDasConventions(EndpointConfiguration config)
{
    var conventions = config.Conventions();

    conventions.DefiningCommandsAs(type => type.Namespace != null && type.Namespace.StartsWith("DAS.Infrastructure.Messaging.Command"));
    conventions.DefiningEventsAs(type => type.Namespace != null && type.Namespace.StartsWith("DAS.Infrastructure.Messaging.Event"));
    conventions.DefiningMessagesAs(type => 
        type.Namespace != null && 
        (type.Namespace.StartsWith("DAS.Infrastructure.Messaging.Message") || type.Namespace.StartsWith("DAS.Infrastructure.Messaging")));
    conventions.DefiningEncryptedPropertiesAs(property => property.Name.StartsWith("Encrypted"));
    conventions.DefiningDataBusPropertiesAs(property => property.Name.EndsWith("DataBus"));
    conventions.DefiningExpressMessagesAs(type => type.Name.EndsWith("Express"));
    conventions.DefiningTimeToBeReceivedAs(type => type.Name.EndsWith("Expires") ? TimeSpan.FromSeconds(30) : TimeSpan.MaxValue);
}

【问题讨论】:

  • 能把代码分享到github/dropbox吗?

标签: c# serialization nservicebus


【解决方案1】:

事实证明,问题似乎在于下游订阅者有一个有问题的消息的旧版本。对象是相同的,但程序集修订会在我们构建服务器上的每个构建中更新,然后推送到 Nuget(例如 1.0.0.45621)。假设 NServiceBus 应该没有问题,只要主要版本没有改变并且它仍然可以在指定的命名空间中找到具有名称的对象。显然,这有一些细微差别,因为一旦我更新了另一个组件中的库,错误就停止了。

我从这个帖子https://groups.google.com/forum/#!topic/particularsoftware/lc7shFVR46k得到这个想法

Particular 的开发人员提到 NSB 需要避免在标头中使用 FQAN。我查看了错误中包含的消息中的标头,我注意到 origin 是我正在处理的服务,并且随附消息类型的 FQAN 显示的修订号不是与该服务中使用的相同。所以我打开了当前在公共汽车上唯一的其他服务,发现有一个匹配。我更新了它,一切都很好。

我关注了那里提到的问题,但看起来它关闭了它,而不是其他一些我不太明白的东西。无论如何,这是我的解决方案。我仍在寻求澄清,否则我将与他们一起开票,因为这在未来是不可持续的。开发人员将不断地在该共享库中工作,我们无法在每次进行更改时更新平台上每个微服务中的库(短时间内将超过 20 个)。

【讨论】:

    猜你喜欢
    • 2017-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-08
    • 2019-03-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多