每个Web服务调用的XmlSerializer First Chance Exception

时间:2015-07-18 16:15:59

标签: web-services stack-trace xmlserializer

我希望你们中的一个能帮助我诊断网络服务电话的堆栈跟踪。我正在试图弄清楚什么导致我们的Web服务上的高CPU使用率,所以当CPU的峰值高于80%时,我已经进行了一些内存转储。 在运行转储文件(并选择简单的修复程序)后,我留下了一个特别有趣的文件。

bcryptPrimitives!accumulate+54 
bcryptPrimitives!create_modulus+200 
bcryptPrimitives!create_modulus_select_arithmetic+2d 
bcryptPrimitives!rsa_import+254 
bcryptPrimitives!MSCryptImportKeyPair+132 
bcrypt!BCryptImportKeyPair+179 
rsaenh!LocalPopulateBCryptPublicKey+206 
rsaenh!CPImportKey+346 
cryptsp!CryptImportKey+163 
clr!StrongNameTokenFromPublicKey+1a5 
clr!CAssemblyName::SetProperty+218 
clr!BaseAssemblySpec::CreateFusionName+32b 
clr!BaseAssemblySpec::GetFileOrDisplayName+4e 
clr!AssemblyNameNative::ToString+164 
[[HelperMethodFrame_1OBJ] (System.Reflection.AssemblyName.nToString)] System.Reflection.AssemblyName.nToString() 
mscorlib_ni!System.Reflection.AssemblyName.get_FullName()+9 
RazorEngine.Compilation.CompilerServiceBase.CurrentDomain_AssemblyResolve(System.Object, System.ResolveEventArgs)+124 
mscorlib_ni!System.AppDomain.OnAssemblyResolveEvent(System.Reflection.RuntimeAssembly, System.String)+a4 
clr!CallDescrWorkerInternal+83 
clr!CallDescrWorkerWithHandler+4a 
clr!MethodDescCallSite::CallTargetWorker+251 
clr!AppDomain::RaiseAssemblyResolveEvent+d6860 
[[GCFrame]] 
clr!AppDomain::TryResolveAssembly+82 
clr!AppDomain::PostBindResolveAssembly+d1 
clr!`AppDomain::BindAssemblySpec'::`1'::catch$5+d7 
MSVCR120_CLR0400!CallSettingFrame+20 
MSVCR120_CLR0400!_CxxCallCatchBlock+f5 
ntdll!RcConsolidateFrames+3 
clr!AppDomain::BindAssemblySpec+ef7 
clr!AssemblySpec::LoadDomainAssembly+1ec 
clr!AssemblySpec::LoadAssembly+1b 
clr!AssemblyNative::Load+304 
[[HelperMethodFrame_PROTECTOBJ] (System.Reflection.RuntimeAssembly._nLoad)] System.Reflection.RuntimeAssembly._nLoad(System.Reflection.AssemblyName, System.String, System.Security.Policy.Evidence, System.Reflection.RuntimeAssembly, System.Threading.StackCrawlMarkByRef, IntPtr, Boolean, Boolean, Boolean) 
mscorlib_ni!System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(System.Reflection.AssemblyName, System.Security.Policy.Evidence, System.Reflection.RuntimeAssembly, System.Threading.StackCrawlMark ByRef, IntPtr, Boolean, Boolean, Boolean)+d2 
mscorlib_ni!System.Reflection.Assembly.Load(System.Reflection.AssemblyName)+3b 
System_Xml_ni!System.Xml.Serialization.TempAssembly.LoadGeneratedAssembly(System.Type, System.String, System.Xml.Serialization.XmlSerializerImplementation ByRef)+1a6 
System_Xml_ni!System.Xml.Serialization.XmlSerializer.FromMappings(System.Xml.Serialization.XmlMapping[], System.Type)+59 
System_ServiceModel_ni!System.ServiceModel.Description.XmlSerializerOperationBehavior+Reflector+SerializerGenerationContext.GenerateSerializers()+dd 
System_ServiceModel_ni!System.ServiceModel.Description.XmlSerializerOperationBehavior+Reflector+SerializerGenerationContext.GetSerializer(Int32)+74 
System_ServiceModel_ni!System.ServiceModel.Dispatcher.XmlSerializerOperationFormatter.AddHeadersToMessage(System.ServiceModel.Channels.Message, System.ServiceModel.Description.MessageDescription, System.Object[], Boolean)+be 
System_ServiceModel_ni!System.ServiceModel.Dispatcher.OperationFormatter.SerializeRequest(System.ServiceModel.Channels.MessageVersion, System.Object[])+e2 
System_ServiceModel_ni!System.ServiceModel.Dispatcher.ProxyOperationRuntime.BeforeRequest(System.ServiceModel.Dispatcher.ProxyRpc ByRef)+1d1 
System_ServiceModel_ni!System.ServiceModel.Channels.ServiceChannel.PrepareCall(System.ServiceModel.Dispatcher.ProxyOperationRuntime, Boolean, System.ServiceModel.Dispatcher.ProxyRpc ByRef)+85 
System_ServiceModel_ni!System.ServiceModel.Channels.ServiceChannel.Call(System.String, Boolean, System.ServiceModel.Dispatcher.ProxyOperationRuntime, System.Object[], System.Object[], System.TimeSpan)+27f 
System_ServiceModel_ni!System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(System.Runtime.Remoting.Messaging.IMethodCallMessage, System.ServiceModel.Dispatcher.ProxyOperationRuntime)+6c 
System_ServiceModel_ni!System.ServiceModel.Channels.ServiceChannelProxy.Invoke(System.Runtime.Remoting.Messaging.IMessage)+133 
mscorlib_ni!System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(System.Runtime.Remoting.Proxies.MessageData ByRef, Int32)+1f4 
clr!CTPMethodTable__CallTargetHelper3+12 
clr!CallTargetWorker2+74 
clr!CTPMethodTable::OnCall+1fb 
clr!TransparentProxyStub_CrossContextPatchLabel+a 
[[TPMethodFrame] (x.Server.WebReferences.x.x.Save)] x.Server.WebReferences.xxx.xxxServiceSoap.Save() 

