【发布时间】:2013-04-30 13:49:56
【问题描述】:
我在 Windows 服务中有一个 TCP 侦听器,它侦听特定端口上的任何传入 TCP 请求并处理消息。直接访问时效果很好。但是一旦它在负载均衡器后面运行(在 Intranet 中),那么它就不会接受任何请求。我收到诸如“无法连接到远程服务器”或“操作超时”之类的错误。一段时间后,服务因“内存不足”异常而终止。请让我知道这可能是什么原因。粘贴下面的代码。我什至也尝试过异步模式(以避免显式线程启动)。但这没有帮助。
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
}
【问题讨论】:
-
根据负载均衡器的类型,可能有多种原因,但很可能负载均衡器不会转发端口,因为它根本不知道它的存在。
-
我同意 Joachim 的分析。此外,您收到 OutOfMemory 异常的事实可能表明您的客户端没有处理不成功的连接尝试优雅地尝试,将对象留在内存中。这可能是一个非常严重的问题。
-
@OnoSendai,如果你看到上面的代码,我正在关闭方法中处理所有对象。我还尝试了异步实现,这也会引发内存不足异常,这是我面临的另一个问题,除了 LB 的主要问题。
标签: c# tcp load-balancing router tcplistener