精确定位某些环境中慢速WCF自托管服务的原因

时间:2014-11-13 23:37:35

标签: c# wcf

我试图调试为什么我们的软件(客户端和服务器)在某些环境中速度慢。我尝试了一些没有成功的事情,现在我对如何继续追踪这个问题感到茫然。我的问题是:我可以尝试或研究哪些事情来解决这个问题?

我们正在开发一个在服务器上运行的WCF自托管服务,以及一个连接到它的客户端应用程序。该服务与数据库(MS SQL服务器)交互。

设置A

  • 服务器在VM中运行(2 GB RAM,VM为1核心)
  • 客户端是同一个Intranet上的独立桌面计算机
  • 客户端启动(身份验证和初始化 - 大约40次服务调用)在不到5秒的时间内完成

设置B

  • 服务器未虚拟化(16 GB RAM,双XEON e5-2640)
  • 客户端在与服务器相同的计算机上运行(连接到127.0.0.1)以进行测试
  • 客户端启动大约需要45秒

相似性

  • 服务器和客户端软件对于两种设置都是相同的版本
  • 服务器操作系统是windows 2008 r2
  • 文件服务器和IIS的Windows角色(不应该是除SQL服务器之外的任何其他服务器类型的活动)
  • .NET 4.5.1的Windows功能

的差异

  • 安装程序B正在使用SQL Server 2012.安装程序A正在使用SQL Server 2008
  • 设置A和B相距超过1000英里(不同的网络,根据不同的IA规则管理)
  • Windows服务器功能的一些差异,但看起来的任何内容都不会导致问题

我尝试过的事情

  • 安装程序A在服务器上没有防火墙且没有防病毒软件。
  • 设置B已禁用Windows防火墙。语义端点保护正在运行;洞察力,猎犬,自动保护,下载洞察力被禁用进行测试,但没有任何区别。
  • SQL集成,报告和分析服务被禁用,几乎没有变化。
  • 我在Windows事件查看器中查看并且看不到任何与众不同的内容,但我不确定是否有具体的内容我应该寻找。
  • 我已启用WCF日志记录(根据here),但查看SvcTraceViewer.exe中的日志并不能告诉我任何有用的内容。
  • 同样,尝试在perfmon中记录各种统计数据并不高效。

其他想法

  • 在服务中不使用Entity Framework。
  • 文件存储位于同一台物理计算机上
  • 服务器正在为相关的webtool运行IIS,但WCF自托管服务应该不受影响(对吗?)
  • 运行SQL事件探查器,所有数据库调用都快速解决(毫秒),因此我不认为这是数据库问题。
  • CPU使用率始终很低。设置B上的RAM使用率低于60%(每个任务管理器)。
  • 由于它似乎不是数据库或资源问题,我猜它是网络或WCF问题。

我将要尝试的事情

  • 还有一些差异需要解决 - 不同的补丁,服务器功能等
  • 克隆设置VM到设置B服务器
  • 不确定

