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

c# html-agility-pack stack-overflow

我在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並防止崩潰首先發生?

熱門答案

嘗試這樣的東西, 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頁面啟動和拆除線程,可以將該想法擴展為更高效。



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow