Skip to main content

TOTD #84: Using Apache + mod_proxy_balancer to load balance Ruby-on-Rails running on GlassFish

Posted by arungupta on June 17, 2009 at 11:06 AM PDT



TOTD
#81
explained how to install/configure href="http://nginx.net/">nginx for
load-balancing/front-ending a cluster of Rails application running on href="http://rubyforge.org/projects/glassfishgem/">GlassFish
Gem. Another popular approach in the Rails community is to
use Apache HTTPD
href="http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html">mod_proxy_balancer.
A user asked the exact details of this
setup on the href="http://rubyforge.org/forum/message.php?msg_id=82479">GlassFish
Gem Forum. This Tip
Of style="font-weight: bold;">The style="font-weight: bold;">Day (TOTD) will
clearly explain the steps.

  1. Create a simple Rails scaffold and run this application
    using GlassFish Gem on 3 separate ports as explained in  href="http://blogs.sun.com/arungupta/entry/totd_81_how_to_use">TOTD
    #81.
  2. Setup and configure HTTPD and mod_proxy_balancer
    1. Setup and install Apache HTTPD as explained href="http://httpd.apache.org/docs/2.2/install.html">here.
      I believe href="http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html">mod_proxy_balancer
      and other related modules comes pre-bundled with HTTPD, at least that's
      what I observed with Mac OS X 10.5.7. Make sure that the
      "mod_proxy_balancer" module is enabled by verifying the following line
      is uncommented in "/etc/apache2/httpd.conf":


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
      LoadModule proxy_balancer_module
      libexec/apache2/mod_proxy_balancer.so



      Please note another similar file exists in "/etc/httpd/httpd.conf" but
      ignore that one.

    2. Setup a mod_proxy_balancer cluster by adding the
      following fragment in "httpd.conf" as:


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
      <Proxy balancer://glassfishgem>

      BalancerMember http://localhost:3000

      BalancerMember http://localhost:3001

      BalancerMember http://localhost:3002

      </Proxy>



      The port numbers must exactly match with those used in the first step.

    3. Specify the href="http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxypass">ProxyPass directives
      to map the cluster to a local path as:


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
      ProxyPass / balancer://glassfishgem/

      CustomLog /var/log/glassfishgem.log/apache_access_log combined



      The "/" at the end of "balancer://glassfishgem" is very important to
      ensure that all the files are resolved correctly.

    4. Optionally, the following directive can be added to view
      the access log:


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
      CustomLog
      /var/log/glassfishgem.log/apache_access_log combined



      Make sure to create
      the directory specified in "CustomLog" directive.

  3. Now the application is accessible at
    "http://localhost/runlogs". If a new GlassFish instance is started then
    update the <Proxy> directive and restart your HTTPD as
    "sudo httpd -k restart". Dynamic update of BalancerMembers can be
    configured as explained href="http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html#enable">here.

TOTD
#81
started the Rails application in root context. You can
alternatively start the application in a non-root context as:


style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
cellpadding="2" cellspacing="2">
~/tools/jruby/rails/runner > style="font-weight: bold;">../../bin/jruby -S glassfish -e
production -c myapp

Starting GlassFish server at: 10.0.177.178:3000 in production
environment...

Writing log messages to:
/Users/arungupta/tools/jruby-1.3.0/rails/runner/log/production.log.

Press Ctrl+C to stop.

. . .

~/tools/jruby/rails/runner >../../bin/jruby
-S glassfish -e production -c myapp -p 3001


Starting GlassFish server at: 10.0.177.178:3001 in production
environment...

Writing log messages to:
/Users/arungupta/tools/jruby-1.3.0/rails/runner/log/production.log.

Press Ctrl+C to stop.

. . .

~/tools/jruby/rails/runner >../../bin/jruby
-S glassfish -e production -c myapp -p 3002


Starting GlassFish server at: 10.0.177.178:3002 in production
environment...

Writing log messages to:
/Users/arungupta/tools/jruby-1.3.0/rails/runner/log/production.log.

Press Ctrl+C to stop.



and then the ProxyPass directive will change to:


style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
cellpadding="2" cellspacing="2">
ProxyPass /myapp/
balancer://glassfishgem/myapp/



The changes are highlighted in bold. And the application is now
accessible at "http://localhost/myapp/runlogs".



After discussing on href="http://www.nabble.com/Backend-host-port-in-the-log-td24003433.html">Apache
HTTP Server forum, the BalancerMember host/port
can be printd in the log file using a custom log format. So add the
following log format to "/etc/apache2/httpd.conf":


style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
cellpadding="2" cellspacing="2">
LogFormat "%h %l %u %t \"%r\" %>s %b
\"%{Referer}i\" \"%{User-agent}i\"
\"%{BALANCER_WORKER_NAME}e\"" custom



And change the format from the default "combined" to the newly defined
"custom" format as:


style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
cellpadding="2" cellspacing="2">
CustomLog /var/log/glassfishgem.com/apache_access_log
custom



Three subsequent invocations of "http://localhost/runlogs" then prints
the following log entries:


style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
cellpadding="2" cellspacing="2">
::1 - - [17/Jun/2009:10:53:53 -0700] "GET /runlogs
HTTP/1.1" 304 - "-" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5;
en-US; rv:1.9.0.11) Gecko/2009060214 Firefox/3.0.11"
"http://localhost:3002"

::1 - - [17/Jun/2009:10:54:04 -0700] "GET /runlogs HTTP/1.1" 200 621
"-" "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US;
rv:1.9.0.11) Gecko/2009060214 Firefox/3.0.11" "http://localhost:3000"

::1 - - [17/Jun/2009:10:54:05 -0700] "GET /runlogs HTTP/1.1" 304 - "-"
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.0.11)
Gecko/2009060214 Firefox/3.0.11" "http://localhost:3001"



As evident from the last fragment of each log line, the load is
distributed amongst three GlassFish Gem instances. More details on load
balancer algorithm are available href="http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html#scheduler">here.



Feel free to drop a comment on this blog if you are using href="http://glassfish.org">GlassFish in
production for your Rails applications. Several stories are already
available at href="http://blogs.sun.com/arungupta/tags/rubyonrails+glassfish+stories">rubyonrails+glassfish+stories.



Technorati: href="http://technorati.com/tags/glassfish">glassfish
rubyonrails
apache
httpd
mod_proxy_balancer
loadbalancing
clustering

Related Topics >>