How to kill Umbraco with UrlRewrite.Net
Recently we were contacted by another Norwegian company who inherited a custom Umbraco solution. The original developer is off chasing green fields, so they came to us when the site restarted twice an hour. Something about CPU spikes... It had been upgraded to 7.5.4 and everything, so we could just start off clicking all the shiny new buttons in the health dashboard. Most "known" Azure fixes were already in place, and the rest was applied for good measure. Yet the problem persisted, so we knew we were facing a more dire problem.
Jumping onto the Azure graphs and logs, we could see a pattern of massive memory usage as well as the CPU. Here's a nice bouncy graph of the state of the S3(!) server.
Going through the Umbraco logs, we found several restarts due to out of memory exceptions from seemingly unrelated calls. All of them seemed to correlate with the restarts and massive resource spikes. Some of them came from cached views, so we did an attemt to remove caching from the most varied pages. After all, Umbraco already has the content in memory, so how much CPU goes into rendering it? It was quickly dismissed though, the problem persisted.
We'd also spotted another suspect in the logs, namely UrlRewrite.Net. But at this point we were also ready to throw some profiling tools on the site. Somehow, none of JetBrains' tools worked. For some reason the views could not be rendered. I suspect it has something to do with the caching, profiling views or how the tools work. But I digress. We were able to run VS' profiler on it, and guess who turned up as our main suspect again?
I think the table speaks for it self. The upper two calls are in idling background threads. They don't affect CPU at all. Having the system access the database for one second is within limits for several requests. But the rest of the CPU time was actually spent solely in UrlRewrite.Net and parsing of regular expressions. I could quickly verify we weren't the first seeing this after searching our.umbraco.org too.
Now don't go panic over your own UrlRewrites just yet. This site had more than 2.500 rewritten URLs buried in urlrewrite.config. After being made aware, our contractor cut it down to 150 more generalized regular expressions, and voila, there's been a steady 3% CPU usage since then.
I've been sceptical to people bad-mouthing UrlRewrite.Net in the past. We've never had many problems with it in our sites. But then again, we've never gone past 50 rewrite rules. (I think.) It's a great tool for its purpose, but as we've now witnessed, it can also do great harm when used wrong. It might be time for us to throw out the old IIS 6 servers and start using Microsoft's Url Rewrite Module instead.
But what should we do, then, when faced with situations where we have thousands of URLs to keep 301'ing? I'd guess you've got some kind of pattern there so you can simplify with catching regular expressions like we did here. Otherwise, you're probably better off writing your own small HttpModule with some logic, rather than relying on generic rewriters and regex.