0

Windows サービスでホストされている WCF サービスがあり、長期間非アクティブ状態が続いた後 (つまり、週末の後) にハングします。

この動作はさまざまな場所で発生します。

このサービスは、トランスポート セキュリティを使用するように設定された WSHttpBinding と、Windows 認証を使用するカスタム serviceAuthorization authorizationPolicy を使用します。

Spring フレームワークが使用されます。Spring.ServiceModel.Activation.ServiceHostFactory は Service ホストを作成します。

サービス スロットルは、200 のセッション、インスタンス、および呼び出しに設定されています。システムのユーザーは最大 15 人です。

トレースが有効になっており、警告に設定されているため、スロットルの問題について通知されます。サービス トレース ログにメッセージはありません。関連するメッセージはイベント ログにありません。HTTPPerf ログに関連するログはありません。サーバー側アプリケーションにかなりのログが記録されますが、システムがハングしたときに記録されるアクティビティはありません。システムがハングアップすると、完全にブラック ボックスになります。

クライアントは次のメッセージで失敗します。08:13:32.014 [1] ERROR App - 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:

これに関する関連情報を探すのに何時間も費やしました。

これはトレース ログに記録する必要があるため、非アクティブ タイムアウトとは関係ないと思います。

私が考えられる唯一のことは、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>
4

2 に答える 2

0

クライアントはどのようにサービスを呼び出していますか? SvcUtil生成されたプロキシを介してサービスを呼び出している場合。プロキシ接続を適切に閉じていますか? クライアントが接続を閉じていないか、単に接続が適切に閉じられていないと思います。

重要なことの 1 つは、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;
   }
}
于 2012-07-09T16:53:06.920 に答える
0

これは、クライアントとサーバーのバインディングエンドポイントと動作を同じに維持することで実行できると思います。クライアントとサーバーの構成で指定されたタイムアウト値は同じであるべきです。

于 2012-07-16T08:51:48.723 に答える