Архив 11.04.2009

11
Апр
09

Запуск JRuby on Rails в Google AppEngine Java

Я не устоял перед соблазном и решил попробовать запустить JRuby on Rails в AppEngine. На этот шаг меня вдохновил целый ряд постов в разных блогах и мое повествование будет неполным без них:

По правде, до этого пользоваться JRuby мне приходилось только один раз, да и то, ради любопытства. Думаю многим JRuby знаком так же “хорошо”, поэтому начнем с самого начала. А для начала нам понадобиться свежий JRuby. Вытягиваем его из репозитория и собираем:

svn co http://svn.codehaus.org/jruby/trunk/jruby
cd jruby
ant && ant jar-complete

Использовать rake build тоже можно, но результатом его работы будет только собраный JRuby. А нам с вами нужен еще jruby-complete.jar, чуть позже мы вернемся к нему. Пока же для удобства пропишите себе путь к jruby/bin и продолжим – установим Rails и сделаем скелет приложения:

jruby -S gem install rails
jruby -S rails depot

Замораживаем все gems и удаляем в них тесты. Как я уже писал, GAE/J имеет ряд ограничений, в том числе и на число файлов. Их количество не должно привышать 1000 штук. Надеюсь, это временно ограничение. ActiveRecord нам тоже больше не нужен, на GAE/J применения ему нет, за компанию выбросим и ActionMailer с ActiveResource:

jruby -S rake rails:freeze:gems
rm -rf vendor/rails/actionpack/test/
rm -rf vendor/rails/activerecord/
rm -rf vendor/rails/actionmailer/
rm -rf vendor/rails/activeresource/

Поскольку от ActiveRecord, ActionMailer и ActiveResource мы избавились, будет разумным сразу поправить config/environment.rb:

environment.rb
config.frameworks -= [ :active_record, :active_resource, :action_mailer ]

Пока оставим Rails и займемся SDK для Google AppEngine Java. Для начала, вам следует скачать его с code.google.com, после разверните его в удобное для вас место и пропишите пути к скриптам в appengine-java-sdk/bin.

Из поставки GAE/J SDK нам понадобиться библиотека appengine-java-sdk/lib/impl/appengine-api.jar. Скопируйте ее в RAILS_ROOT/lib. Туда же нужно будет положить jruby-complete.jar из jruby/lib и jruby-jrack.jar. Последний можно найти в репозитории jruby-rack:

git clone git://github.com/nicksieger/jruby-rack.git
cd jruby-rack
jruby -S rake SKIP_SPECS=true

Поскольку jruby-complete.rb слишком большой для GAE/J, воспользуемся скриптом Ola Bini, позволяющим разбить его на две части – jruby-core.jar и ruby-stdlib.jar:

fix_libs.sh
#!/bin/sh
rm -rf jruby-core.jar
rm -rf ruby-stdlib.jar
rm -rf tmp_unpack
mkdir tmp_unpack
cd tmp_unpack
jar xf ../jruby-complete.jar
cd ..
mkdir jruby-core
mv tmp_unpack/org jruby-core/
mv tmp_unpack/com jruby-core/
mv tmp_unpack/jline jruby-core/
mv tmp_unpack/jay jruby-core/
mv tmp_unpack/jruby jruby-core/
cd jruby-core
jar cf ../jruby-core.jar .
cd ../tmp_unpack
jar cf ../ruby-stdlib.jar .
cd ..
rm -rf jruby-core
rm -rf tmp_unpack
rm -rf jruby-complete.jar

Этот скрипт можно найти в репозитории Ola Bini YARBL. Для замены ActiveRecord нужно будет установить Bumble из репозитория. Добавьте загрузку Bumble в environment.rb. В enviroments/session_store.rb отключите сессии. Готового решения для Rails 2.3.2 пока нет (узнать подробней об этом можно здесь). Пользоваться cookie для хранения сессий пока нельзя, нет обвязок для java.security и javax.crypto.

Библиотеки все собраны и для запуска нам осталось совсем немного. Установите warbler и сконфигурируйте его. Делать это надо в RAILS_ROOT и обратите внимание на коварство разработчиков – gem называется warbler, а скрипт warble:

jruby -S gem install warbler
jruby -S warble pluginize
jruby -S warble config

Конфигурация находиться в config/warble.rb:

warble.rb
config.includes = FileList["appengine-web.xml", "datastore-indexes.xml"]
config.webxml.jruby.min.runtimes = 1
config.webxml.jruby.max.runtimes = 2

Файлы appengine-web.xml и datastore-index.xml стандартные для приложений GAE/J. В первом доступна конфигурация приложения, во втором – индексы для DataStore. В нашем случае мы воспользуемся самым простыми вариантами этих двух файлов:

appengine-web.xml
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<application>depot</application>
<version>2</version>
<static-files />
<resource-files />
<sessions-enabled>true</sessions-enabled>
<system-properties>
<property name="jruby.management.enabled" value="false" />
<property name="os.arch" value="" />
<property name="jruby.compile.mode" value="JIT"/> <!-- JIT|FORCE|OFF -->
<property name="jruby.compile.fastest" value="true"/>
<property name="jruby.compile.frameless" value="true"/>
<property name="jruby.compile.positionless" value="true"/>
<property name="jruby.compile.threadless" value="false"/>
<property name="jruby.compile.fastops" value="false"/>
<property name="jruby.compile.fastcase" value="false"/>
<property name="jruby.compile.chainsize" value="500"/>
<property name="jruby.compile.lazyHandles" value="false"/>
<property name="jruby.compile.peephole" value="true"/>
</system-properties>
</appengine-web-app>

datastore-indexes.xml
<?xml version="1.0" encoding="utf-8"?>
<datastore-indexes autoGenerate="true">
</datastore-indexes>

Теперь можно попробовать запустить тестовый сервер GAE/J:

jruby -S warble
dev_appserver.sh tmp/war

Если все в порядке, то по адресу http://localhost:8080 вам будет доступен тестовый сервер GAE/J с вашим приложением.

11
Апр
09

Ограничения AppEngine

Nick Sieger в блоге рассказал о своих впечатлениях от работы с GAE/J. Там же упомянуты ряд ограничений для GAE/J:

  • No regular net/http, restclient, ActiveResource usage. Google has a URL fetch library, and has hooked up Java’s HttpURLConnection to it, but none of the Ruby URL-fetching libraries use it.
  • No ActiveRecord. ‘Nuff said. For some folks, that’s a welcome change, but wrapping your head around AppEngine’s BigTable-backed data store takes some thought. You just can’t view it like a SQL engine.
  • No RMagick/ImageScience/attachment_fu. No ImageVoodoo even (no javax.image APIs). Google has it’s own image manipulation API.
  • Startup/first request processing time is currently an issue. It’s not clear yet how long Google keeps JVMs warm, so if your application is idle, the first few hits to it return 500 errors. I can only assume Google has a plan to address this.
  • Crypto. Although java.security and javax.crypto APIs are apparently whitelisted, I haven’t had time to figure out how to leverage them. JRuby’s jruby-openssl gem does not work, which means things like digest aren’t available. That’s currently a blocker for Rails’ cookie session store.
  • 1000-files limit per application. In order to work around this, I ended up jarring up all the Rails gems when deploying a Rails application.

Что касается первого пункта, Bas Wilbers подготовил несложную библиотеку для работы с URL Fetch API в GAE/J. Найти ее вы можете на github.com: urlfetch-gae.

Вторая интересная библиотека Bas Wilbers – интерфейс к GAE/J MailService, pony-gae. Безусловно, начилие этих библиотек, а так же Beeu и Bumble от Ola Bini не решает всех текущих проблем, но запускать JRuby on Rails приложения это совсем не мешает.




Follow

Get every new post delivered to your Inbox.