NServiceBus序列化问题 - 似乎并不尊重序列化程序配置

时间:2016-11-30 17:47:00

标签: c# serialization nservicebus

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

  

//没有设置序列化程序。看来NServiceBus序列化为   XML(如文档所述)但尝试使用NewtonSoft反序列化

     

" NServiceBus.ExceptionInfo.StackTrace" :   " NServiceBus.MessageDeserializationException:发生错误   尝试从传输消息中提取逻辑消息   7cc546df-09ca-493e-bb6d-a6ce00a6bb10 --->   Newtonsoft.Json.JsonReaderException:遇到意外的字符   在解析值时:<。路径'',第0行,位置0. \ u000d \ u000a at   Newtonsoft.Json.JsonTextReader.ParseValue()in   C:\建立\ SRC \ NServiceBus.Core \断路器\ CircuitBreaker.cs:行   0 \ u000d \ u000a at   NServiceBus.JsonMessageSerializer.Deserialize(Stream stream,IList`1   messageTypes)in   C:\建立\ SRC \ NServiceBus.Core \串行器\的Json \ JsonMessageSerializer.cs:行   108 \ u000d \ u000a at ...

  

//将序列化程序设置为正常的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'或者,如果您不想实施   界面,您可以使用' Unobtrusive Mode'。\ u000d \ u000a at   NServiceBus.Unicast.Messages.MessageMetadataRegistry.GetMessageMetadata(类型   messageType)in ...

  

//将序列化程序设置为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'或者,如果您不想实施   界面,您可以使用' Unobtrusive Mode'。\ u000d \ u000a at   NServiceBus.Unicast.Messages.MessageMetadataRegistry.GetMessageMetadata(类型   messageType)in ...

这个感觉就像其中一个或全部一样。我的想法基于我所看到的:

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

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

  • 从消息中包含的标头(来自错误队列):
    • 当我使用任何一个json序列化程序时,内容类型是application / json,内部异常是Newtonsoft.Json.JsonReaderException
    • 当我没有设置序列化程序时,内容类型为text / xml,内部异常为Newtonsoft.Json.JsonReaderException
  • 这是托管在WebAPI应用程序中的
    • 也许这会影响序列化选择?
  • 消息类位于共享的pcl库中。我没有实现IMessage(etc)接口,而是在配置期间将它们包含在约定中(不引人注目的模式)。
  • 这个工作正常一段时间,然后本周才开始抛出这些错误。我无法找到与NServiceBus有任何关联的任何我改变的内容。
  • 我曾经遇到过Commands这个问题,但是当我为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);
}

1 个答案:

答案 0 :(得分:0)

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

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

得到了这个想法

如果dev特别提到NSB需要在标题中使用FQAN。我查看了错误中包含的消息中的标题,我注意到 origin 是我正在处理的服务,所附消息类型的FQAN显示的是不是的修订号与该服务中使用的相同。所以我打开了当前公交车上唯一的其他服务,发现其中一个匹配。我更新了它,一切都很好。

我跟着那里提到的问题,但它似乎关闭了它代替了我没有得到的其他东西。无论如何,这是我的解决方案。我还在寻求澄清,或者我会和他们一起开门票,因为这在将来是不可持续的。开发人员将不断在该共享库中工作,并且每次进行更改时,我们都无法在平台上的每个微服务中更新库(在短时间内将超过20个)。