WCFサービスとそれへのサービス参照を含むアプリケーションがあり、アプリケーションにはループがあり、反復ごとに、このwcf Webサービスのメソッドを呼び出しています。
問題は、約9回程度の呼び出しの後、停止するだけであり、VSのPause
ボタンを押すと、呼び出し先の回線でスタックしていることがわかります。
しばらく待ってから、次のTimeoutExceptionがスローされます。
00:00:59.9970000の後で応答を待機しているときに、要求チャネルがタイムアウトしました。 Requestの呼び出しに渡されるタイムアウト値を増やすか、BindingのSendTimeout値を増やします。この操作に割り当てられた時間は、より長いタイムアウトの一部であった可能性があります。
私はこれについて少し調査し、アプリケーションでapp.configを編集することを含むいくつかの解決策を見つけました、そしてここにそれの抜粋があります:
<serviceBehaviors>
<behavior name="ThrottlingIssue">
<serviceThrottling maxConcurrentCalls="500" maxConcurrentSessions="500" />
</behavior>
</serviceBehaviors>
。
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
次に、デバッグを停止した後、数分後に致命的なエラーが発生したことを示すエラーメッセージがポップアップ表示されます。
この問題を解決するにはどうすればよいですか?通常のWebサービスを使用していたときには、この問題は発生しませんでした。
参考までに、全体はapp.config
:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="ThrottlingIssue">
<serviceThrottling maxConcurrentCalls="500" maxConcurrentSessions="500" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IDBInteractionGateway" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
allowCookies="false">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" establishSecurityContext="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:28918/DBInteractionGateway.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IDBInteractionGateway"
contract="DBInteraction.IDBInteractionGateway" name="WSHttpBinding_IDBInteractionGateway">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
[更新]ソリューション:
どうやら各リクエストの後、接続をClose
する必要があります ...今、各リクエストの後に接続を閉じており、それは魅力のように機能しています。
まだ理解できないのは、私のapp.configでmaxConcurrentCallsとmaxConcurrentSessionsを500に設定しているにもかかわらず、10しか作成できないことです。 ? (多分私は上に投稿された私のapp.configに何か問題があります)
上記の質問に対する回答(現在は破線)は、クライアントを編集していたためですapp.config
、サービス構成ファイル(web.config
)
許可される同時接続のデフォルト数は10です。
おそらくクライアントが接続を閉じていません。
同時呼び出しの数を増やすには、クライアントではなくサービス構成に動作を追加する必要があります。
Clientservice.close()を呼び出すと問題が解決します。
これは、Webサービス参照とアプリケーション間のインターフェースとしてシングルトンクラスを作成することで解決できます。次に、サービス参照のインスタンスを1つだけ作成します。
class ServiceInterface
{
private static ServiceInterface _instance;
private ServiceClient _service = new ServiceClient ;
private ServiceInterface()
{
//Prevent accessing default constructor
}
public static ServiceInterface GetInstance()
{
if(_instance == null)
{
_instance = new ServiceInterface();
}
return _instance;
}
// You can add your functions to access web service here
Public int PerformTask()
{
return _service.PerformTask();
}
}
私は今週この問題に遭遇し、何が起こっているのかを完全に理解することができませんでした。サービスへの呼び出しを実際にサービスクライアントDispose()
に変更しましたが、何の効果もないようです。どうやら、どこかに潜んでいる別のサービスコールがありました。
興味深いのは、これがではなく問題であると私が判断した理由です。この制限は、ソケットへの実際のソケット接続数とは関係ありません。ウェブサービス。 maxConcurrentSessions
の制限に達しても、1つの実際のソケット接続しかありません。これをnetstat
でチェックしていたため、間違った結論に至りました。したがって、セッションとソケットを混同しないでくださいです。
すべてのWCFサービスに対して定義されたインターフェイスがあるので、このパターンをコードに今すぐ適用する予定です。
IMyService service = new MyServiceClient();
using (service as IDisposable)
{
service.MyServiceMethod();
}
また興味深いのは、サービス(およびWebサイト)がIISでホストされていたときに問題が発生しなかったことです。構成は(ほぼ)同一ですが、そのマシンではこの動作を再現できませんでした。それは良いことだと思います:)
using
の変数割り当てについて):私は通常、変数割り当てをusing
ステートメントに入れます。ただし、生成されるIMyServiceは暗黙的にIDisposable
に変換できません。そこに割り当てが本当に必要な場合は、代替案は次のようになります。
IService service;
using ((service = new ServiceClient()) as IDisposable)
{
}
しかし、それでも変数スコープの問題が残っています。 IService service
への参照は使用できませんが、まだスコープ内にあります。したがって、これはその点で優れています:
using (IDisposable serviceDisposable = new ServiceClient())
{
IService service = (IService)serviceDisposable;
}
ただし、追加の変数名を紹介する必要があります。 * Meh *
トレースの構成 でループを実行できますか?チャネルに障害が発生し、クライアントがタイムアウトになった可能性があります。
Close()
またはDispose()
のどちらでも解決されなかったmuch同様の問題を解決した後、つまり、- ServicePointManager.DefaultConnectionLimit
これはデフォルトで2です。
「DefaultConnectionLimitプロパティは、ServicePointManagerオブジェクトがServicePointオブジェクトの作成時にConnectionLimitプロパティに割り当てる同時接続のデフォルトの最大数を設定します。」
私の場合、アプリケーションはリモートサービスに2回正常に接続しました。3回目の試行では、サービスに接続しようとしませんでした。代わりに、上記の質問と同じエラーメッセージでタイムアウトする前にしばらく待機しました。 DefaultConnectionLimit
を増やすことでこれを解決しました。フラストレーションを追加するために、この動作はややランダムでした-10の1つのケースでは、Webサービスは複数回(> 2)正常に呼び出されました。
解決策はこれらの2つのスレッド wcf-timeout-exception-detailed-investigation および wcf-service-throttling から始まり、さらに議論されます。私の問題を解決しました。