我们的架构很简单:我们有一个桌面客户端,它通过WCF与我们的服务进行通信。然后,我们的一些服务调用将通过Web服务将数据推送到另一个系统。上面的堆栈跟踪代表了这样的调用 - 从我们的服务到另一个服务。

我在加载XmlSerializer时收到第一次机会异常(从我的研究完成,这是预期的行为,如果找不到生成的程序集,它将生成一个并继续)。但是,对于每个进行的Web服务调用,我们似乎都会收到此异常。我的印象是,一旦生成了程序集,它将不再抛出第一次机会异常?)

这是Web服务调用的正常行为吗? 对我来说,好像我们每次都在生成这个程序集 - 然后轮流引发AssemblyResolveEvent - 然后执行RazorEngine.Compilation解析事件......这在此时完全没必要..

有什么想法和想法吗?

提前致谢

1 个答案:

答案 0 :(得分:0)

从您的回溯中可以看出,一直占用的方法不是生成和加载动态创建的XmlSerializer DLL的方法。相反,花费时间的方法是尝试加载pre-generated XmlSerializer DLLs的方法。

要查看此内容,请查看reference source中的XmlSerializer.FromMappings

    public static XmlSerializer[] FromMappings(XmlMapping[] mappings, Type type) {
        if (mappings == null || mappings.Length == 0) return new XmlSerializer[0];
        XmlSerializerImplementation contract = null;
        Assembly assembly = type == null ? null : TempAssembly.LoadGeneratedAssembly(type, null, out contract);
        TempAssembly tempAssembly = null;
        if (assembly == null) {
            if (XmlMapping.IsShallow(mappings)) {
                return new XmlSerializer[0];
            }
            else {                    
                if (type == null) {
                    tempAssembly = new TempAssembly(mappings, new Type[] { type }, null, null, null);
                    XmlSerializer[] serializers = new XmlSerializer[mappings.Length];

                    contract = tempAssembly.Contract;

                    for (int i = 0; i < serializers.Length; i++) {
                        serializers[i] = (XmlSerializer)contract.TypedSerializers[mappings[i].Key];
                        serializers[i].SetTempAssembly(tempAssembly, mappings[i]);
                    }

                    return serializers;
                }
                else {
                    // Use XmlSerializer cache when the type is not null.
                    return GetSerializersFromCache(mappings, type);
                }
            }
        }
        else {
            XmlSerializer[] serializers = new XmlSerializer[mappings.Length];
            for (int i = 0; i < serializers.Length; i++)
                serializers[i] = (XmlSerializer)contract.TypedSerializers[mappings[i].Key];
            return serializers;
        }
    }

调用TempAssembly.LoadGeneratedAssembly

    /// <devdoc>
    ///    <para>
    ///    Attempts to load pre-generated serialization assembly.
    ///    </para>
    /// </devdoc>
    internal static Assembly LoadGeneratedAssembly(Type type, string defaultNamespace, out XmlSerializerImplementation contract) 

运行时XmlSerializer DLL的加载发生在GetSerializersFromCache内,顾名思义,它被缓存。

如果XmlSerializer.FromMappings在此特定回溯中的每次调用上花费了大量的CPU时间,那么您的服务器上可能还有一些过时的pre-compiled .XmlSerializers.dll文件(在磁盘上或GAC中)需要清理吗?在每次调用时.Net可能会尝试加载它们,然后发现版本号或签名不匹配,然后抛出异常,这样做会消耗大量的CPU时间。或者,如果DLL没有过时,可能还有architecture mismatch