2013-05-06 101 views
0

我在Windows服务中有一个TCP监听器,用于监听特定端口上的任何传入TCP请求并处理该消息。它直接访问时工作正常。但是,一旦它运行在负载平衡器(在Intranet中)后面,它就不会接受任何请求。我收到“无法连接到远程服务器”或“操作超时”等错误。一段时间后,服务终止,出现“内存不足”异常。请让我知道这可能是什么原因。粘贴下面的代码。我甚至尝试了异步模式(以避免显式线程启动)。但这并没有帮助。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 

} 
+0

根据负载平衡器的类型,可能有几个原因,但最有可能的是负载平衡器不转发端口,因为它只是简单地不知道它的存在。 – 2013-05-06 18:40:02

+0

我同意约阿希姆的分析。此外,您收到OutOfMemory异常的事实可能表明您的客户端没有处理不成功的连接,因此会优雅地尝试将对象留在内存中。这可能是一个非常严重的问题。 – OnoSendai 2013-05-06 19:02:11

+0

@OnoSendai,如果您看到上面的代码,我将在关闭方法中处理所有对象。我也试过异步实现,这也抛出了内存异常,这是我除了与LB的主要问题之外我面临的另一个问题。 – RKP 2013-05-07 06:52:55

回答

1

这是因为NLB在Windows需要你的应用程序是一个聚集一个默认。如果不是(这是你的情况),你必须使用粘滞会话。显然你的NLB没有使用粘滞会话,所以请求可能会在每次通过时传送到不同的服务器。这就是为什么你会得到这些例外(看看this)。

这发生在我自己的项目之一(一个高性能的TCP服务器 - 与你正在做的相反)。

+0

感谢您的回复。正如我所说我尝试将代码更改为异步模式(使用回调)。但是,我仍然得到这些内存不足的例外。我检查了这个链接http://stackoverflow.com/questions/6023264/high-performance-tcp-server-in-c-sharp在这个网站,这也是建议去异步 – RKP 2013-05-07 03:59:44

+0

你说我的应用程序需要聚集一个。那是什么意思?请解释 – RKP 2013-05-07 04:00:46

+0

我已经阅读了文章,并且没有使用任何会话。每个传入的TCP请求都可以独立处理,而不需要维护内存中先前请求的任何状态。所以“无亲和力”模式对我来说很合适 – RKP 2013-05-07 06:47:25