Service 传入TCP连接的云服务挂起
我正在开发一个云服务工作者角色,用于从许多仪器收集数据。这些仪器大约每分钟随机报告一次数据。服务本身不是性能关键型的,不需要是异步的。当连接尝试失败时,仪器可以在一小时内重新发送数据 我已经为我的云服务尝试了几种实现,包括: 但他们迟早都会挂断我的云服务器,有时会在一小时内挂断。 我怀疑我的代码有问题。我在我的代码中有很多日志记录,但我没有收到任何错误。服务只是停止接收传入的连接 在Azure门户中,服务似乎运行良好。没有错误日志,没有可疑的cpu使用情况等 如果我重新启动服务,它将再次正常运行,直到下次挂起 如果有人能帮我,我将不胜感激Service 传入TCP连接的云服务挂起,service,tcp,Service,Tcp,我正在开发一个云服务工作者角色,用于从许多仪器收集数据。这些仪器大约每分钟随机报告一次数据。服务本身不是性能关键型的,不需要是异步的。当连接尝试失败时,仪器可以在一小时内重新发送数据 我已经为我的云服务尝试了几种实现,包括: 但他们迟早都会挂断我的云服务器,有时会在一小时内挂断。 我怀疑我的代码有问题。我在我的代码中有很多日志记录,但我没有收到任何错误。服务只是停止接收传入的连接 在Azure门户中,服务似乎运行良好。没有错误日志,没有可疑的cpu使用情况等 如果我重新启动服务,它将再次正常运行
public class WorkerRole : RoleEntryPoint
{
private LoggingService _loggingService;
public override void Run()
{
_loggingService = new LoggingService();
StartListeningForIncommingTCPConnections();
}
private void StartListeningForIncommingTCPConnections()
{
TcpListener listener = null;
try
{
listener = new TcpListener(RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["WatchMeEndpoint"].IPEndpoint);
listener.Start();
while (true)
{
_loggingService.Log(SeverityLevel.Info, "Waiting for connection...");
var client = listener.AcceptTcpClient();
var remoteEndPoint = client.Client != null ? client.Client.RemoteEndPoint.ToString() : "Unknown";
_loggingService.Log(SeverityLevel.Info, String.Format("Connected to {0}", remoteEndPoint));
var netStream = client.GetStream();
var data = String.Empty;
using (var reader = new StreamReader(netStream, Encoding.ASCII))
{
data = reader.ReadToEnd();
}
_loggingService.Log(SeverityLevel.Info, "Received data: " + data);
ProcessData(data); //data is processed and stored in database (all resources are released when done)
client.Close();
_loggingService.Log(SeverityLevel.Info, String.Format("Connection closed for {0}", remoteEndPoint));
}
}
catch (Exception exception)
{
_loggingService.Log(SeverityLevel.Error, exception.Message);
}
finally
{
if (listener != null)
listener.Stop();
}
}
private void ProcessData(String data)
{
try
{
var processor = new Processor();
var lines = data.Split('\n');
foreach (var line in lines)
processor.ProcessLine(line);
processor.ProcessMessage();
}
catch (Exception ex)
{
_loggingService.Log(SeverityLevel.Error, ex.Message);
throw new Exception(ex.InnerException.Message);
}
}
}
我刚才做了一个奇怪的观察:
我最近查看了日志,在过去30分钟内没有任何仪器连接,这表明服务已关闭
我通过自己编写的TCP客户端连接到该服务,并上传了一些测试数据
这很有效
当我再次检查日志时,我的测试数据已存储
奇怪的是,其他4台仪器几乎同时连接并成功发送数据
为什么在我连接测试客户机之前,他们不能自己连接
另外,.csdef中的此设置对InputEndpoint IdleTimeOutingMinutes有什么作用
===============================================
编辑:
从几天前开始,我的云服务一直在成功运行
不幸的是,今天早上最后一个日志条目来自以下行:
_loggingService.Log(SeverityLevel.Info, String.Format("Connected to {0}", remoteEndPoint));
在此之后,无法进行其他连接。即使是从我自己的测试TCP客户端也没有得到任何错误,但是没有存储任何数据,也没有新的日志
这使我认为以下代码导致服务挂起:
var netStream = client.GetStream();
var data = String.Empty;
using (var reader = new StreamReader(netStream, Encoding.ASCII))
{
data = reader.ReadToEnd();
}
我读过StremReader的ReadToEnd可以挂起来的地方。这可能吗
我现在将这段代码更改为:
int i;
var bytes = new Byte[256];
var data = new StringBuilder();
const int dataLimit = 10;
var dataCount = 0;
while ((i = netStream.Read(bytes, 0, bytes.Length)) != 0)
{
data.Append(Encoding.ASCII.GetString(bytes, 0, i));
if (dataCount >= dataLimit)
{
_loggingService.Log(SeverityLevel.Error, "Reached data limit");
break;
}
dataCount++;
}
另一种解释可能是数据库中挂着什么东西。我使用SqlConnection和SqlCommand类读取和写入数据库。我总是在最后阻塞后关闭连接
SqlConnection和SqlCommand应该有默认超时,对吗
===============================================
编辑:
在进一步调试之后,我发现当服务没有响应时,它挂起在这行代码上:
while ((i = netStream.Read(bytes, 0, bytes.Length)) != 0)
经过一番挖掘,我发现NetStream类及其读取方法实际上可能会挂起。尽管微软宣称并非如此
我现在已将代码更改为:
Thread thread = null;
var task = Task.Factory.StartNew(() =>
{
thread = Thread.CurrentThread;
while ((i = netStream.Read(bytes, 0, bytes.Length)) != 0)
{
// Translate data bytes to a ASCII string.
data.Append(Encoding.ASCII.GetString(bytes, 0, i));
}
streamReadSucceeded = true;
});
task.Wait(5000);
if (streamReadSucceeded)
{
//Process data
}
else
{
thread.Abort();
}
希望这能阻止绞刑 我想说,部分问题是您正在侦听客户端连接的线程上处理数据。如果另一个客户端启动了某种类型的长时间运行操作,这将阻止新客户端连接。我建议您将处理延迟到工作线程,从而释放侦听器线程以接受新连接 您可能遇到的另一个问题是,如果您的服务抛出错误,那么该服务也将停止接受连接
private static void ListenForClients()
{
tcpListener.Start();
while (true)
{
TcpClient client = tcpListener.AcceptTcpClient();
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
private static void HandleClientComm(object obj)
{
try
{
using(TcpClient tcpClient = (TcpClient)obj)
{
Console.WriteLine("Got Client...");
using (NetworkStream clientStream = tcpClient.GetStream())
using (StreamWriter writer = new StreamWriter(clientStream))
using(StreamReader reader = new StreamReader(clientStream))
{
//do stuff
}
}
}
catch(Exception ex)
{
}
}
我试过穿线。不幸的是,它本身并没有解决挂起问题,尽管它可能会帮助服务变得无响应。有关详细信息,请参阅最新编辑。