我在MVC 5 Web Api中使用HtmlAgilityPack。 99.99%的时间,没有问题...网站加载,我解析它们来提取我想要的文本。我的API每天可能会出现数十万次没有问题。它过去24小时内处理了超过200万次点击...
然而,偶尔形成的网站会导致错误500响应。然后所有后续请求都会出现500个错误,并且该站点将完全无法使用。此方案中唯一的解决方案是重新启动Web应用程序。该站点托管在Windows Azure上。我使用了负载均衡的大型实例,一旦CPU峰值保持高位。过去,这在单个中型Azure实例(2核/ 3.5 GB RAM)上运行良好
错误是Stackoverflow ...我知道我无法抓住。
请注意,此代码不会导致控制台应用程序崩溃
HtmlWeb web = new HtmlWeb();
HtmlDocument doc = web.Load("http://nursingandmidwiferycareersni.com/");
Console.Write(doc.DocumentNode.InnerText);
...但肯定会崩溃一个MVC网络应用程序。
但是,在一个简单的MVC Web应用程序中,我可以使用http://nursingandmidwiferycareersni.com/等站点重现stackoverflow错误。如果您将http://nursingandmidwiferycareersni.com/放入https://validator.w3.org,您将设法在validator.w3.org上获得内部服务器错误!
如果有必要,我会破解HAP源代码来解决这个问题......目前我只是使用Nuget软件包。
是否可以防止HAP中发生堆栈溢出?
或者有没有办法检查可怕的HTML并防止崩溃首先发生?
答案 0 :(得分:1)
尝试使用此类内容,ParseHtml
方法和ParsedHtml
类型只是占位符供您填写:
public async Task<ParsedHtml> TryParseHtml(
string untrustedHtml,
CancellationToken cancellationToken)
{
var tcs = new TaskCompletionSource<ParsedHtml>();
var thread = new Thread(() =>
{
ParsedHtml result = ParseHtml(untrustedHtml);
tcs.TrySetResult(result);
});
thread.Start();
using (cancellationToken.Register(() => tcs.TrySetCanceled()))
{
try
{
return await tcs.Task;
}
catch (OperationCanceledException)
{
thread.Abort();
throw;
}
}
}
通过在成功案例中重用线程,可以扩展这个想法,而不是为每个HTML页面启动和拆除一个线程。