服务app.config

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
   <configSections>
      <section name="fooNET.serviceProvider" type="foo.fooNET.ServiceRegistration.Classes.ServiceProviderConfiguration, foo.fooNET.ServiceRegistration" />
      <section name="nlog" type="bar.com.foo.NLog.Config.ConfigSectionHandler, foo.NLog" />
   </configSections>
   <connectionStrings>
      <add name="BaseDB" connectionString="..." />
      <add name="UserStore2" connectionString="..." />
      <add name="UserStore" connectionString="..." providerName="System.Data.EntityClient" />
      <add name="MetricCollectionDAL.Properties.Settings.MASSMetricsConnectionString" connectionString="..." />
   </connectionStrings>
   <appSettings>
      <add key="maxRequestLength" value="16384" />
      <add key="exclusiveFlag" value="true" />
      <add key="SubscriptionDeleteNotification" value="true" />
   </appSettings>
   <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <targets>
         <target name="file" xsi:type="File" fileName="${basedir}/fooNetLog.txt" keepFileOpen="true" layout="${date:format=MM/dd/yyyy HH\:mm\:ss}|${level}|${windows-identity}|${callsite}|${message}" archiveEvery="Day" maxArchiveFiles="5" />
         <target name="session" xsi:type="File" fileName="${basedir}/sessionlog.txt" keepFileOpen="true" layout="${date:format=MM/dd/yyyy HH\:mm\:ss}|${level}|${windows-identity}|${callsite}|${message}" concurrentWrites="false" deleteOldFileOnStartup="true" />
      </targets>
      <rules>
         <logger name="*" minlevel="Error" writeTo="file,session" />
      </rules>
   </nlog>
   <fooNET.serviceProvider xmlns="foo.fooNET">
      <plugins directory="Plugins" />
      <baseAddress uri="https://localhost:6040/ServiceProvider" />
      <brokers count="1" remoteRegister="true" registrationInterval="1" />
   </fooNET.serviceProvider>
   <system.serviceModel>
      <diagnostics performanceCounters="All" />
      <services>
         <service behaviorConfiguration="ServiceProviderBehavior" name="foo.fooNET.ServiceRegistration.Classes.ServiceProvider">
            <endpoint address="" binding="ws2007FederationHttpBinding" bindingConfiguration="ws2007Binding" behaviorConfiguration="EndpointBehavior" contract="foo.fooNET.Shared.Server.Interfaces.IServiceProvider" />
            <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
            <host>
               <baseAddresses>
                  <add baseAddress="https://localhost:6040/ServiceProvider" />
               </baseAddresses>
               <timeouts closeTimeout="00:10:00" openTimeout="00:10:00" />
            </host>
         </service>
      </services>
      <behaviors>
         <serviceBehaviors>
            <behavior name="ServiceProviderBehavior">
               <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" policyVersion="Policy15" />
               <serviceDebug includeExceptionDetailInFaults="false" />
               <serviceSecurityAudit auditLogLocation="Application" suppressAuditFailure="false" serviceAuthorizationAuditLevel="Failure" messageAuthenticationAuditLevel="Failure" />
               <serviceThrottling maxConcurrentCalls="32" maxConcurrentSessions="20" maxConcurrentInstances="2147483647" />
            </behavior>
         </serviceBehaviors>
         <endpointBehaviors>
            <behavior name="EndpointBehavior">
               <dispatcherSynchronization maxPendingReceives="6" />
            </behavior>
         </endpointBehaviors>
      </behaviors>
      <bindings>
         <ws2007FederationHttpBinding>
            <binding name="2007MtomBinding" closeTimeout="01:00:00" openTimeout="00:40:00" receiveTimeout="01:00:00" sendTimeout="00:40:00" transactionFlow="false" maxBufferPoolSize="0" maxReceivedMessageSize="2147483647" messageEncoding="Mtom" useDefaultWebProxy="false">
               <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
               <reliableSession ordered="false" inactivityTimeout="01:00:00" enabled="false" />
               <security mode="TransportWithMessageCredential">
                  <message establishSecurityContext="false">
                     <claimTypeRequirements>
                        <add claimType="http://bar.com/foo/fooNET/claims/FirstName" isOptional="false" />
                     </claimTypeRequirements>
                  </message>
               </security>
            </binding>
            <binding name="ws2007Binding" closeTimeout="01:00:00" openTimeout="00:05:00" receiveTimeout="01:00:00" sendTimeout="00:40:00" maxReceivedMessageSize="2147483647" maxBufferPoolSize="0" useDefaultWebProxy="false">
               <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
               <reliableSession inactivityTimeout="01:00:00" />
               <security mode="TransportWithMessageCredential">
                  <message negotiateServiceCredential="false" establishSecurityContext="false">
                     <claimTypeRequirements>
                        <add claimType="http://bar.com/foo/fooNET/claims/FirstName" isOptional="false" />
                     </claimTypeRequirements>
                  </message>
               </security>
            </binding>
         </ws2007FederationHttpBinding>
         <wsHttpBinding>
            <binding name="AuthenticationBinding" closeTimeout="01:00:00" receiveTimeout="01:00:00" sendTimeout="00:40:00" maxReceivedMessageSize="2147483647" bypassProxyOnLocal="true">
               <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
               <reliableSession inactivityTimeout="01:00:00" />
               <security mode="Transport" />
            </binding>
         </wsHttpBinding>
         <ws2007HttpBinding>
            <binding name="SecurityAuth" sendTimeout="00:40:00" maxReceivedMessageSize="2147483647" closeTimeout="01:00:00" receiveTimeout="01:00:00" useDefaultWebProxy="false">
               <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
               <reliableSession inactivityTimeout="01:00:00" />
               <security mode="TransportWithMessageCredential">
                  <message negotiateServiceCredential="true" />
               </security>
            </binding>
         </ws2007HttpBinding>
      </bindings>
   </system.serviceModel>
   <startup>
      <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
   </startup>
</configuration>

更新2014-11-18

收到&#34;快照&#34;服务器A(单个文件.vhd)。在服务器B上使用单CPU和2 GB RAM在hyper-v中创建了一个新VM(必须添加hyper-v角色)并加载到服务器A vhd中。具有localhost连接的服务器A的本地VM速度与预期一样快。这告诉我唯一的事情就是物理盒子没什么问题。尝试将分配给VM的核心数量更改为4,几乎没有变化。

1 个答案:

答案 0 :(得分:0)

站起服务器虚拟机。我做了三次修改

  1. 网络上可见的IP地址
  2. 加入本地域
  3. 将服务帐户从[上一个]域更改为本地计算机(非域名)帐户
  4. 我运行wireshark并捕获了初始身份验证和启动。立即得到了大量的条目如下:

    enter image description here

    我将运行该服务的帐户更改为域上的帐户,但之后我根本无法进行通信。我得到一个例外(在客户端上)

      

    “通信对象System.ServiceModel.Channels.ServiceChannel不能用于通信,因为它处于Faulted状态。”

    这似乎表明存在未被捕获/未处理的异常。

    管理以提出更有用的例外:

      

    “安全支持提供程序接口(SSPI)身份验证失败。服务器可能没有   在身份'主机/ [计算机]'的帐户中运行。如果服务器正在运行   服务帐户(例如网络服务),指定帐户   ServicePrincipalName作为服务器的EndpointAddress中的标识。如果是服务器   正在用户帐户中运行,请将帐户的UserPrincipalName指定为标识   在服务器的EndpointAddress中。“

    即将开始尝试弄清楚这意味着什么(例如here),但后来我在services.msc中从域帐户更改为“本地系统帐户”复选框,一切都超级快。