3

WAS がホストするサービス (PerCall、Concurrency.Multiple) を正常にシャットダウン/リサイクルする必要がありますが、非アクティブな (ただし開いている) クライアント プロキシはサービスの正常なシャットダウンをブロックします。

receiveTimout が起動して非アクティブなセッションを破棄することを期待していましたが、そのようには機能しないようです。

IIS/WAS リサイクルは、終了タイムアウトを TimeSpan.MaxValue に設定して ServiceHost.BeginClose を呼び出します。

スループットと低レイテンシーが必須であるため、netTcpBinding を使用して長期間有効なクライアント プロキシ (実際には制御できません) を許可する必要があります。

以下の問題を再現しました。この問題に関する回避策とヘルプがあれば幸いです。

using System;
using System.ServiceModel;

namespace Test
{
    [ServiceContract(Name = "MyService", SessionMode = SessionMode.Allowed)]    
    public interface IHelloWorldService
    {
        [OperationContract]
        void PrintHelloWorld();
    }

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class HellowWorldService : IHelloWorldService
    {
        [OperationBehavior]
        public void PrintHelloWorld()
        {
            Console.WriteLine("Hello world!");
        }
    }

    public class ThaProgram
    {
        static void Main(string[] args)
        {
            const string ServiceAddress = "net.tcp://localhost:12345/HelloWorld";            
            var netTcpBinding = new NetTcpBinding(SecurityMode.None, false);
            netTcpBinding.ReceiveTimeout = TimeSpan.FromSeconds(3);
            var serviceHost = new ServiceHost(typeof(HellowWorldService), new Uri("net.tcp://localhost:12345"));
            serviceHost.AddServiceEndpoint(typeof(IHelloWorldService), netTcpBinding, ServiceAddress);

            serviceHost.Open();
            Console.WriteLine("Service host state: {0}", serviceHost.State);

            netTcpBinding.ReceiveTimeout = TimeSpan.FromSeconds(10);
            var channel = new ChannelFactory<IHelloWorldService>(netTcpBinding, ServiceAddress).CreateChannel();
            channel.PrintHelloWorld();

            // Uncomment to make everything work (then the session will be closed before the service enters the closing state)
            // Thread.Sleep(4000);

            // Simulate application pool shutdown
            var asyncResult = serviceHost.BeginClose(TimeSpan.MaxValue, null, null);
            Console.WriteLine("Service host state: {0}", serviceHost.State);
            serviceHost.EndClose(asyncResult);
            Console.WriteLine("Service host state: {0}", serviceHost.State);

            Console.WriteLine("Hit Enter to close the application");
            Console.ReadLine();
        }
    }
}
4

2 に答える 2

3

TCP にバインドされた*WCF サービス ホスト* が好きなときにいつでも接続を切断できないのは奇妙です。これは、名前付きパイプとは異なり、TCP の利点です。

いずれにせよ、私が好んで使用する 1 つの良いパターンは、すべてのサービス ホスト操作を別の .net AppDomainにラップすることです。サービスをホストするのはこのセカンダリ AppDomain であり、プライマリ AppDomainではありません。サンドボックスと考えてください。次に、シャットダウンする場合は、通常のサービス ホストクローズメソッドを使用してシャットダウンし、次にプライマリ アプリケーション ドメインにAppDomain.Unload () を実行させます .

以前のプロジェクトで見つけたように、クライアントはサーバーが再起動するのを防ぐことができるため、このようなパターンは名前付きパイプWCFでは絶対に必要です。(孤立した接続のため)

すべてがうまくいくことを願って

于 2011-07-09T05:46:06.853 に答える
0

net.tcp を使用しているため、クライアントは Web プロキシ経由でサーバーに接続していないと仮定します。その場合、問題を解決するために二重 net.tcp バインディングに切り替えることを検討させてください。

双方向バインディングを使用すると、クライアントが接続してコールバック コントラクトのインスタンスを保存するときに、サブスクライブ メソッドを呼び出すことができます。コールバック コントラクトでは、サーバーを閉じたいことをクライアントに知らせる操作を追加できます。

この目的のために、プロジェクトには既に二重契約がありますが、Windows サービスの OnStop がクライアントに切断を要求する上記のソリューションを実装する必要があります。残念ながら、IIS ホスティングの状況で BeginClose をインターセプトする方法がわかりません。おそらくカスタムServiceHostを使用していますか?

于 2011-09-21T05:52:00.027 に答える