【问题标题】:Hosted WCF Service Hangs after the weekend周末后托管的 WCF 服务挂起
【发布时间】:2012-07-03 11:02:35
【问题描述】:

我们有一个托管在 Windows 服务中的 WCF 服务,该服务在长时间不活动后挂起:即周末之后。

这种行为发生在不同的位置。

该服务使用设置为使用传输安全的 WSHttpBinding 以及使用 Windows 身份验证的自定义 serviceAuthorization authenticationPolicy。

使用了 Spring 框架。 Spring.ServiceModel.Activation.ServiceHostFactory 创建服务主机。

服务限制设置为 200 个会话、实例和调用。系统最多有 15 个用户。

跟踪已启用并设置为警告,这应该让我知道油门问题。 服务跟踪日志中没有消息。 事件日志中没有看起来相关的消息。 HTTPPerf 日志中没有相关日志。 我们在服务器端应用程序中大量登录,但系统挂起时没有记录任何活动。 当系统挂起时,它是一个完全黑匣子。

客户端失败并显示以下消息。 08:13:32.014 [1] 错误应用程序 - System.TimeoutException:客户端无法在配置的超时 (00:00:59.9941374) 内完成安全协商。当前的谈判腿是 1 (00:00:59.9863206)。 ---> System.TimeoutException:请求通道在 00:00:59.9628702 之后等待回复时超时。增加传递给 Request 调用的超时值或增加 Binding 上的 SendTimeout 值。分配给此操作的时间可能是较长超时的一部分。 ---> System.TimeoutException:对“http://localhost:8080/OrderManagementService.svc”的 HTTP 请求已超过分配的超时 00:00:59.9690000。分配给此操作的时间可能是较长超时的一部分。 ---> System.Net.WebException:操作已超时 在 System.Net.HttpWebRequest.GetResponse()

我花了很多时间搜索这方面的相关信息。

我不认为这与不活动超时有关,因为这应该记录在跟踪日志中。

我能想到的唯一事情是与 Active Directory 凭据缓存或类似性质的事情有关,或者与 Spring 框架的使用有关。

任何帮助将不胜感激。

我正在考虑完全放弃 WSHttpBinding 或 WCF,因为这是不可接受的情况。

服务端配置如下。

<system.serviceModel>
<bindings>
  <wsHttpBinding>
    <binding name="WSHttpBinding" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false" maxBufferPoolSize="2147483646" maxReceivedMessageSize="2147483646">
      <readerQuotas maxDepth="2147483646" maxStringContentLength="2147483646" maxArrayLength="2147483646" maxBytesPerRead="2147483646" maxNameTableCharCount="2147483646" />
      <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
      <security>
        <transport></transport>
      </security>
    </binding>
  </wsHttpBinding>
</bindings>
<behaviors>
  <serviceBehaviors>
    <behavior name="ServiceBehavior">
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
      <serviceAuthorization principalPermissionMode="Custom">
        <authorizationPolicies>
          <add policyType="Kodi.Kodiak.Security.AuthorizationPolicy, Kodi.Kodiak.Security" />
        </authorizationPolicies>
      </serviceAuthorization>
      <serviceCredentials>
        <windowsAuthentication includeWindowsGroups="true" allowAnonymousLogons="false" />
      </serviceCredentials>
      <serviceThrottling maxConcurrentCalls="200" maxConcurrentSessions="200" maxConcurrentInstances="200" />
      <dataContractSerializer maxItemsInObjectGraph="2147483646" />
    </behavior>
  </serviceBehaviors>
  <endpointBehaviors>
    <behavior name="rest">
      <webHttp />
    </behavior>
  </endpointBehaviors>
</behaviors>
<services>
  <service behaviorConfiguration="ServiceBehavior" name="OrderManagementService">
    <endpoint address="" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding" contract="Kodi.Kodiak.Services.ServiceContracts.IOrderManagementService" />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  </service>
</services>

弹簧配置

<object id="OrderManagementService"
    singleton="false"
    type="Kodi.Kodiak.Services.OrderManagementService, Kodi.Kodiak.Services"
    scope="session">
 </object>

【问题讨论】:

  • 重启后还能用吗?你能在 IIS 上托管这个应用程序,看看它在那里是如何工作的吗?
  • 周末后你是如何“解决”这个问题的?重启windows服务?当客户端周一早上尝试连接时,wcf 端点是否可访问(例如通过 telnet 测试)? (在您的客户之前尝试此操作)
  • 直到你无法找到解决方案,保持服务活着这样。 stackoverflow.com/questions/3466490/…
  • Brijesh,是的,它在重新启动后工作。无法在 IIS 中托管,因为 windows 服务正在连接到其他系统并且需要维护状态、连接等。Wal,当我们遇到这个问题时,我们重新启动了 windows 服务。顺便说一句,这种情况并非每周一都会发生,所以这有点难以确定。
  • 我很好奇,ReliableSession 配置中的 enabled="false" 做了什么?

标签: wcf spring.net freeze


【解决方案1】:

客户如何调用服务?如果他们通过SvcUtil生成的代理调用服务; 他们是否正确关闭了代理连接?我认为客户端没有关闭连接,或者只是连接没有正确关闭。

重要的是,您应该避免在创建代理时使用using 语句。

更好的方法是这样的,

ServiceClient client = null;

try
{
  client = new ServiceClient();
  client.CallMethod();
}
finally
{
  client.CloseConnection(); // extension method
}

public static void CloseConnection(this ICommunicationObject client)
{
   if (client.State != CommunicationState.Opened)
   {
      return;
   }

   try
   {
      client.Close();
   } 
   catch (CommunicationException)
   {
      client.Abort();
      throw;
   }
   catch (TimeoutException)
   {
      client.Abort();
      throw;
   }
   catch (Exception)
   {
      client.Abort();
      throw;
   }
}

【讨论】:

  • 您好,Mark,是的,我们正在以类似的方式调用该服务。我们不使用 using 语句。我们使用 ChannelFactory 创建客户端并使用 try.. finally 以与您发布的方式类似的方式。
【解决方案2】:

我认为这可以通过保持客户端和服务器的绑定端点和行为相同来完成,客户端和服务器配置中指定的超时值应该相同

【讨论】:

    猜你喜欢
    • 2018-09-11
    • 1970-01-01
    • 2019-01-06
    • 2011-09-18
    • 1970-01-01
    • 2013-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多