Posts Tagged ‘apache’

Deploying Grails - Things I learned from Feedlr

Monday, March 10th, 2008

When I was about to deploy Feedlr on my VPS server there wasn’t much information about the deployment of Grails out there. I know that deploying a Grails war is just like a Java war. But are there going to be any differences? How much memory do I need? Will it eat any more hardware than a plain old Java app? I really have no idea. So this post is about the server stuff I’ve learned by doing the deployment for Feedlr.

I started by deploying my Grails app on Tomcat 6 on a 256M RAM VPS. And since my blogs are also hosted on this VPS, I use mod_proxy_ajp to connect Tomcat to Apache for Feedlr.

My first attempt on the 256 VPS turned out very badly. When I started Tomcat with Feedlr deployed, the server simply becomes very unresponsive and swap activity started flying. That’s a bad sign for “low memory”, I think. So I upgraded the server to 512M RAM and things began to look normal.

Then comes the optimization part. I really don’t have much server tuning experience, especially with a limited resource VPS. So all this is new and interesting to me, solving issues one by one.

The first bad thing happened was that whenever Tomcat ran for a while, like a couple hours, the whole VPS box began to eat a low of swap, and connection will often timeout. I suspected Tomcat, but it turned out to be Apache. The default installation on Ubuntu for Apache + PHP5 uses the Apache mpm_prefork module. The problem is that mpm_prefork spawns multiple Apache instances to handle requests to the server. And the default config is like

<IfModule mpm_prefork_module>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 150
MaxRequestsPerChild 0
</IfModule>

The default config worked fine when I was only hosting a couple blogs on the 256 box. But with a Grails app on Tomcat running, memory becomes critical. So then I changed the settings to smaller numbers and it has been working fine now.

<IfModule mpm_prefork_module>
StartServers 2
MinSpareServers 2
MaxSpareServers 4
MaxClients 150
MaxRequestsPerChild 0
</IfModule>

I will replace mpm_prefork with mpm_worker module since the latter is more efficient for concurrency. Aptitude on Ubuntu can’t figure out for you how to put mpm_worker and PHP5 together so there are some config work to do. Currently I’m running mpm_worker on my development/staging server and it’s working fine but I just don’t know how it’s gonna behave on a low memory environment. BTW. If you have anything to say about this I’m all ears.

Then it’s about Tomcat. Actually Tomcat is working great with Grails out of the box. The tuning is all about memory and efficiency. Here’s my Tomcat startup opts:

CATALINA_OPTS=”-server -Xmx420m -Xms420m -XX:MaxPermSize=128m -Dcom.sun.management.jmxremote”

I set the heap size to 420M since I want to leave some room for my blogs. And so far this setting has worked fine for me. The “-Dcom.sun.management.jmxremote” part is for LambdaProbe which I’m using as the server management app.

Besides, for the production environment, it’s better to set reloadable=”false” for the Tomcat Context of the app. It should be false by default. In this way new code won’t be reloaded on the fly, but it saves quite some server overhead which can be notable on a low memory environment.

And finally, server logging. Here’s my logging settings in Config.groovy. Log files will be saved daily for stdout and stacktrace.

log4j {
    appender.stdout = "org.apache.log4j.ConsoleAppender"
    appender.'stdout.layout'="org.apache.log4j.PatternLayout"
    appender.'stdout.layout.ConversionPattern'='[%r] %c{2} %m%n'

//    	rolling file logger
    appender.logfile = "org.apache.log4j.DailyRollingFileAppender"
    appender.'logfile.File' = "/path/to/public_html/feedlr.com/logs/feedlr_grails.log"
    appender.'logfile.layout' = "org.apache.log4j.PatternLayout"
    appender.'logfile.layout.ConversionPattern' = '%d{[ dd.MM.yy HH:mm:ss.SSS]} [%t] %-5p %c %x - %m%n'

    appender.errors = "org.apache.log4j.DailyRollingFileAppender"
    appender.'errors.layout'="org.apache.log4j.PatternLayout"
    appender.'errors.layout.ConversionPattern'='%d{[ dd.MM.yy HH:mm:ss.SSS]} [%t] %-5p %c %x - %m%n'
    appender.'errors.File'="/path/to/public_html/feedlr.com/logs/feedlr_grails_stacktrace.log" //prod setting
    rootLogger="error,stdout"
    logger {
        grails="info,stdout,logfile" //prod settings
        StackTrace="error,errors"
        org {
            codehaus.groovy.grails.web.servlet="info,stdout,logfile"  //  controllers
            codehaus.groovy.grails.web.pages="info,stdout,logfile" //  GSP
            codehaus.groovy.grails.web.sitemesh="info,stdout,logfile" //  layouts
            codehaus.groovy.grails."web.mapping.filter"="info,stdout,logfile" // URL mapping
            codehaus.groovy.grails."web.mapping"="info,stdout,logfile" // URL mapping
            codehaus.groovy.grails.commons="info,stdout,logfile" // core / classloading
            codehaus.groovy.grails.plugins="info,stdout,logfile" // plugins
            codehaus.groovy.grails.orm.hibernate="info,stdout,logfile" // hibernate integration
            springframework="off,stdout,logfile"
            hibernate="off,stdout,logfile"
        }
    }
    additivity.StackTrace=false
}

P.S. I’m using SliceHost’s VPS and it’s great. I especially love the on-demand slice resizing which will automatically resize your VPS in minutes, with data completely intact. So you can totally start with a frugal setup and grow as needed. And did I mention completely full control over your server? I won’t say more but I know your inner geek would love it once you use it. So if you are seeking some good server space for your project why not give it a try with my referral link :)