我在一个简单的测试应用程序(Visual Studio 控制台应用程序)中遇到了一个奇怪的零星问题,它通过发送简单的 http 请求并计时响应时间来充当托管 aspx 网站(不是应用程序)的看门狗。过去我已经使用了好几个星期,没有这个特殊的问题。在一天中看似随机的时间,我的 http 请求开始失败并出现上述错误。它们似乎是超时,因为失败的请求都需要 60 秒。在按照上述持续错误的一段时间(在一种情况下从几分钟到 90 分钟的随机时间段)之后,错误停止并且 http 响应开始以正常速度(通常大约 0.25 秒)无错误地返回。看门狗客户端请求触发一个非常简单的数据库查找,在服务器端只需 1-2 行代码。
我还可以通过更新主机站点上的任何 .cs 文件随意触发此行为,除其他外,这会导致应用程序池回收。立即我的看门狗应用程序再次开始超时并出现上述错误。
它闻起来像是某种回收的连接问题,因为如果我只是重新启动看门狗应用程序,它就可以正常工作,并且响应开始以正常延迟返回。
我试过设置 request.KeepAlive = false 和 request.ServicePoint.ConnectionLimit = 1,这些都没有帮助。
另一个线索,我无法通过 IIS 管理器连接到托管在此服务器上的两个不同网站中的任何一个,这一直运行良好。我正在尝试通过 IIS 管理器连接“底层连接已关闭”。每次。我已经有一段时间没有更新任何一个网站了,所以这对我没有任何改变。
这是一个在 IIS7 上运行的后端的 asp.net 4 网站,具有集成管道模式的专用应用程序池。
此外,如果我将看门狗应用程序中的 sleeptime 变量更改为 30 秒,则问题不会出现。在我相信 10-20 秒的范围内有一些神奇的数字,如果请求暂停的时间超过这个时间,它们永远不会失败。
我认为 IIS 管理器无法连接这一事实很好地证明了主机端出现问题,与我的测试应用程序无关,但我想在打开支持事件之前覆盖我的基础......尤其是因为我的控制台简单重启应用程序解决了这个问题......至少有一段时间。
class Program
{
//make a simple web request and just return the status code
static string SendHttpMsg(string url, string postData)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(url));
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] byte1 = encoding.GetBytes(postData);
request.ContentLength = byte1.Length;
//request.KeepAlive = false; //no effect
//request.ServicePoint.ConnectionLimit = 1; //no effect
Stream requestStream = request.GetRequestStream();
requestStream.Write(byte1, 0, byte1.Length);
requestStream.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
response.Close();
return ((int)response.StatusCode).ToString();
}
static void Main(string[] args)
{
int sleeptime = 5000;
string result = "";
while (true)
{
DateTime start = DateTime.Now;
try
{
//this is a very simple call that results in a very simple, fast query in the database
result = SendHttpMsg("http://example.com/somepage.aspx", "command=test");
}
catch (Exception ex)
{
//fancy exception handling here, removed
}
DateTime end = DateTime.Now;
TimeSpan calltime = end - start;
Console.WriteLine(end.ToString() + ", " + calltime.TotalSeconds.ToString("F") + " seconds " + result);
Thread.Sleep(sleeptime);
}
}
}