如何防止HtmlAgilityPack中的Stackoverflow异常非常糟糕的html

时间:2015-05-27 16:40:22

标签: c# stack-overflow html-agility-pack

我在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并防止崩溃首先发生?

1 个答案:

答案 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页面启动和拆除一个线程。