tag:blogger.com,1999:blog-68439902169390518012017-09-13T03:16:22.390-07:00Deploying with JRubyJoe Kutnerhttp://www.blogger.com/profile/02791715457347394080noreply@blogger.comBlogger10125tag:blogger.com,1999:blog-6843990216939051801.post-25642265498078531432014-12-04T12:23:00.000-08:002014-12-05T07:59:48.551-08:00Using Puma, Rails 4 and JRuby on HerokuThe state of JRuby deployment has improved quite a bit since I wrote my book. But information on setting up a new environment still seems hard to come by. I've encountered a number of folks who have tried to set up a deployment environment using guides that are directed at MRI (C Ruby) users. Let's fix that, shall we...<br /><br />In this post, I'll walk you through the basic steps for setting up Rails 4 to run with Puma under JRuby. Then you'll learn how to deploy that app on Heroku.<br /><br /><h3><b>Creating a New App</b></h3><br />First, let's create a brand new Rails 4 application. Make sure you have JRuby installed and are using it, like this:<br /><br /><script src="https://gist.github.com/jkutner/7f1f271c579ebdab4c31.js?file=jruby.sh-session"></script>Now install the Rails 4 Gem and create a new Rails application:<br /><br /><script src="https://gist.github.com/jkutner/7f1f271c579ebdab4c31.js?file=rails.sh-session"></script>Because this application was created under JRuby, a nice set of defaults have been configured for you. Gems like "therubyrhino" and "activerecord-jdbc" are already in your application's Gemfile.<br /><br />But the new application does not have a production ready web server. That's were Puma comes in.<br /><br /><h3>Using and Configuring Puma</h3><br />Move into the root directory for your new application and open the Gemfile. You'll probably see a commented out line for the "unicorn" gem. Delete it. JRuby and Unicorn are a bad combination (if they even work together at all).<br /><br />Now add the following line to the Gemfile to make Puma a dependency:<br /><br /><script src="https://gist.github.com/jkutner/7f1f271c579ebdab4c31.js?file=Gemfile.rb"></script>Run <span style="font-family: &quot;Courier New&quot;,Courier,monospace;">bundle install</span> at the command line to install the Gem.&nbsp; Then configure Puma by creating a <span style="font-family: &quot;Courier New&quot;,Courier,monospace;">config/puma.rb</span> file and putting the follow code in it:<br /><br /><script src="https://gist.github.com/jkutner/7f1f271c579ebdab4c31.js?file=puma.rb"></script>This will set the port, environment, and thread pool size based on environment variables. The defaults are intended for development. <br /><br />Because Puma is a multi-threaded server, and JRuby has real threads, you'll want to configure your database connection pool size appropriately. To do this, create a <span style="font-family: &quot;Courier New&quot;,Courier,monospace;">config/initializers/database_connection.rb</span> file, and put the following code in it:<br /><br /><script src="https://gist.github.com/jkutner/7f1f271c579ebdab4c31.js?file=database_connection.rb"></script>Setting your maximum pool size to the number of threads is a good default.<br /><br />Now run the application with this command:<br /><br /><script src="https://gist.github.com/jkutner/7f1f271c579ebdab4c31.js?file=puma.sh-session"></script>Your application is running, and you can see it by browsing to <a href="http://localhost:3000/">http://localhost:3000</a>. You'll probably get an error if you haven't connected the application to a database. You can do that locally, or you can use a free one from Heroku.<br /><br /><h3>Deploying to Heroku</h3><br />Heroku is a Platform-as-a-Service that supports both Ruby and Java applications. Naturally, it also supports JRuby. To start using Heroku, follow <a href="https://toolbelt.heroku.com/">this guide for installing the Heroku toolbelt</a> and creating an account. This will provide you with a <span style="font-family: &quot;Courier New&quot;,Courier,monospace;">heroku</span> command that you can use to create and deploy apps for free!<br /><br />To start, make sure your project is under version control with Git by running these commands:<br /><br /><script src="https://gist.github.com/jkutner/7f1f271c579ebdab4c31.js?file=git.sh-session"></script>Now you need to tell Heroku how to run your app. Do this by placing the command you ran earlier in a <span style="font-family: &quot;Courier New&quot;,Courier,monospace;">Procfile</span> in the root directory of your project. Create the <span style="font-family: &quot;Courier New&quot;,Courier,monospace;">Procfile</span> and put this code in it:<br /><br /><script src="https://gist.github.com/jkutner/7f1f271c579ebdab4c31.js?file=Procfile"></script>You'll also need to configure the Ruby runtime in your Gemfile (in this case its JRuby) by adding this line:<br /><br /><script src="https://gist.github.com/jkutner/7f1f271c579ebdab4c31.js?file=Gemfile2.rb"></script>Add the changes to Git by running these commands:<br /><br /><script src="https://gist.github.com/jkutner/7f1f271c579ebdab4c31.js?file=git-add.sh-session"></script>Next, create a Heroku app for the project and make your first deployment by running these command:<br /><br /><script src="https://gist.github.com/jkutner/7f1f271c579ebdab4c31.js?file=heroku-create.sh-session"></script>Heroku has detected that your application uses JRuby, it installed the JDK, ran bundler and launched your web process. If you were to open the app by running <span style="font-size: small;"><span style="font-family: &quot;Courier New&quot;,Courier,monospace;">heroku open</span></span> you'll probably get an error, because the default landing page is disabled in this environment. But you can create standard Rails templates by running <span style="font-size: small;"><span style="font-family: &quot;Courier New&quot;,Courier,monospace;">rails generate controller welcome</span></span> as you would with MRI.<br /><br />There is a great deal more that Heroku can do for you. You can provision a database, a queuing system, a scheduler, monitoring tools, or even telephony services. And of course, you can begin to leverage the power of the JVM for your Ruby app. <br /><br />You can download the complete source code for the application presented in this article from the <a href="https://github.com/kissaten/heroku-jruby-rails-4">heroku-jruby-rails-4 repo on Github</a>.Joe Kutnerhttp://www.blogger.com/profile/02791715457347394080noreply@blogger.com8tag:blogger.com,1999:blog-6843990216939051801.post-79965620890429677042013-07-22T13:16:00.000-07:002013-07-22T15:41:16.154-07:00Why JRuby Arrays are not ThreadsafeRun <a href="https://github.com/jruby/jruby-lint">JRuby-Lint</a> against one of your Rails projects and you'll probably see this message:<br /><br /><script src="https://gist.github.com/jkutner/6056579.js?file=jrlint.sh"></script> It's a warning that the statement below is a potential problem in multi-threaded applications because it's appending values to an Array.<br /><br /><script src="https://gist.github.com/jkutner/6056579.js?file=application.rb"></script> <div class="p2">Rails is thread safe, so this line of code won't be a problem. But JRuby-Lint must warn us because it's impossible to write a program that determines if some code is absolutely thread safe. In your own code, however, you won't have the same guarantee. That's because JRuby uses a different threading model than MRI. It has a big impact on performance, but it also makes the Array class a little different.</div><div class="p1"><br /></div><div class="p2">Threads in MRI are encumbered by a mechanism called the Global Interpreter Lock (GIL), which is also known as the Giant VM Lock (GVM). The GIL allows only one thread in the process&nbsp;to execute Ruby code at a time. It does this very efficiently but it will never allow Ruby threads to run in&nbsp;parallel. As a result, there will be little to no increase in speed&nbsp;when running on a multiprocessor machine, which is the case for most production servers. To illustrate this, consider the figure below.</div><div class="p1"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-ESI6NhVmj6s/Ue2IevaXIxI/AAAAAAAABEk/fHe_oHbxRoY/s1600/threads.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="237" src="http://1.bp.blogspot.com/-ESI6NhVmj6s/Ue2IevaXIxI/AAAAAAAABEk/fHe_oHbxRoY/s400/threads.png" width="400" /></a></div><div class="p2"><br /></div><div class="p1"><br /></div><div class="p2">Each user thread in the JVM, which is just an instance of the Thread class, is mapped directly to a kernel thread. Kernel threads are scheduled and managed by the operating system kernel, which can schedule two threads from the same process to run on two different CPU cores at the same time. The GIL prevents this from happening.</div><div class="p1"><br /></div><div class="p2">So getting back to the += operation described earlier, let's look at an example that is not thread safe. Put the following code, which populates an array with 256 integers, into a file called <span style="font-family: Courier New, Courier, monospace;">threads.rb</span>.</div><br /><script src="https://gist.github.com/jkutner/6056579.js?file=threads.rb"></script> <div class="p2">It uses &lt;&lt; to append to the array, which presents the same problem as the += operator. When we run&nbsp;<span style="font-family: 'Courier New', Courier, monospace;">threads.rb</span>&nbsp;with MRI, we see the following:</div><br /><script src="https://gist.github.com/jkutner/6056579.js?file=mri.sh"></script> <br /><div class="p2">The array was correctly populated with 256 integers. But when we run the same program with JRuby, we might see the following (though probably not exactly):</div><br /><script src="https://gist.github.com/jkutner/6056579.js?file=jruby.sh"></script> <br /><div class="p2">In fact, nearly every time we run the program with JRuby we could get a different result. And we might even encounter a ConcurrencyError. That's because the threads in our program are running in parallel and can corrupt the array. Arrays are not threadsafe in JRuby. They aren't in MRI either. But when we ran the program with MRI, the GIL prevented the threads from executing concurrently. Thus, the array was not corrupted.</div><div class="p1"><br /></div><div class="p2">The following statement is the critical section:</div><br /><script src="https://gist.github.com/jkutner/6056579.js?file=critical.rb"></script> <br /><div class="p2">Even though it is a single statement, it actually involves multiple steps. Both the Java code in JRuby and the C code in MRI implement methods on the Array class that do essentially the same thing as this pseudo-code:</div><br /><script src="https://gist.github.com/jkutner/6056579.js?file=append"></script> <br /><div class="p2"><span class="Apple-tab-span"> </span>In JRuby, you can see exactly this (with some additional error checking) in the <a href="https://github.com/jruby/jruby/blob/a63d961735d1b5d89ebda549e9a3d1b7040d67be/core/src/main/java/org/jruby/RubyArray.java#L1132">RubyArray.java</a>&nbsp;append method (lines 7, 18, and 21 below):</div><div class="p2"><br /></div><script src="https://gist.github.com/jkutner/6056579.js?file=RubyArray.java"></script> <br /><div class="p2">The execution of these three instructions on two threads is illustrated below.</div><div class="p1"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-C4V7ON9IMMg/Ue2Ikzyi4cI/AAAAAAAABEs/qlMLcFUOSnw/s1600/thread_execution.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="368" src="http://3.bp.blogspot.com/-C4V7ON9IMMg/Ue2Ikzyi4cI/AAAAAAAABEs/qlMLcFUOSnw/s640/thread_execution.png" width="640" /></a></div><div class="p2"><br /></div><div class="p1"><br /></div><div class="p2">The instructions execute atomically in MRI because the GIL is locked at the start of the method and released at the end of the method. So there is overlap between two threads. In the JVM, however, the threads can walk all over each other. In this illustration, both threads set the <span style="font-family: Courier New, Courier, monospace;">i</span> variable to the same value because Thread 2 executed the first statement before Thread 1 reallocated the array. Then, Thread 2 overwrites the value that Thread 1 set instead of adding a new value. That's how our JRuby array can end up with less than 256 values.</div><div class="p1"><br /></div><div class="p2">The lack of thread safety in the JRuby Array class is not insurmountable. The JRuby team could have put a lock around this method. Or we could put a lock around the critical section in our thread. But either change would make the program slower.</div><div class="p1"><br /></div><div class="p2">The real problem is that we are sharing the array between multiple threads. It would be okay if the array was immutable. That is, if we were not changing it. But we are mutating the array. Having mutable shared data is the quickest way to make a program not threadsafe. The best, and only full-proof way, to make your Ruby programs threadsafe is to avoid sharing any data between threads.</div><div class="p1"><br /></div><div class="p2">We can consider our code thread-safe if it behaves correctly when accessed from multiple threads without any synchronization or other coordination on the part of the calling code. That's a mouthful. But thread safety is difficult to define. Formal attempts in academia are complicated and don't provide much practical guidance.</div><div class="p1"><br /></div><div class="p2">Ultimately, thread safety is a matter of program correctness. Whether the execution is correct or not really depends on your program. In the threading example we expected our array to have 256 integers when it finished. But with JRuby it doesn't always end up that way. So its not correct.</div><div class="p1"><br /></div><div class="p1">Running the program with MRI always gives us 256 integers. But if we were to inspect the array we would find that it is not always in the same order. Does the order of the data array affect the correctness of our program? It depends on the requirements. Thread safety can be situational.</div><div class="p1"><br /></div><div class="p2">Fortunately, there are some good heuristics for making our code thread-safe. The most important is to avoid mutable shared state. In fact, that was the problem with the threading example. It modified the data array from multiple threads.</div><div class="p1"><br /></div><div class="p2">The most common way to accidentally share mutable data between threads in a Ruby program is with class variables. Consider the following example:</div><br /><script src="https://gist.github.com/jkutner/6056579.js?file=expensive_to_create.rb"></script> <br /><div class="p2">In a multi-threaded environment, like a web server, this class suffers from the same problem illustrated earlier. In general, its a good idea to avoid class variables unless you protect them with some kind of thread synchronization. Databases are very good at that kind of protection. Thus, if you are going to keep any kind of state in your program, its usually preferable to do so in a database or anything else that handles concurrent access well.<br /><br />Ultimately, JRuby Arrays are non-threadsafe because we want them to perform as fast as possible. With this power comes responsibility, but as you can see from the Rails example, it is feasible to use JRuby Arrays safely.</div><br />I borrowed some <a href="https://blog.engineyard.com/2011/concurrency-in-jruby">examples from Nick Seiger</a> for this post. Thanks Nick!<br /><div class="p1"><br /></div>Joe Kutnerhttp://www.blogger.com/profile/02791715457347394080noreply@blogger.com1tag:blogger.com,1999:blog-6843990216939051801.post-67747808676148106252013-05-11T07:45:00.000-07:002013-05-13T09:03:40.824-07:00How to Run Rails 4.0.0.rc1 on JRuby<br />Getting Rails 4.0.0.rc1 running on JRuby isn't that different from running it on MRI, but there are a few minor things you'll need to adjust. Let's start with a new Rails4 app. Make sure you're using JRuby and install the Rails4 release candidate like this:<br /><br /><script src="https://gist.github.com/jkutner/5560118.js?file=example1"></script> Then use the <span style="font-family: Courier New, Courier, monospace;">rails</span> command to generate a new app.<br /><br /><script src="https://gist.github.com/jkutner/5560118.js?file=example2"></script> Move into the newly created <span style="font-family: Courier New, Courier, monospace;">my_app</span> directory so we can tweak some settings. Open the <span style="font-family: Courier New, Courier, monospace;">Gemfile</span> in an editor and look for these lines:<br /><br /><script src="https://gist.github.com/jkutner/5560118.js?file=Gemfile1.rb"></script> First, we'll remove <span style="font-family: Courier New, Courier, monospace;">jruby-openssl</span> because it's included in JRuby 1.7 (this has been fixed in Rails master). Then we need to set the version of <span style="font-family: Courier New, Courier, monospace;">activerecord-jdbcsqlite3-adapter</span> to 1.3.0.beta1. &nbsp;Next, you should thank Karol Bucek (<a href="https://github.com/kares" target="_blank">@kares</a>) for all the hard work he's put into activerecord-jdbc and jruby-rack. Your <span style="font-family: Courier New, Courier, monospace;">Gemfile</span> should now have just these lines in in place of the code shown above:<br /><br /><script src="https://gist.github.com/jkutner/5560118.js?file=Gemfile2.rb"></script> Now return to the console and update bundler like this:<br /><br /><script src="https://gist.github.com/jkutner/5560118.js?file=example3"></script> Do some basic housekeeping<br /><br /><script src="https://gist.github.com/jkutner/5560118.js?file=example4"></script> Now we can smoke test the app by starting the server like this:<br /><br /><script src="https://gist.github.com/jkutner/5560118.js?file=example5"></script> Point a browser to <a href="http://localhost:3000/">http://localhost:3000</a>&nbsp;and there's a chance you'll see the app running. &nbsp;But you might encounter the error shown below:<br /><br /><span style="font-family: Courier New, Courier, monospace;"><b>OpenSSL::Cipher::CipherError: Illegal key size: possibly you need to install Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files for your JRE</b></span><br /><br />If you see this error it means you need to install the unrestricted policy files for the JVM. You can find these at <a href="http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html" target="_blank">the Oracle Website</a>. Download the zip file, and extract the two important files it contains: <span style="font-family: Courier New, Courier, monospace;">local_policy.jar</span> and <span style="font-family: Courier New, Courier, monospace;">US_export_policy.jar</span>. Move these files into your <span style="font-family: Courier New, Courier, monospace;">$JAVA_HOME/jre/lib/security</span> directory, and replace the existing files of the same name. &nbsp;On Mac OS X they are probably located here:<br /><br /><span style="font-family: Courier New, Courier, monospace;"><b>/Library/Java/JavaVirtualMachines/jdk1.7.0_09.jdk/Contents/Home/jre/lib/security/</b></span><br /><br />With the unrestricted policy files installed, restart the server and you'll be good to go. But this may present a problem in deployment. For example, you won't be able to update the JVM on a Heroku dyno. Another option may be to downgrade cryptography as described in <a href="http://jira.codehaus.org/browse/JRUBY-4326" target="_blank">this JIRA issue</a>, but I haven't tried that.&nbsp;Hopefully this will all get worked out.<br /><br />And of course, you probably won't want to use WEBrick in production. Warbler 1.3.8 may work for you, but try the <a href="https://github.com/jruby/warbler/tree/rails4" target="_blank">rails4 branch</a> if it doesn't. &nbsp;I have an example of a working Rails4 app on BitBucket in <a href="https://bitbucket.org/codefinger/warbler-examples/src/master/rails4_app" target="_blank">my warbler-examples repo</a>.<br /><br />I haven't attempted to run a Rails4 app on Trinidad, Puma or TorqueBox. I would love to hear your results. <br /><br />Please give this a go, and report back with any problems you find. &nbsp;We would love to have Rails4 working on JRuby the day it's released.<br /><br /><br />Joe Kutnerhttp://www.blogger.com/profile/02791715457347394080noreply@blogger.com15tag:blogger.com,1999:blog-6843990216939051801.post-52692033467183173442012-08-11T09:29:00.001-07:002012-08-11T09:29:39.854-07:00JRubyConf 2012 Talk<iframe src="http://player.vimeo.com/video/45717166" width="500" height="281" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe><iframe src="http://www.slideshare.net/slideshow/embed_code/13944845?hostedIn=slideshare&page=upload" width="476" height="400" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>Joe Kutnerhttp://www.blogger.com/profile/02791715457347394080noreply@blogger.com10tag:blogger.com,1999:blog-6843990216939051801.post-57252625115878581982012-05-29T07:43:00.002-07:002012-05-29T07:44:52.466-07:00Faster RSpec on JRuby with guard-jruby-rspecThe biggest complaint I hear about JRuby is how long it takes to run tests or specs. &nbsp;I feel your pain. &nbsp;That's why I started hacking on <a href="https://github.com/jkutner/guard-jruby-rspec">guard-jruby-rspec</a>.<br /><br /><br />This guard extention allows you to run all of your specs on JRuby without the initial start up cost. &nbsp;It does not run a subset of your specs like guard-rspec (yet) and it does not trigger a run when a file changes (yet). &nbsp;Instead, this extension loads all of your application files in advance, and reloads them individually when they change. &nbsp;That way, when you run RSpec, the JVM is already running, and your files have already been required.<br /><br />Here's a short video of me using it:<br /><br /><iframe allowfullscreen="" frameborder="0" height="315" src="http://www.youtube.com/embed/r1vVTVzMmnM" width="560"></iframe><br /><div class="separator" style="clear: both; text-align: center;"><br /></div>There's still a lot to do. &nbsp;For instance:<br /><ul><li>Autorun specs like guard-rspec (want to integrate with guard-rspec so as to not duplicate all of it's logic).</li><li>Allow for extra rspec options</li><li>Fix the way guard uses stdin so its not flaky on JRuby</li><li>Work out the kinks in gj-rspec script so that specs can be run in main terminal.</li></ul>More to come...Joe Kutnerhttp://www.blogger.com/profile/02791715457347394080noreply@blogger.com8tag:blogger.com,1999:blog-6843990216939051801.post-74166536004504920052012-05-04T07:57:00.000-07:002012-05-04T08:16:53.075-07:00Zero-Downtime Deploys with JRuby<br />One of the most common questions I get from readers of <a href="http://pragprog.com/book/jkdepj/deploying-with-jruby">my book</a> is about zero-downtime deployment. That is, how do you deploy new versions of a JRuby web application without missing users' requests?<br /><br />To answer this question, let's first look at how MRI-based deployments handle zero-downtime. &nbsp;When a process running an MRI web server needs to load a new version, we shut it down, push the new code, and start it up again.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-9TXfvEWHVlU/T6PqCF0veHI/AAAAAAAAA-A/u02AUlyZPCs/s1600/mri-downtime.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-9TXfvEWHVlU/T6PqCF0veHI/AAAAAAAAA-A/u02AUlyZPCs/s1600/mri-downtime.png" /></a></div><br />This leaves a gap where no requests can be handled. &nbsp;But most MRI deployments use a pool of application processes, which provides a nice way around this problem. &nbsp;While one process is reloading, we can rely on the other processes to service requests. &nbsp;The result is a "rolling restart" in which the re-deployment of each process is staggered. <br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-hbiCLCGZ9JU/T6PqGx459wI/AAAAAAAAA-I/tZJ3aeEtfmw/s1600/rolling-downtime.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="99" src="http://4.bp.blogspot.com/-hbiCLCGZ9JU/T6PqGx459wI/AAAAAAAAA-I/tZJ3aeEtfmw/s320/rolling-downtime.png" width="320" /></a></div><br />In practice this is a difficult dance to&nbsp;coordinate. &nbsp;Technologies like Passenger make it a lot easier, but under the covers it's still complicated.<br /><br />JRuby deployments are different, though. &nbsp;Instead of having a pool of processes, we deploy our applications to a single JRuby server process, which never gets shutdown (ideally). &nbsp;The result is that our deployment has just two steps: undeploy and deploy. <br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-hQpoE0WZfpo/T6PqYCb6zeI/AAAAAAAAA-Q/GawI79GW2as/s1600/jvm-downtime.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-hQpoE0WZfpo/T6PqYCb6zeI/AAAAAAAAA-Q/GawI79GW2as/s1600/jvm-downtime.png" /></a></div><br />However, this still leaves a gap where requests can be dropped, and we don't have other server processes that can take over while we're updating. &nbsp;To fix this, we simply need to reverse the order of the steps! <br /><br />A zero-downtime JRuby deployment requires that we fully deploy a new version of the application before we undeploy the old version. &nbsp;Thus, we will have two version of the app running at the same time, but only one will handle requests.<br /><br />The good news is that Trinidad essentially does this for us. &nbsp;All we have to do is redeploy our application. It works because deep within the bowels of Trinidad is a method that looks like this:<br /><br /><script src="https://gist.github.com/2594825.js?file=lifecycle_listener_host.rb"></script><br /><br />In the takeover method, Trinidad is creating a new context for the next version of the application while the old version continues to run. &nbsp;Then it swaps those contexts in one step. &nbsp;The result is effectively zero-downtime deployment.<br /><br />Unfortunately, not all JRuby web servers do this for us, so we may have to script the process ourselves. &nbsp;Let's take TorqueBox for example. &nbsp;When we deploy a new version of a TorqueBox application to a running TorqueBox server, it completely undeploys the app before loading the new version.<br /><br />Getting around this is pretty easy when TorqueBox is running in a cluster (i.e. multiple TorqueBox instances across mutiple physical or virtual servers). &nbsp;We simply need to deploy a new version of the application to one node at a time. &nbsp;When the old version is undeployed, the <a href="http://www.jboss.org/mod_cluster">Apache mod_cluster proxy</a> will stop sending it requests.<br /><br />If you're really paranoid, you can manually disable a node prior to deploying the new version of your application by invoking the <i>disable()</i> operation on the server's <i>jboss.as.modcluter</i> MBean. &nbsp;The screen shot below shows me doing this from the JMX console.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-8-rJu7W7O8s/T6Ptq73O2GI/AAAAAAAAA-0/qKhYlVYLDso/s1600/jmx-disable-modcluster.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-8-rJu7W7O8s/T6Ptq73O2GI/AAAAAAAAA-0/qKhYlVYLDso/s1600/jmx-disable-modcluster.png" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"></div><br />In my book, I show how to invoke an MBean operation programmatically from a Rake task. That way, you can easily work this step into your deployment scripts.<br /><br />If you're not running TorqueBox in a cluster, the process is a little more complicated. &nbsp;Rather than just dropping your Knob file into the deployment directory or relying on Capistrano to create a deployment descriptor, you'll need to create a custom deployment descriptor for each new version of your application. &nbsp;An example might look like this:<br /><br /><script src="https://gist.github.com/2594825.js?file=myapp-v2-knob.yml"></script><br /><br />When the YAML file is dropped into the <i>$JBOSS_HOME/standalone/deployments</i> directory, it will deploy the new version of the application under the myapp-v2/ context without undeploying the old version of the application (assuming it is not also using the myapp-v1/ context). &nbsp;Then you need to configure your proxy to point to myapp-v2/ instead of myapp-v1/. &nbsp;The resulting process looks like this:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-YH3nnWk6fbY/T6Pq7CPw8fI/AAAAAAAAA-g/JpAl4BlDrSI/s1600/jvm-zero-downtime.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-YH3nnWk6fbY/T6Pq7CPw8fI/AAAAAAAAA-g/JpAl4BlDrSI/s1600/jvm-zero-downtime.png" /></a></div><br /><br />In my experience, if you really care about zero-downtime deployment, then you are probably running a redundant cluster anyways. &nbsp;So the need to orchestrate the context switching on a single node is unusual. <br /><br />In any case, it's certainly possible to achieve zero-downtime deployment with JRuby. &nbsp;And in most cases, it's a lot easier than with MRI.Joe Kutnerhttp://www.blogger.com/profile/02791715457347394080noreply@blogger.com6tag:blogger.com,1999:blog-6843990216939051801.post-35638668601577503312012-03-29T12:10:00.005-07:002012-03-29T12:27:26.029-07:00Clustering TorqueBoxI've create a new screencast to go with the second Beta release of <a href="http://pragprog.com/book/jkdepj/deploying-with-jruby">my book</a>.<div><br /></div><div>In this video, I demonstrate how <a href="http://torquebox.org/">TorqueBox</a> scheduled jobs can be run in a cluster without duplicating the job across nodes.</div><br /><iframe width="560" height="315" src="http://www.youtube.com/embed/v578HHVyvSk" frameborder="0" allowfullscreen=""></iframe><br /><div><br /></div><div>To run the examples I've shown in the video, you'll need to install the torquebox-server gem to your JRuby runtime:</div><br /><script src="https://gist.github.com/2242363.js?file=install.sh"></script><div><br /></div><div>Here are the commands and code I run in the video:</div><br /><script src="https://gist.github.com/2242363.js?file=commands.sh"></script><br /><script src="https://gist.github.com/2242363.js?file=my_job.rb"></script><br /><script src="https://gist.github.com/2242363.js?file=torquebox.rb"></script><div><br /></div><div><br /></div><div><br /></div>Joe Kutnerhttp://www.blogger.com/profile/02791715457347394080noreply@blogger.com2tag:blogger.com,1999:blog-6843990216939051801.post-57875214305058455712012-03-15T17:28:00.006-07:002012-03-15T19:40:16.482-07:00Talkin' about JRubyI gave a talk today at hsv.rb on the subject of my book. The video, slides and code samples are below. Enjoy!<div><br /></div><br /><iframe src="http://player.vimeo.com/video/38608030" width="500" height="283" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe><br /><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/jkutner/deploying-with-jruby" title="Deploying with JRuby" target="_blank">Deploying with JRuby</a></strong> <br /><iframe src="http://www.slideshare.net/slideshow/embed_code/12024358" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe> <div style="padding:5px 0 12px"> View more <a href="http://www.slideshare.net/" target="_blank">presentations</a> from <a href="http://www.slideshare.net/jkutner" target="_blank">jkutner</a> </div><br /><script src="https://gist.github.com/2047877.js?file=threads.rb"></script><br /><script src="https://gist.github.com/2047877.js?file=benchmark.rb"></script>Joe Kutnerhttp://www.blogger.com/profile/02791715457347394080noreply@blogger.com5tag:blogger.com,1999:blog-6843990216939051801.post-10451317337681518922012-03-10T17:29:00.012-08:002012-03-12T06:43:45.366-07:00Deploying with Trinidad on Heroku<div style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal; "><span style="font-size: 100%; ">Heroku is an excellent platform for JRuby deployment, but it only provides indirect support for JRuby through it's Java stack. As a result, deployment on Heroku requires some XML, a little knowledge of </span><a href="http://maven.apache.org/" style="font-size: 100%; ">Maven</a><span style="font-size: 100%; ">, and bunch of hacky-feeling tricks. That's why I chose not to include a detailed discussion of it in my book. Instead, I thought it would make a nice blog post.</span></div><div style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal; "><br class="Apple-interchange-newline">I've created the simplest possible Rack application that can be deployed on Heroku with Trinidad and JRuby &lt;<a href="https://github.com/jkutner/jruby-trinidad-heroku">https://github.com/jkutner/jruby-trinidad-heroku</a>&gt;. The key elements are these:</div><div><ul><li><span>pom.xml</span><span> - this is a Maven config file that can be copied as is (in most cases).</span></li><li><span>Jemfile</span><span> - a renamed Gemfile so that Heroku doesn't think this is an MRI app.</span></li><li><span>Procfile</span><span> - a Heroku config file with instructions for running the app.</span></li><li><span>script/jruby</span><span> - a modified jruby executable for the Heroku platform.</span></li><li><span>config.ru</span><span> - the application itself (can be replaced with any Rack app)</span></li></ul></div><div style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal; ">Once your application has these components, you'll need to create the Heroku application by running this command from the application root:</div><div style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal; "><br /></div><script src="https://gist.github.com/2017633.js?file=heroku.sh"></script><div style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal; "><br class="Apple-interchange-newline">The first thing you'll notice is that we are creating an app on <a href="http://blog.heroku.com/archives/2011/8/25/java/">the Heroku Cedar stack</a>. This provides the Java platform support. We're also using a<span style="font-size: 100%; "> buildpack takes care of setting up the essentials for any Java application on Heroku (most importantly is making sure the Maven dependencies are available at runtime). </span></div><div style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal; "><span style="font-size: 100%; "><br /></span></div><div style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal; "><span style="font-size: 100%; ">Then you can deploy with this command:</span></div><div style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal; "><span style="font-size: 100%; "><br /></span></div><script src="https://gist.github.com/2017633.js?file=deploy.sh"></script><div style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal; "><span style="font-size: 100%; "><br /></span></div><div style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal; "><span style="font-size: 100%; ">There is a slightly out-dated post by Chris Howie on deploying </span><a href="http://chris.chowie.net/2011/08/28/Sinatra-with-JRuby-on-Heroku/" style="font-size: 100%; ">Sinatra on a Trinidad, JRuby, Heroku stack</a><span style="font-size: 100%; ">. There is also an example application called </span><a href="https://github.com/Khaless/Punchy" style="font-size: 100%; ">Punchy</a><span style="font-size: 100%; "> that has been ported to Heroku by Mathew Rodley. Heroku has changed it's configuration since these were created, but the basics hold true. They are worth reading.</span></div><div style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal; "><br /></div><div style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal; ">In addition to Heroku's lack of native JRuby support, it also lacks native support for Trinidad. So it's unclear how many of the Trinidad extensions will function. This is unfortunately because the Trinidad extension are a big part of why this platform is superior to almost every MRI-based server. </div><div style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal; "><br /></div><div style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal; ">In the future, I will investigate Trinidad extensions on Heroku and follow up with another post.</div><div style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal; "><br /></div><div style="font-family: Georgia, serif; font-size: 100%; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal; "><br /></div>Joe Kutnerhttp://www.blogger.com/profile/02791715457347394080noreply@blogger.com0tag:blogger.com,1999:blog-6843990216939051801.post-85761390126423162222012-03-10T15:47:00.003-08:002012-03-10T15:55:50.772-08:00Welcome!This is the official blog for the book <a href="http://pragprog.com/book/jkdepj/deploying-with-jruby">Deploying with JRuby</a> by Joe Kutner. <span style="font-size: 100%; ">I'll be making regular posts here that address topics associated with the book, but not necessarily covered in the book. </span><div><span style="font-size: 100%; "><br /></span></div><div><span style="font-size: 100%; ">The most common questions I've received about the book are: "does it cover Heroku?" and "does it cover Google AppEngine?" </span><span style="font-size: 100%; ">I've chosen not to provide detailed coverage of these platforms in the book, but they are still excellent choices for JRuby deployment. As a result, I hope to post some tutorials of how to use them on this blog.</span></div><div><span style="font-size: 100%; "><br /></span></div><div><span style="font-size: 100%; ">I'll also be posting updates on new platforms, and some less mainstream server technologies that can be used for deploying JRuby. </span></div><div><span style="font-size: 100%; "><br /></span></div><div><span style="font-size: 100%; ">Stay tuned for more!</span></div>Joe Kutnerhttp://www.blogger.com/profile/02791715457347394080noreply@blogger.com0