在部署了我们的一个应用程序的新版本后,我们开始看到来自 WebApiContrib/protobuf-net 的多个 ArgumentOutOfRangeExceptions。它以前发生过一次,但在部署后发生得更频繁(5-10 次左右)。它只发生在少数几个请求中,我无法在本地或其他环境中重现。错误发生在多台机器上。
调用应用程序安装一个带有 protobuf 合约的 Nuget 类库,并且该合约已在此版本的被调用应用程序中更新。一些属性被删除(不改变 ProtoMember.Tag),一些属性被标记为 IsRequired=false 而不是 true。
是否有人对可能失败的原因或我们如何进一步诊断有任何见解?
System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: offset
at System.Web.HttpInputStream.Seek(Int64 offset, SeekOrigin origin)
at System.Web.Http.WebHost.SeekableBufferedRequestStream.Seek(Int64 offset, SeekOrigin origin)
at ProtoBuf.ProtoReader.Seek(Stream source, Int32 count, Byte[] buffer) in c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 1143
at proto_14(Object , ProtoReader )
at ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key, ProtoReader reader, Type type) in c:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 579
at proto_2(Object , ProtoReader )
at ProtoBuf.Meta.TypeModel.DeserializeCore(ProtoReader reader, Type type, Object value, Boolean noAutoCreate) in c:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs:line 704
at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type type, SerializationContext context) in c:\Dev\protobuf-net\protobuf-net\Meta\TypeModel.cs:line 588
at WebApiContrib.Formatting.ProtoBufFormatter.ReadFromStreamAsync(Type type, Stream stream, HttpContent content, IFormatterLogger formatterLogger)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Net.Http.HttpContentExtensions.<ReadAsAsyncCore>d__0`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.ModelBinding.FormatterParameterBinding.<ExecuteBindingAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Controllers.HttpActionBinding.<ExecuteBindingAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.HttpServer.<SendAsync>d__0.MoveNext()
版本:
<package id="Microsoft.AspNet.WebApi" version="5.2.3" targetFramework="net452" />
<package id="protobuf-net" version="2.0.0.668" targetFramework="net452" />
<package id="WebApiContrib.Formatting.ProtoBuf" version="0.9.5.0" targetFramework="net452" />
更新:
- 我们尝试从 WebApiContrib.Formatting 中删除 ProtobufFormatter,而是使用 Serializer.Deserialize 直接在代码中进行反序列化。那没有效果。
- 然后我们添加了重试。将 stream.Position 重置为 0 并再次反序列化。这样可行。
- 我们现在将 Request.Content 记录为 base64 字符串。该内容反序列化得很好,当尝试在本地复制它时,即使有数千个请求,也没有任何失败。