NServiceBus 序列化问题 - 似乎不支持序列化器配置
NServiceBus serialization problems - doesn't seem to honoring serializer configuration
所以我开始遇到 NServiceBus 的这个问题,它显然会接受消息并序列化它们,但似乎无法反序列化它们进行处理。我已经尝试通过几种不同的方式在设置中设置序列化程序。这是我从错误 queue.
中提取的一些异常(堆栈顶部)
// not setting the serializer. Appears that NServiceBus serializes as
XML (as documented) but tries to deserialize using NewtonSoft
"NServiceBus.ExceptionInfo.StackTrace" :
"NServiceBus.MessageDeserializationException: An error occurred while
attempting to extract logical messages from transport message
7cc546df-09ca-493e-bb6d-a6ce00a6bb10 --->
Newtonsoft.Json.JsonReaderException: Unexpected character encountered
while parsing value: <. Path '', line 0, position 0.\u000d\u000a at
Newtonsoft.Json.JsonTextReader.ParseValue() in
C:\Build\src\NServiceBus.Core\CircuitBreakers\CircuitBreaker.cs:line
0\u000d\u000a at
NServiceBus.JsonMessageSerializer.Deserialize(Stream stream, IList`1
messageTypes) in
C:\Build\src\NServiceBus.Core\Serializers\Json\JsonMessageSerializer.cs:line
108\u000d\u000a at ...
// with setting the serializer to the normal NServiceBus
JsonSerializer (as in the tutorials). Looks like it can't deserialize
JObject because it didn't include Newtonsoft in the scan. But why is
it JObject at all?
"NServiceBus.ExceptionInfo.StackTrace" :
"NServiceBus.MessageDeserializationException: An error occurred while
attempting to extract logical messages from transport message
ee5c8703-f509-40aa-a187-a6ce00a7fd1e ---> System.Exception: Could not
find metadata for 'Newtonsoft.Json.Linq.JObject'.\u000d\u000aEnsure
the following:\u000d\u000a1. 'Newtonsoft.Json.Linq.JObject' is
included in initial scanning. \u000d\u000a2.
'Newtonsoft.Json.Linq.JObject' implements either 'IMessage', 'IEvent'
or 'ICommand' or alternatively, if you don't want to implement an
interface, you can use 'Unobtrusive Mode'.\u000d\u000a at
NServiceBus.Unicast.Messages.MessageMetadataRegistry.GetMessageMetadata(Type
messageType) in ...
// with setting the serializer to NewtonSoftSerializer it appears to
be the same error "NServiceBus.ExceptionInfo.StackTrace" :
"NServiceBus.MessageDeserializationException: An error occurred while
attempting to extract logical messages from transport message
603e07e7-7877-4d71-90b3-a6ce00a9370b ---> System.Exception: Could not
find metadata for 'Newtonsoft.Json.Linq.JObject'.\u000d\u000aEnsure
the following:\u000d\u000a1. 'Newtonsoft.Json.Linq.JObject' is
included in initial scanning. \u000d\u000a2.
'Newtonsoft.Json.Linq.JObject' implements either 'IMessage', 'IEvent'
or 'ICommand' or alternatively, if you don't want to implement an
interface, you can use 'Unobtrusive Mode'.\u000d\u000a at
NServiceBus.Unicast.Messages.MessageMetadataRegistry.GetMessageMetadata(Type
messageType) in ...
这 感觉 像其中一个或全部。根据我所看到的,我的想法是:
- 出于某种原因,当我设置 json 序列化器时,objects 正在使用相同的方法序列化(不确定是什么)
- 无论我设置什么序列化器(或者即使我通过将相同的序列化器添加到反序列化器来进行镜像),它都会尝试使用 Newtonsoft
对其进行反序列化
其他我认为有用的点:
- 来自消息中包含的 headers(来自错误 queue):
- 当我使用 json 序列化程序时,内容类型是 application/json 并且内部异常是 Newtonsoft.Json.JsonReaderException
- 当我没有设置序列化器时,内容类型是text/xml,内部异常是Newtonsoft.Json.JsonReaderException
- 这是托管在 WebAPI 应用程序中
- 这可能会影响序列化程序的选择?
- 消息 类 在共享 pcl 库中。我没有实现 IMessage(等)接口,而是在配置期间将它们包含在约定中(非侵入式模式)。
- 这一段时间工作正常,然后这周才开始抛出这些错误。我找不到任何与 NServiceBus 相关的更改。
- 我以前在使用命令时遇到过这个问题,但是当我为 NServiceBus 添加 Newtonsoft nuget 库时,命令 (Send()) 停止抛出此错误。但是现在事件 (Publish()) 仍然抛出相同的异常
- 我在另一个线程中看到,有人建议查看消息中的 json body 以查看序列化的 body 是否具有 $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);
}
事实证明,问题 似乎 是下游订阅者对存在问题的消息进行了较旧的修订。 objects 是相同的,但程序集修订版在我们的构建服务器上的每个构建上得到更新,然后推送到 Nuget(例如 1.0.0.45621)。据推测,只要主要修订版没有更改,NServiceBus 应该不会有问题,并且它仍然可以在指定的命名空间中找到名称为 object 的 object 。显然,这有一些细微差别,因为一旦我更新了另一个组件中的库,错误就停止了。
我从这个帖子中得到了灵感 https://groups.google.com/forum/#!topic/particularsoftware/lc7shFVR46k
Particular 的一位开发人员提到 NSB 需要避免在 headers 中使用 FQAN。我查看了错误中包含的消息中的 headers,我注意到 origin 是我正在处理的服务,并且显示了所附消息类型的 FQAN与该服务中使用的版本号不同的版本号。所以我打开了公交车上目前唯一的其他服务,发现有一个匹配。我更新了它,一切都很好。
我关注了那里提到的问题,但它看起来像是关闭了它以代替我不太明白的其他事情。无论如何,那是我的解决方案。我仍在寻求澄清,否则我将与他们开票,因为这在未来是不可持续的。开发人员将不断地在该共享库中工作,我们无法在每次进行更改时更新平台上每个微服务中的库(短时间内会超过 20 个)。
所以我开始遇到 NServiceBus 的这个问题,它显然会接受消息并序列化它们,但似乎无法反序列化它们进行处理。我已经尝试通过几种不同的方式在设置中设置序列化程序。这是我从错误 queue.
中提取的一些异常(堆栈顶部)// not setting the serializer. Appears that NServiceBus serializes as XML (as documented) but tries to deserialize using NewtonSoft
"NServiceBus.ExceptionInfo.StackTrace" : "NServiceBus.MessageDeserializationException: An error occurred while attempting to extract logical messages from transport message 7cc546df-09ca-493e-bb6d-a6ce00a6bb10 ---> Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0.\u000d\u000a at Newtonsoft.Json.JsonTextReader.ParseValue() in C:\Build\src\NServiceBus.Core\CircuitBreakers\CircuitBreaker.cs:line 0\u000d\u000a at NServiceBus.JsonMessageSerializer.Deserialize(Stream stream, IList`1 messageTypes) in C:\Build\src\NServiceBus.Core\Serializers\Json\JsonMessageSerializer.cs:line 108\u000d\u000a at ...
// with setting the serializer to the normal NServiceBus JsonSerializer (as in the tutorials). Looks like it can't deserialize JObject because it didn't include Newtonsoft in the scan. But why is it JObject at all?
"NServiceBus.ExceptionInfo.StackTrace" : "NServiceBus.MessageDeserializationException: An error occurred while attempting to extract logical messages from transport message ee5c8703-f509-40aa-a187-a6ce00a7fd1e ---> System.Exception: Could not find metadata for 'Newtonsoft.Json.Linq.JObject'.\u000d\u000aEnsure the following:\u000d\u000a1. 'Newtonsoft.Json.Linq.JObject' is included in initial scanning. \u000d\u000a2. 'Newtonsoft.Json.Linq.JObject' implements either 'IMessage', 'IEvent' or 'ICommand' or alternatively, if you don't want to implement an interface, you can use 'Unobtrusive Mode'.\u000d\u000a at NServiceBus.Unicast.Messages.MessageMetadataRegistry.GetMessageMetadata(Type messageType) in ...
// with setting the serializer to NewtonSoftSerializer it appears to be the same error "NServiceBus.ExceptionInfo.StackTrace" : "NServiceBus.MessageDeserializationException: An error occurred while attempting to extract logical messages from transport message 603e07e7-7877-4d71-90b3-a6ce00a9370b ---> System.Exception: Could not find metadata for 'Newtonsoft.Json.Linq.JObject'.\u000d\u000aEnsure the following:\u000d\u000a1. 'Newtonsoft.Json.Linq.JObject' is included in initial scanning. \u000d\u000a2. 'Newtonsoft.Json.Linq.JObject' implements either 'IMessage', 'IEvent' or 'ICommand' or alternatively, if you don't want to implement an interface, you can use 'Unobtrusive Mode'.\u000d\u000a at NServiceBus.Unicast.Messages.MessageMetadataRegistry.GetMessageMetadata(Type messageType) in ...
这 感觉 像其中一个或全部。根据我所看到的,我的想法是:
- 出于某种原因,当我设置 json 序列化器时,objects 正在使用相同的方法序列化(不确定是什么)
- 无论我设置什么序列化器(或者即使我通过将相同的序列化器添加到反序列化器来进行镜像),它都会尝试使用 Newtonsoft 对其进行反序列化
其他我认为有用的点:
- 来自消息中包含的 headers(来自错误 queue):
- 当我使用 json 序列化程序时,内容类型是 application/json 并且内部异常是 Newtonsoft.Json.JsonReaderException
- 当我没有设置序列化器时,内容类型是text/xml,内部异常是Newtonsoft.Json.JsonReaderException
- 这是托管在 WebAPI 应用程序中
- 这可能会影响序列化程序的选择?
- 消息 类 在共享 pcl 库中。我没有实现 IMessage(等)接口,而是在配置期间将它们包含在约定中(非侵入式模式)。
- 这一段时间工作正常,然后这周才开始抛出这些错误。我找不到任何与 NServiceBus 相关的更改。
- 我以前在使用命令时遇到过这个问题,但是当我为 NServiceBus 添加 Newtonsoft nuget 库时,命令 (Send()) 停止抛出此错误。但是现在事件 (Publish()) 仍然抛出相同的异常
- 我在另一个线程中看到,有人建议查看消息中的 json body 以查看序列化的 body 是否具有 $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);
}
事实证明,问题 似乎 是下游订阅者对存在问题的消息进行了较旧的修订。 objects 是相同的,但程序集修订版在我们的构建服务器上的每个构建上得到更新,然后推送到 Nuget(例如 1.0.0.45621)。据推测,只要主要修订版没有更改,NServiceBus 应该不会有问题,并且它仍然可以在指定的命名空间中找到名称为 object 的 object 。显然,这有一些细微差别,因为一旦我更新了另一个组件中的库,错误就停止了。
我从这个帖子中得到了灵感 https://groups.google.com/forum/#!topic/particularsoftware/lc7shFVR46k
Particular 的一位开发人员提到 NSB 需要避免在 headers 中使用 FQAN。我查看了错误中包含的消息中的 headers,我注意到 origin 是我正在处理的服务,并且显示了所附消息类型的 FQAN与该服务中使用的版本号不同的版本号。所以我打开了公交车上目前唯一的其他服务,发现有一个匹配。我更新了它,一切都很好。
我关注了那里提到的问题,但它看起来像是关闭了它以代替我不太明白的其他事情。无论如何,那是我的解决方案。我仍在寻求澄清,否则我将与他们开票,因为这在未来是不可持续的。开发人员将不断地在该共享库中工作,我们无法在每次进行更改时更新平台上每个微服务中的库(短时间内会超过 20 个)。