Railo and mod_cfml

The way Railo works with Tomcat is quite different to Adobe ColdFusion (ACF), and the differences can be pretty important if you have a lot of virtual hosts.

I don’t want to go into the gory details about how Tomcat works, but a few background points:

  • Tomcat has a virtual host concept analogous to web server virtual hosts, where there’s a default host and then specific host configurations tied to defined hostnames.
  • Tomcat’s virtual host configuration is completely independent of the front end web server (e.g. Apache or IIS)
  • Within each virtual host is at least one “context”, which essentially maps to a classloader and a set of resources (e.g. a directory on the filesystem).

All of this is quite different to the way webservers work, so Railo and ACF both try to hide it from you, in different ways.

ACF sets up Tomcat with just the default virtual host and a single default context. The default host will handle any request not bound to some other host, so with no further configuration every hostname ends up in the default Tomcat host and context. Simple and easy. In effect, your entire ColdFusion environment, multiple hostnames, multiple applications, the whole shebang, lives inside a single Tomcat context.

This is decidedly not idiomatic from a Java servlet container point of view, where each application gets at least its own context. Among other things, this allows the application to define its own classpath, thus isolating applications from issues like JAR conflicts with other applications. So Railo takes this path – each ColdFusion application maps to a Tomcat application, with its own context. That means Tomcat must be configured for each and every hostname and application folder.

But wait – ColdFusion is supposed to hide all unpleasant details, isn’t it? CF developers shouldn’t need to know or care about Java-specific stuff like servlet container configuration, right? So Railo introduces another piece, mod_cfml. The Railo installer configures this by default, and what it does is watch for unrecognised hostnames and create new Tomcat contexts for them on the fly. Pretty neat trick really, and it makes Railo just as seamless and noob-friendly as ACF. Until…

Until you migrate an environment with hundreds of virtual hosts from ACF to Railo. At which point, several things might start to cause problems:

  1. Context memory overhead: it may be only 1-2MB per context, but that’s enough that your site that hummed along nicely in a 512MB JVM is now completely unresponsive with memory stress.
  2. Context startup time: on my anemic dev box, it takes mod_cfml 30 seconds to create a new context, and over a minute to validate an existing context after a server restart. Even a fairly beefy staging box only brings that down to 10 seconds per context. Multiply that by 500, and you’ve got a problem.
  3. Context creation throttling: because of these overheads, mod_cfml throttles context creation to avoid becoming a DoS vector. By default, you get one context creation per 30 seconds up to a maximum of 200 contexts per 24 hour period. You’ll simply get a 503 error on every virtual host after the first 200.
  4. Context restart: this deserves a separate dot point – mod_cfml “creates” every context the first time it is hit after a restart, even if it already exists. That means that even if you have fewer than 200 virtual hosts, you can hit the limit simply by restarting the Railo service. Sites that worked before the restart suddenly become unresponsive after the restart.

What to do? There are, as always, options:

You can beef up your environment. Make sure you have enough memory, enough CPU, adjust the mod_cfml throttling settings, and preload all the contexts by hitting them once after each server restart (so your users don’t get the delay). Of course you’re now busy fiddling with servlet container configuration, so mod_cfml isn’t earning its keep from a simplification point of view.

You can just ditch mod_cfml and use mod_proxy or whatever-it-is-on-IIS, and then configure Tomcat manually. This lets you group virtual hosts into shared contexts (as per ACF), thus avoiding the issues that come with uncontrolled proliferation of contexts. To be honest, when I installed Railo I took one look at mod_cfml and said “No thanks” – and that was before I knew about the gotchas listed above. I reckon if you can configure a web server, you can configure a servlet container, so mod_cfml just isn’t solving any problem that I have.

Or, you can manually configure Tomcat to recognise all your existing virtual hosts, but keep mod_cfml around to pick up any new hostnames. This can be handy if you add hostnames (say, one hostname per client) on a daily basis. The new ones will all get a context each, but to control this you can periodically add the new hostnames to your shared context and delete the standalone contexts.

Leave a comment if you want me to post a detailed how-to for any of these options.

Edit: more detail on configuration tweaks

5 thoughts on “Railo and mod_cfml

  1. After grappling with this ourselves, and coming to the conclusion that we should never use mod_cfml in a production environment, we have configured our servers with a single Tomcat host and a context path per application. We then have nginx in front of that dealing with mapping domains to context paths.

    The benefit to this approach is that the nginx virtual hosts configuration we created can be reloaded instantly without downtime; whereas changes to Tomcat’s configuration require a restart which causes a headache in just about any environment. We can deploy new applications without any interruption to services and little (or no, in the case of dev and staging) extra server configuration.

    The potential downside is that your applications need to be smart about how they build their URLs, in particular, how they deal with context path. This isn’t an issue for the applications we host on this system but is worth thinking about.

    Anyways, it probably deserves a blog post.

  2. @Dominic, it’d be interesting to hear more about how you deploy without interruption. I’m guessing you’re just adding context files to conf/Catalina/<host>, right? Or do you in fact have a fixed set of contexts with a floating population of virtual hosts in front of those?

    Of course it’s not strictly true that Tomcat config changes always require a restart. Context loading and reloading does not, which is why mod_cfml works in the first place. However, in my case, I use a lot of host aliases, and AFAIK there’s no way to add these without a restart.

  3. Jamie and Dominic, as a Railo newbie I’d be very grateful for more detail on your approaches. My instinct tells me I don’t want mod_cfml even though it hasn’t bitten me in development yet. In production though I definitely don’t want downtime on every config change.


  4. Julian,
    If you’re not comfortable with messing with Tomcat config, or you aren’t going to have lots of virtual hosts (say, more than 50), I’d recommend you stick with the default configuration. mod_cfml really doesn’t present any issues in that case. I certainly wouldn’t want to give the impression that mod_cfml is somehow flaky.

    Otherwise, stay tuned for a follow up post with more detail.

    Oh, and np re the name – I’m pretty used to it 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *