JRuby GA on an Engine Yard Cloud Near You »

Created at: 28.09.2011 16:13, source: Engine Yard Blog, tagged: News Product Technology jruby jruby on appcloud jruby on engine yard cloud trinidad

We are very excited to announce the general availability of JRuby and Trinidad on Engine Yard Cloud!

Everyone who runs production Ruby web applications should be interested in JRuby. Want a list of life-changing reasons? Reasons you cannot get with any other Ruby implementation nor any other Platform as a Service?

Want to try Trinidad/JRuby on your laptop right this very instant? Do this. Do it now:

rvm install jruby
rvm use jruby
git clone git://github.com/engineyard/todo.git
cd todo
bundle
trinidad

Your application is now running in development mode on your laptop!

Want to try Trinidad/JRuby with your own Ruby web app this very instant? Here is a simple tutorial to get started!

Want to learn more about the awesomeness in JRuby and Trinidad (amongst other topics)? In New Orleans this week for RubyConf? Then on Saturday come and see “High Performance Ruby: Evented vs Threaded”.

We are so excited to be able to support JRuby and to finally be offering it and supporting it for big businesses and small on our Engine Yard Cloud and Engine Yard Managed platforms.

For the last two years, Engine Yard has been funding the development of JRuby and we are excited to provide fully supported JRuby for your application development. This is a major milestone for the JRuby project led by Charlie Nutter, Thomas Enebo, Nick Seiger, Hiro Asari, and David Calavera. Charlie has written a great post about the history and next steps of the project here.


more »

Ruby and Passenger News »

Created at: 05.08.2011 03:09, source: Engine Yard Blog, tagged: Product appcloud jruby on appcloud passenger 3 ruby 1.9.2

Our team is working hard to ensure that our customers are using the latest and greatest features for their environments and we’re happy to make a couple of exciting announcements today.

Ruby 1.9.2 is now default

First, Ruby 1.9.2 is now the default Ruby run-time for new AppCloud environments and Free Trial customers. We released Ruby 1.9.2 back in May and think all our customers’ applications will benefit heavily from it. This will not have any impact on existing environments and customers will still be free to choose a different version using the drop down menu.

Passenger 3 is GA

Second, we have just released Passenger 3 into GA and it is now our default app stack! Customers currently using Passenger 2 should see a significant boost when updating to Passenger 3. While Passenger 3 is set as the default, customers using Passenger 2 can continue to select it.

Benefits

  • Performance boost (check out the graph below)
  • Self-Healing via new internal watchdog daemon
  • Fast restarts compared to Passenger 2
  • Asynchronous spawning (no blocking of clients while new instance spawns)
  • Ability to configure minimum number of processes
  • Improved application security
  • Global request queuing as default

Important!

Passenger 3 is not available to environments running Ruby 1.8.6.  Customers are encouraged to upgrade their environments to Ruby 1.8.7 or 1.9.2 first.

JRuby is now in beta

Finally, we released JRuby into public beta for all customers a week ago. You can find more details here.


more »

Leveraging Trinidad and JRuby on AppCloud »

Created at: 08.07.2011 00:08, source: Engine Yard Blog, tagged: Product Technology jruby on appcloud trinidad

As you may recall, we introduced the JRuby beta program a few weeks ago. Today, we'd like to provide more details about Trinidad, the application server used with the JRuby environment. In this post, we'll explain how everybody can take advantage of Trinidad's features and how to enable the best configuration options for our environment.

The configuration file

Trinidad uses a YAML file for configuration. AppCloud generates a default file for each environment that can be overridden when we deploy the application. Here are the few options we add to this file:
    ---
      jruby_min_runtimes: 2
      jruby_max_runtimes: 5
These two lines mean that when we start Trinidad up it configures a runtime pool with at least two JRuby instances for our application. If you need a thread safe environment, you don't have to worry because Trinidad disables these two options and uses a single runtime that works just fine with your thread safe application. We keep this file under a shared directory, the same one where we keep the configuration files for the application, so we just need to add our custom trinidad.yml file under the application's configuration directory and deploy the application as usual. Each time we modify the file, AppCloud will restart the server rather than perform a hot deploy, so our changes will be automatically applied. We don't apply any restriction to configure Trinidad, so any option or feature described on Trinidad's wiki can be used on AppCloud, even extensions.

Introducing Trinidad diagnostics extension

Trinidad diagnostics is a plugin that uses JRuby-lint under the hood to inspect our application and let us know whether the application has any incompatibility issues to run with JRuby. For instance, if we will know if we are using a gem that's not fully compatible with JRuby, or if we are using libraries which behavior diverges from MRI. JRuby-lint generates an html report file with all the messages for our application, and the extension keeps it under the application's public directory, thus, we can access it from a browser. We just need two steps to enable this plugin for our AppCloud environment, actually the same two steps that we need to enable it for any other environment. First, add the gem to the application's Gemfile:
    gem 'trinidad_diagnostics_extension'
Second, add it to our custom configuration file:
    ---
      extensions:
        diagnostics:
After deploying the application again, we'll have the generated report available under the path `/diagnostics.html`.

Recap

In this post, we've just scratched the surface of all that Trinidad has to offer us. Whether we need to modify our HTTP connector to allow long non-blocking requests, or use an advanced task scheduler, we just need to add them to our custom configuration file.


more »

JRuby on AppCloud Available Through Beta Program »

Created at: 25.05.2011 04:39, source: Engine Yard Blog, tagged: cloud Product Technology Engine Yard Beta Program jruby jruby on appcloud trinidad

We’re overjoyed to announce that customers can now sign up to use JRuby with Engine Yard AppCloud through our beta program. Engine Yard has been a strong supporter of the JRuby project and we’re thrilled that we can now begin offering JRuby support to our customers. There are two camps of customers demanding JRuby:

  • Applications that desire to incorporate Java libraries
  • Developers wanting features that MRI cannot provide – real threads, a selection of modern garbage collectors, in-process caching, and full utilization of available memory, as starters.
A key enabler for JRuby support is Trinidad. Trinidad allows you to run rails or rack compatible applications within an embedded Apache Tomcat, and it is the creation of Engine Yard’s David Calavera. Switching to Trinidad and JRuby in local development is very easy:
  1. Add to your Gemfile:
      platforms :jruby do
        gem 'activerecord-jdbc-adapter'
        gem 'jruby-openssl'
        gem 'jdbc-mysql', :require => false
        gem 'trinidad'
      end
      platforms :ruby do
        gem 'mysql2'
      end
  2. Install and switch to JRuby:
    $ rvm install jruby
    $ rvm jruby
    $ bundle
  3. Launch your Ruby application with Trinidad (it auto-detects what sort of Ruby web application you have):
    $ trinidad
  4. Open http://localhost:3000 in your browser and wait for the Tomcat application server to boot up, then you are good to go.
  5. Commit the Gemfile & Gemfile.lock changes (possibly to a branch)
  6. Deploy to staging environment on AppCloud setup with JRuby. There are some additional instructions and limitations in the Trinidad/JRuby documentation.
It is strongly suggested you trial your application against JRuby locally first, then in an AppCloud staging environment, and then upgrade your production environment. As a feature under the beta program, we will endeavor to provide all JRuby users with feedback and support via the ey-beta-talk mailing list. It is our intent to stabilize our JRuby integration as soon as possible and move it into General Availability (and thus fully supported under Engine Yard Support programs).

Full House of Rubies

Personally, I’m more than overjoyed. With JRuby now available on AppCloud, Engine Yard is the first Ruby platform to make available all stable, production-ready Ruby implementations; most notably JRuby and Rubinius.

OSS Grant for David Calavera

I would also like to announce that earlier this year Engine Yard offered David Calavera an Engine Yard OSS Grant towards the Trinidad project. This has allowed David to travel to Baltimore last week to speak at RailsConf. We’re excited to continue to help David spread the word about Trinidad – it is our favorite “JRuby in a Box” solution!


more »

Taking Stock of JRuby Web Servers »

Created at: 24.03.2011 19:41, source: Engine Yard Blog, tagged: Open Source aspen jboss netty jruby jruby on appcloud jruby-rack kirk mizuno torquebox trinidad warbler web servers

One of the more frequent questions that new JRubyists ask is "Which server should I use to build and deploy my application?" I'm glad you asked! But first, I need to know a little more about you, your environment, and your deployment needs. Do you have an existing Java environment? Do you prefer to make sure you're using the same components for both development and production? Do you like rolling your own servers? Do you like experimentation? Do you like running background services in the same process? How about zero-downtime redeployments? Read on, we have something for everybody.

You have an existing Java web server

Maybe your organization is already Java-heavy, or you have an operations team that's familiar with operating an existing Java server. That's fine! In that case, JRuby-Rack is what you need. JRuby-Rack is the foundation that enables Ruby applications to run on virtually any existing Java web server. Put simply, JRuby-Rack is a bridge from the Java Servlet API to Ruby's Rack API. So if you have a Servlet container (and pretty much every widely-used Java server in existence has one), you can run any Rack application with JRuby-Rack. We regularly test JRuby-Rack with Tomcat 6/7, Jetty 6/7, JBoss 5/6, Resin 4, and GlassFish 3, so chances are good that your application will run fine on your server. JRuby-Rack is also the hidden engine behind Warbler, the tool that quickly assembles a full .war file from your Ruby application. When you run warble, Warbler includes a copy of JRuby-Rack in the final assembled archive and wires up the RackFilter Servlet filter that delegates requests to your Ruby application. In addition to managing the lifecycle of your Ruby application inside the Java web server, JRuby-Rack has accumulated a number of useful extensions over its three-year life. Here are three.

Response streaming

Say you'd like to do some early flushing of your response. With JRuby-Rack, simply set the Transfer-Encoding: chunked header in the response, and JRuby-Rack will flush each element of the response body individually. (A word of caution: Aaron Patterson reports how the Rack API doesn't support this very well, so make sure you know what you're doing.) Here's a Sinatra example that perpetually reports the server time in a series of JSON chunks:
class ServerTime
  def initialize(response)
    @boundary = 'MultipartBody'
    response['Content-Type'] = "multipart/mixed; boundary=\"#{@boundary}\""
    response['Transfer-Encoding'] = 'chunked'
  end

  def chunk(content_type, body)
    "--#{@boundary}\nContent-Type: #{content_type}\n\n#{body}\n"
  end

  def each
    loop do
      yield chunk("application/json", "{\"currentTime\":\"#{Time.now.strftime '%H:%M:%S'}\"}")
      sleep 2
    end
  end
end

get '/servertime' do
  ServerTime.new(response)
end

A more efficient X-Sendfile

You can also use a Ruby File or Tempfile object as the response body, and JRuby-Rack will write it to the response using the Java NIO FileChannel#transferTo method, which, depending on the OS, can transfer bytes directly from the filesystem cache to the target channel without actually copying them. JRuby-Rack will close the file after the request is finished so you don't have to worry about leaking the resource.

Interaction with Servlets

You can use the JRuby-Rack RackFilter alongside other servlets or JSPs in a Java web application. For example, you can internally redirect from Ruby to another servlet. JRuby-Rack adds a custom #forward_to method to Rails' ActionController:
class JspController < ApplicationController
  def index
    servlet_request['message'] = 'Hello from Rails!'
    forward_to '/jsp/index.jsp'
  end
end
Inside public/jsps/index.jsp, we can consume the message attribute as follows:
<html>
  <head><title>Rails with JSPs</title></head>
  <body>
    <h1><%= request.getAttribute("message") %></h1>
  </body>
</html>
With this technique it's easy to introduce Rails as the routing and controller layer on top of an existing Java web application. We'll be writing much more about integrating Ruby alongside Java web applications in the near future, so watch this space.

You want to distribute your application

Warbler comes with a feature dubbed executable war, which builds a .war file that can be deployed in a container or run as an self-contained executable. Warbler embeds Winstone, a small servlet container, in the archive that self-extracts and listens at localhost:8080 when run:
$ warble executable war
rm -f sinatra.war
Creating sinatra.war
$ java -jar sinatra.war
[Winstone 2011/03/07 12:40:58] - Beginning extraction from war file
[Winstone 2011/03/07 12:40:59] - WARNING: The Servlet 2.4/2.5 spec XSD was unavailable inside the winstone classpath. Will be retrieved from the web if required (slow)
[Winstone 2011/03/07 12:40:59] - No webapp classes folder found - /private/var/folders/CA/CAMqlEcnEmSLCKPW5k22oE+++TI/-Tmp-/winstone5711860033631390551webroot/sinatra.war/WEB-INF/classes
[Winstone 2011/03/07 12:41:05] - HTTP Listener started: port=8080
[Winstone 2011/03/07 12:41:05] - Listener winstone.ajp13.Ajp13Listener not found / disabled - ignoring
[Winstone 2011/03/07 12:41:05] - Listener winstone.ssl.HttpsListener not found / disabled - ignoring
[Winstone 2011/03/07 12:41:05] - Winstone Servlet Engine v0.9.10 running: controlPort=disabled
The executable archive is completely self-contained, so you can distribute it and run it anywhere a Java Virtual Machine is installed. Up to this point, we've learned that Warbler and JRuby-Rack are great for deploying across a wide range of environments, but what about development? When you're coding a new application, it would be mighty painful  to generate a .war file and deploy it after every change. Rubyists are used to firing up a web server, writing code, and hitting the refresh button. JRuby certainly supports this mode, but with a different cast of characters than you know from the C Ruby world. Let's take a look at five JRuby servers that fill different needs.

You want uniformity across environments

Unlike WEBrick, the server included in Ruby's standard library, Trinidad by David Calavera is equally suited for development and production use. Written in pure Ruby, Trinidad is built by employing JRuby-Rack and Apache Tomcat as embedded Java libraries. To try out Trinidad, simply gem install trinidad and start the server with the trinidad command. Trinidad is the most mature of the JRuby web servers, and most familiar in feel to other Ruby servers. trinidad -e production -p 3001 does what you expect. In addition, JRuby-specific options like --threadsafe, --classes, and --jars are easily accessible. You can also customize Trinidad with extensions. Currently there are lifecycle, daemon, hotdeploy, and sandbox extensions available.  Also notable is the brand new scheduler extension, developed by Brandon DeWitt, and is the first extension developed by someone other than David, showing growth in the Trinidad community beyond its primary maintainer.

You want a light, customizable server

Mizuno, by Don Werve, is a great example of how easy it is to leverage an existing Java library in a very small amount of code. Mizuno is advertised as "a set of Jetty-powered running shoes for JRuby and Rack", and clocks in at a svelte 335 lines of pure Ruby code. Size does not matter in this case though, as Mizuno manages to turn in good performance numbers as well. Try out the Mizuno gem and if you're thinking of writing a custom server, take a look at the Mizuno codebase as a starting point.

You like playing with asynchronous APIs

Kevin Williams has been hacking on his server, Aspen, for a while now, and has recently kicked it up a notch. Aspen's approach is to mimic the design of the Ruby web server Thin using the JBoss Netty asynchronous event-driven network application framework. If a JVM-based, Ruby-flavored Node.js is up your alley, get in touch with Kevin and take a look at Aspen.

You want a full-stack solution

TorqueBox, from the fine folks at RedHat, provides an all-in-one solution by building on top of the JBoss application server. According to the FAQ:
[TorqueBox] attempts to go beyond providing web-centric services (supporting Rails, Rack, Sinatra, etc), to also expose other enterprise-grade services to Ruby applications.
One of the niceties of TorqueBox's full-stack solution is integrated messaging and asynchronous tasks. Backgrounding is as simple as creating a task class in app/tasks/email_task.rb:
class EmailTask < TorqueBox::Messaging::Task
  def send_hello(payload)
    puts "EmailTask: sent hello email with #{payload.inspect}"
  end
end
and invoking it:
class HelloController < ApplicationController
  def index
    EmailTask.async(:send_hello, params[:message])
  end
end
This is much better than simply launching a background thread or even a subprocess, because behind the scenes TorqueBox creates a queue for your task on the internal HornetQ message bus and invokes an instance of the task class on the receiving end of the queue. If the server happens to crash, you're much less likely to lose the task. So if you're familiar with JBoss or like the idea of having a wider platform to build messaging and other background infrastructure all in Ruby, TorqueBox is definitely worth a look.

You want zero-downtime deploys

Kirk, at two months old the youngest entry in the JRuby server category, is brought to us by Carl Lerche of Rails core and Bundler fame. The key use case for Kirk is zero-downtime deploys in the same fashion as Passenger or Unicorn. Applications deployed in Kirk can be redeployed either by command-line or by updating files that Kirk is configured to watch. Kirk deployments are configured with a Kirkfile (facepalm!). Here's a simple example:
rack "rails3/config.ru" do
  listen 9090
end

rack "sinatra/config.ru" do
  listen 9091
end

rack "camping/config.ru" do
  listen 9092
end
As you surely guessed, this starts up three socket listeners on ports 9090-9092, all inside a single JVM. Each application is redeployable on its own, or all at once if you configure them to watch the same file. If you redeploy while the application is servicing requests, Kirk warms up the new version of the application and swaps it in atomically. In a stress test, I compared response rates between a stable application and one that continuously redeploys every two seconds. The stable server performed at a rate of 285 replies per second:
$ httperf --port 9292 --uri /env --num-conns 500 --num-calls 20
httperf --client=0/1 --server=localhost --port=9292 --uri=/env --send-buffer=4096 --recv-buffer=16384 --num-conns=500 --num-calls=20
httperf: warning: open file limit > FD_SETSIZE; limiting max. # of open files to FD_SETSIZE
Maximum connect burst length: 1

Total: connections 500 requests 10000 replies 10000 test-duration 34.972 s

Connection rate: 14.3 conn/s (69.9 ms/conn, <=1 concurrent connections)
Connection time [ms]: min 61.1 avg 69.9 max 357.4 median 66.5 stddev 15.9
Connection time [ms]: connect 0.3
Connection length [replies/conn]: 20.000

Request rate: 285.9 req/s (3.5 ms/req)
Request size [B]: 65.0

Reply rate [replies/s]: min 220.8 avg 284.9 max 305.6 stddev 32.6 (6 samples)
Reply time [ms]: response 3.5 transfer 0.0
Reply size [B]: header 113.0 content 6893.0 footer 0.0 (total 7006.0)
Reply status: 1xx=0 2xx=10000 3xx=0 4xx=0 5xx=0
The coutinuous-redeploy version responded to every request but dropped to a rate of 90 replies per second. Obviously redeploys aren't free, but as long as you don't deploy new code every two seconds (!), you won't see a noticeable slowdown.
$ httperf --port 9292 --uri /env --num-conns 500 --num-calls 20
httperf --client=0/1 --server=localhost --port=9292 --uri=/env --send-buffer=4096 --recv-buffer=16384 --num-conns=500 --num-calls=20
httperf: warning: open file limit > FD_SETSIZE; limiting max. # of open files to FD_SETSIZE
Maximum connect burst length: 1

Total: connections 500 requests 10000 replies 10000 test-duration 111.636 s

Connection rate: 4.5 conn/s (223.3 ms/conn, <=1 concurrent connections)
Connection time [ms]: min 63.7 avg 223.3 max 5839.1 median 161.5 stddev 337.7
Connection time [ms]: connect 1.6
Connection length [replies/conn]: 20.000

Request rate: 89.6 req/s (11.2 ms/req)
Request size [B]: 65.0

Reply rate [replies/s]: min 8.4 avg 90.2 max 169.8 stddev 34.7 (22 samples)
Reply time [ms]: response 11.1 transfer 0.0
Reply size [B]: header 113.0 content 6908.0 footer 0.0 (total 7021.0)
Reply status: 1xx=0 2xx=10000 3xx=0 4xx=0 5xx=0

Bright Future

There's certainly a swarm of activity in JRuby web server land, and you can count on seeing a few of these options appear in future JRuby offerings on the Engine Yard AppCloud. If you haven't yet tried running your application with JRuby, stay tuned. My session at RailsConf 2011 covers porting to JRuby and you can rest assured that we'll cover the details in a future article as well. Let us know in the comments about your preferred way of deploying JRuby applications, or tell us frankly what's holding you back from deploying with JRuby so we can correct those issues!


more »