Tydzień temu JRuby osiągnął spory milestone w wersji 1.5.0, co utwierdziło mnie w przekonaniu, że jest to jeden z poważniejszych projektów w świecie Ruby'ego. Jest kilka przyczyn, dla których warto się nim zainteresować. Mówi się o wysokiej wydajności tej implementacji - nie ustępującej MRI 1.9. W środowiskach z rozbudowaną infrastrukturą JavaEE JRuby stanowi świetny punkt zaczepienia dla Ruby'ego.

Dla mnie podstawowym atutem JRuby'ego jest wygodny dostęp do multum bibliotek Javy, z których niejedna dojrzałością przewyższa znane gemy w Rubym.

Decydując się na JRuby on Rails w budowanym właśnie przeze mnie projekcie obawiałem się, że będę musiał przeprosić się z Tomcatem czy Jettym, grzebać się w XMLach i innych WARach. Obcując z wersją sprzed kilku miesięcy miałem też przykre doświadczenia z kompatybilnością niektórych gemów. Na szczęście JRuby 1.4.0 - a 1.5.0 tym bardziej - wszystkie te problemy rozwiązał.

Pojawiły się też w międzyczasie narzędzia ułatwiające deployment do tego stopnia, że nie jest on ani trochę trudniejszy od wdrożenia aplikacji na Passengerze. Nie trzeba też rezygnować z Capistrano.

Dla potomnych poniżej najprostszy scenariusz wdrożenia aplikacji JRuby on Rails.

Przygotowanie

Przed wdrożeniem upewnij się, że aplikacja na localhoście działa w pełni na JRubym. W moim projekcie tylko mały fragment korzysta z Javy, mam więc tendencję do odpalania:

./script/server

zamiast

jruby script/server

Nic nie stoi na przeszkodzie aby na komputerze mieć zarówno Ruby'ego MRI (czy EE) obok JRuby. Możesz też oczywiście skorzystać z rvm. Pamiętaj, że każdy interpreter ma swój własny zestaw gemów.

JRuby i glassfish

Na serwerze musi być oczywiście zainstalowany JRuby - ja zawsze instaluję do /opt/jruby-1.x.x, a wersję która mnie interesuje symlinkuję do /opt/jruby. Do $PATH dochodzi /opt/jruby/bin.

Zainstaluj gem glassfish:

jgem install glassfish

I w sumie na tym koniec... serwer jest gotowy ;) Glassfish to serwer aplikacji Java stworzony przez Suna, a dzięki jednemu developerowi jest dostępny w postaci gema.

Z katalogu aplikacji możesz teraz wywołać:

jruby -S glassfish

...i aplikacja działa na porcie 3000. Przydałoby się jednak odpalić serwer w tle. I może zmienić port? I restartować przy deployu... Pora więc na...

Capistrano

Do współpracy z Capistrano potrzebne są 2 kroki. Po pierwsze musimy przygotować plik konfiguracyjny Glassfisha - tak aby odpalał się jako daemon i w odpowiednim miejscu zapisywał plik z pidem. Wywołaj w katalogu aplikacji:

gfrake

Komenda wygeneruje podstawowy plik config/glassfish.yml z domyślnymi ustawieniami. Ustaw poniższe wartości:

...
environment: production
...
port: 3000  # (wedle uznania)
...
daemon:
  enable: true
  pid: tmp/pids/glassfish.pid
...

Konfig koniecznie przenieś do shared i pamiętaj o symlinkowaniu przy deployu (to temat na inną rozmowę).

Teraz pozostaje tylko przygotować kroki deploy w przepisie Capistrano:

namespace :deploy do
  desc "Start Glassfish Gem from a shutdown state"
  task :cold do
    start
  end

  desc "Stop a server running Glassfish Gem"
  task :stop do
    pid = "$(cat #{current_path}/tmp/pids/glassfish.pid)"
    run "if ps -p #{pid} > /dev/null; ↩
         then kill -INT #{pid}; ↩
         else echo 'Glassfish not running'; ↩
         fi"
  end

  desc "Starts a server running Glassfish Gem"
  task :start do
    run "cd #{current_path} && glassfish"
  end

  desc "Restarts a server running Glassfish Gem"
  task :restart, :roles => :app do
    stop
    start
  end
end

start to po prostu uruchomienie glassfish. Dzięki konfigowi uruchomi się w tle, a pid zapisze do tmp/pids/glassfish.pid.

stop to sprawdzenie czy proces o danym pidzie istnieje i - jeśli tak - ubicie go.

Żadna filozofia.

W takiej konfiguracji Glassfish serwuje wszystko - również zasoby z public. Teoretycznie nie ma w tym nic złego, ale z punktu widzenia wydajności warto (warto?) tę funkcję zrzucić np. na Apache'a. Miało być jednak prosto więc na tym skończymy.

Czarne chmury

Glassfish gem jest stabilny, wydajny i super prosty w użyciu, ale ma jedną sporą wadę... nie jest już aktywnie rozwijany. W świetle zmian jakie ostatnio przeszedł Sun, projekt ten - do tej pory wspierany przez firmę - nie "przeżył".

Na horyzoncie widać już jednak potencjalnego następcę. A może raczej konkurenta. trinidad to Tomcat opakowany w gem i przygotowany do użycia prawie w taki sam sposób, który opisałem. Warto mieć na oku.

Kombinacja JRuby+Glassfish bardzo pozytywnie mnie zaskoczyła i zdecydowanie polecam ją wszystkim obawiającym się pierwszego kontaktu z JRubym.