0

特定のポートで着信 TCP 要求をリッスンし、メッセージを処理する Windows サービスに TCP リスナーがあります。直接アクセスすると問題なく動作します。しかし、これが (イントラネット内の) ロード バランサーの背後で実行されると、要求を受け入れなくなります。「リモート サーバーに接続できません」や「操作がタイムアウトしました」などのエラーが表示されます。しばらくすると、サービスは「メモリ不足」の例外で終了します。この理由として考えられることを教えてください。以下のコードを貼り付けます。非同期モードも試しました(明示的なスレッドの起動を避けるため)。しかし、それは役に立ちませんでした。

public class SampleListener: IDisposable
{
    public delegate void JobRecieved(HttpMessage msg);
    public event JobRecieved OnJobRecieved;

    #region Property

    private TcpListener _tcpListener;
    private Thread _listenerThread;

    public int Port { get; private set; }

    public string Url
    {
        get
        {
            return new UriBuilder { Scheme = "http", Port = Port, Host = Dns.GetHostName() }.ToString();
        }
    }

    #endregion

    public SampleListener(int port)
    {
        Port = port;
    }

    ~SampleListener()
    {
        DisposeImpl(false);
    }

    public void Start()
    {
        _tcpListener = new TcpListener(IPAddress.Any, Port);
        _tcpListener.Start();

        _listenerThread = new Thread(ListenCallback);
        _listenerThread.Start();
    }

    public void ListenCallback()
    {
        try
        {
            while (true)
            {
                using (TcpClient client = _tcpListener.AcceptTcpClient())
                using (var clientStream = client.GetStream())
                {
                    var msg = new HttpMessage();
                    msg.Receive(clientStream);
                    SendOKResponse(client, "");
                    OnJobRecieved(msg);
                    client.Close();
                }
            }
        }
        catch (System.Net.Sockets.SocketException e)
        {
            // Expected, TcpClient.Stop called                
        }
        catch (System.Threading.ThreadAbortException)
        {
            // Expected, thread going away
        }
        catch (System.IO.IOException)
        {
            // Expected, shutdown while reading
        }
    }

    private void SendOKResponse(TcpClient tcpClient, String responseBody)
    {
        var response = new HttpMessage
        {
            Status = "200",
            Reason = "OK",
            Version = "HTTP/1.1"
        };
        response.Send(tcpClient.GetStream(), responseBody);
    }

    public void Shutdown()
    {
        lock (this)
        {
            if (_listenerThread != null)
            {
                _listenerThread.Abort();
                _listenerThread = null;
            }

            if (_tcpListener != null)
            {
                _tcpListener.Stop();
                _tcpListener.Server.Close();
                _tcpListener = null;
            }                
        }
    }

    #region IDisposable Members

    private void DisposeImpl(Boolean bDisposing)
    {
        lock (this)
        {
            Shutdown();
        }
    }

    public void Dispose()
    {
        GC.SuppressFinalize(this);
        DisposeImpl(true);
    }

    #endregion

}
4

1 に答える 1

1

これは、Windows 上の NLB では、アプリケーションを既定でクラスター化する必要があるためです。そうでない場合 (あなたの場合)、Sticky Sessions を使用する必要があります。どうやら NLB はスティッキー セッションを使用していないため、リクエストはパスごとに異なるサーバーに移動する可能性があります。そのため、これらの例外が発生します (これを見てください)。

それは私自身のプロジェクトの1つで私に起こりました(高性能TCPサーバー-あなたがしていることの反対です)。

于 2013-05-06T21:01:33.027 に答える