The Other mod_rails : Easy Rails Deployment with JRuby Nick Sieger - - PowerPoint PPT Presentation

the other mod rails easy rails deployment with jruby
SMART_READER_LITE
LIVE PREVIEW

The Other mod_rails : Easy Rails Deployment with JRuby Nick Sieger - - PowerPoint PPT Presentation

The Other mod_rails : Easy Rails Deployment with JRuby Nick Sieger Sun Microsystems, Inc CGI/FCGI Mongrel omg puppiez! not nirvana... Processes: 68 total, 3 running, 1 stuck, 64 sleeping... 309 threads Load Avg: 0.71, 0.51, 0.43 CPU


slide-1
SLIDE 1

The Other mod_rails: Easy Rails Deployment with JRuby

Nick Sieger Sun Microsystems, Inc

slide-2
SLIDE 2
slide-3
SLIDE 3

CGI/FCGI

slide-4
SLIDE 4

Mongrel

slide-5
SLIDE 5
  • mg puppiez!
slide-6
SLIDE 6
slide-7
SLIDE 7

not nirvana...

slide-8
SLIDE 8
slide-9
SLIDE 9

Processes: 68 total, 3 running, 1 stuck, 64 sleeping... 309 threads Load Avg: 0.71, 0.51, 0.43 CPU usage: 22.79% user, 13.02% sys, 64.19% idle SharedLibs: num = 8, resident = 80M code, 384K data, 5156K linkedit. MemRegions: num = 13190, resident = 707M + 27M private, 400M shared. PhysMem: 589M wired, 1205M active, 89M inactive, 1883M used, 2197M free. VM: 11G + 373M 188123(0) pageins, 0(0) pageouts PID COMMAND %CPU TIME #TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE 650 top 6.3% 0:01.71 1 18 29 1084K 188K 1676K 18M 571 ruby 0.2% 0:04.09 2 17 163 32M 188K 34M 51M 572 ruby 0.2% 0:04.09 2 17 163 32M 188K 34M 51M 573 ruby 0.2% 0:04.09 2 17 163 32M 188K 34M 51M 574 ruby 0.2% 0:04.09 2 17 163 32M 188K 34M 51M 575 ruby 0.2% 0:04.09 2 17 163 32M 188K 34M 51M 576 ruby 0.2% 0:04.09 2 17 163 32M 188K 34M 51M 577 ruby 0.2% 0:04.09 2 17 163 32M 188K 34M 51M 578 ruby 0.2% 0:04.09 2 17 163 32M 188K 34M 51M 579 ruby 0.2% 0:04.09 2 17 163 32M 188K 34M 51M 580 ruby 0.2% 0:04.09 2 17 163 32M 188K 34M 51M 581 ruby 0.2% 0:04.09 2 17 163 32M 188K 34M 51M 582 ruby 0.2% 0:04.09 2 17 163 32M 188K 34M 51M 583 ruby 0.2% 0:04.09 2 17 163 32M 188K 34M 51M 584 ruby 0.2% 0:04.09 2 17 163 32M 188K 34M 51M 585 ruby 0.2% 0:04.09 2 17 163 32M 188K 34M 51M 586 ruby 0.2% 0:04.09 2 17 163 32M 188K 34M 51M 587 ruby 0.2% 0:04.09 2 17 163 32M 188K 34M 51M 588 ruby 0.2% 0:04.09 2 17 163 32M 188K 34M 51M 589 ruby 0.2% 0:04.09 2 17 163 32M 188K 34M 51M 580 ruby 0.2% 0:04.09 2 17 163 32M 188K 34M 51M 591 ruby 0.2% 0:04.09 2 17 163 32M 188K 34M 51M 592 ruby 0.2% 0:04.09 2 17 163 32M 188K 34M 51M

slide-10
SLIDE 10

Webserver/Load Balancer Ruby Mongrel Rails

Rails Ruby code Key OS Proc.

Ruby Mongrel Rails Ruby Mongrel Rails

slide-11
SLIDE 11

JVM JRuby Rails JRuby Rails Servlet Bridge

Rails Java code Key OS Proc.

GlassFish HTTP Listener HTTP Listener HTTP Listener JRuby Rails

slide-12
SLIDE 12

existing applications

slide-13
SLIDE 13

$ jruby -S gem install activerecord-jdbcmysql-adapter Successfully installed activerecord-jdbc-adapter-0.8 Successfully installed jdbc-mysql-5.0.4 Successfully installed activerecord-jdbcmysql-adapter-0.8 3 gems installed Installing ri documentation for activerecord-jdbc-adapter-0.8... Installing ri documentation for jdbc-mysql-5.0.4... Installing ri documentation for activerecord-jdbcmysql-adapter-0.8... Installing RDoc documentation for activerecord-jdbc-adapter-0.8... Installing RDoc documentation for jdbc-mysql-5.0.4... Installing RDoc documentation for activerecord-jdbcmysql-adapter-0.8...

slide-14
SLIDE 14

# config/database.yml <% jdbc = defined?(JRUBY_VERSION) ? 'jdbc' : '' %> development: adapter: <%= jdbc %>mysql encoding: utf8 database: testapp_development username: root password: socket: /tmp/mysql.sock # same for test/production...

slide-15
SLIDE 15

Gems and libraries with native code

slide-16
SLIDE 16

http://flickr.com/photos/thehappyrobot/1413968365/

slide-17
SLIDE 17

RMagick, ImageScience ImageVoodoo OpenSSL JRuby- OpenSSL gem Ruby/LDAP JRuby/LDap Mongrel, Hpricot OK

replacements/ equivalents

slide-18
SLIDE 18

$ jruby -S gem install mongrel Successfully installed mongrel-1.1.3-java 1 gem installed Installing ri documentation for mongrel-1.1.3-java... Installing RDoc documentation for mongrel-1.1.3-java... $ jruby script/server => Booting Mongrel (use 'script/server webrick' to force WEBrick) => Rails application starting on http://0.0.0.0:3000 => Call with -d to detach => Ctrl-C to shutdown server ** Starting Mongrel listening at 0.0.0.0:3000 ** Starting Rails with development environment... ** Rails loaded. ** Loading any Rails specific GemPlugins ** Signals ready. TERM => stop. USR2 => restart. INT => stop (no restart). ** Rails signals registered. HUP => reload (without restart). It might not work well. ** Mongrel 1.1.3 available at 0.0.0.0:3000 ** Use CTRL-C to stop.

slide-19
SLIDE 19

packaging

slide-20
SLIDE 20
slide-21
SLIDE 21
slide-22
SLIDE 22

warbler

slide-23
SLIDE 23

jruby -S gem install warbler jruby -S warble config

slide-24
SLIDE 24

# Warbler web application assembly configuration file Warbler::Config.new do |config| # ... # Gems to be packaged in the webapp. ... config.gems += ["activerecord-jdbcmysql-adapter", "jruby-openssl"] config.gems["rails"] = "2.0.2" # ... end

slide-25
SLIDE 25

warbler demo

slide-26
SLIDE 26

configuration

slide-27
SLIDE 27

if defined?(JRUBY_VERSION) && defined?($servlet_context) # Logger expects an object that responds to #write and #close device = Object.new def device.write(message) $servlet_context.log(message) end def device.close; end # Make these accessible to wire in the log device class << RAILS_DEFAULT_LOGGER public :instance_variable_get, :instance_variable_set end

  • ld_device = RAILS_DEFAULT_LOGGER.instance_variable_get "@log"
  • ld_device.close rescue nil

RAILS_DEFAULT_LOGGER.instance_variable_set "@log", device end

logging

slide-28
SLIDE 28

config.action_controller.session_store = :java_servlet_store # ... class CGI::Session::JavaServletStore def initialize(session, options) end def restore; end def update; end def close; end end

sessions

slide-29
SLIDE 29

# config/initializers/close_connections.rb if defined?($servlet_context) require 'action_controller/dispatcher' ActionController::Dispatcher.after_dispatch do ActiveRecord::Base.clear_active_connections! end end

connection pools

slide-30
SLIDE 30

view caching

config.action_view.cache_template_loading = true

(default in Rails >= 2.0.2)

slide-31
SLIDE 31

asset timestamps

ENV['RAILS_ASSET_ID'] = "r#{source_revision}"

slide-32
SLIDE 32

Rails.public_path coming in 2.1

full-page cache

config.action_controller.page_cache_directory = "/where/is/my/railsapp/war/deployed"

slide-33
SLIDE 33

if defined?(JRUBY_VERSION) && defined?($servlet_context) # Logger expects an object that responds to #write and #close device = Object.new def device.write(message) $servlet_context.log(message) end def device.close; end # Make these accessible to wire in the log device class << RAILS_DEFAULT_LOGGER public :instance_variable_get, :instance_variable_set end

  • ld_device = RAILS_DEFAULT_LOGGER.instance_variable_get "@log"
  • ld_device.close rescue nil

RAILS_DEFAULT_LOGGER.instance_variable_set "@log", device end

config.action_controller.session_store = :java_servlet_store # ... class CGI::Session::JavaServletStore def initialize(session, options) end def restore; end def update; end def close; end end

config.action_view.cache_template_loading = true

# config/initializers/close_connections.rb if defined?($servlet_context) require 'action_controller/dispatcher' ActionController::Dispatcher.after_dispatch do ActiveRecord::Base.clear_active_connections! end end

ENV['RAILS_ASSET_ID'] = "r#{source_revision}"

config.action_controller.page_cache_directory = "/where/is/my/railsapp/war/deployed"

slide-34
SLIDE 34
slide-35
SLIDE 35

jruby-rack

slide-36
SLIDE 36

available now

released earlier this month

slide-37
SLIDE 37

bundled with warbler

slide-38
SLIDE 38

servlet adapter

slide-39
SLIDE 39

eliminates previous configuration

slide-40
SLIDE 40

http://rack.rubyforge.org/

slide-41
SLIDE 41

proc do |env| [200, {"Content-Type" => "text/html"}, "Hello World!"] end

slide-42
SLIDE 42

“middleware”

slide-43
SLIDE 43

module Rack class ShowStatus def initialize(app) @app = app @template = ERB.new(TEMPLATE) end def call(env) status, headers, body = @app.call(env) if status.to_i >= 400 [status, headers.merge("Content-Type" => "text/html"), [@template.result(binding)]] else [status, headers, body] end end end end

slide-44
SLIDE 44

rack demo

slide-45
SLIDE 45

tuning

slide-46
SLIDE 46

http://flickr.com/photos/86974734@N00/2206011624/

slide-47
SLIDE 47

Warbler::Config.new do |config| # ... # Control the pool of Rails runtimes config.webxml.jruby.min.runtimes = 2 config.webxml.jruby.max.runtimes = 4 end

pool size

slide-48
SLIDE 48

performance misattribution

slide-49
SLIDE 49

lies, damned lies

slide-50
SLIDE 50

YMMV

slide-51
SLIDE 51

measure your own @#$!& app

slide-52
SLIDE 52

15 30 45 60 75 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100

Request Scaling (1 process or runtime)

avg reply rate request rate

webrick mongrel glassfish

slide-53
SLIDE 53

Warbler::Config.new do |config| # ... # Control the pool of Rails runtimes config.webxml.jruby.min.runtimes = 1 config.webxml.jruby.max.runtimes = 1 end

slide-54
SLIDE 54

Warbler::Config.new do |config| # ... # Control the pool of Rails runtimes config.webxml.jruby.min.runtimes = 3 config.webxml.jruby.max.runtimes = 3 end

slide-55
SLIDE 55

25 50 75 100 125 150 175 200

15 30 45 60 75 90 105 120 135 150 165 180 195 210 225 240 255 270 285 300

JRuby/Glassfish

Avg reply rate Request rate

1 runtime (interpolated above 90) 3 runtimes

slide-56
SLIDE 56

the future is now

slide-57
SLIDE 57

rails concurrency

Each Rails request must execute in isolation. “Rails is not thread-safe? WTF?” “Servlets have been multi-threaded since, like,1997!”

slide-58
SLIDE 58

concurrency context

Writing thread-safe code is hard + Ruby's userland threads don't yield much benefit Not worth the effort

slide-59
SLIDE 59

but what if it was?

slide-60
SLIDE 60

Rails to become thread-safe

(Google SoC 2008 project)

slide-61
SLIDE 61

connection pooling for ActiveRecord

(yours truly)

slide-62
SLIDE 62

Rails on a Rack?

Ezra’s work: http://github.com/ezmobius/rails/

slide-63
SLIDE 63

rails rack connection pooling single-file deployment + native threading industrial-strength vm

slide-64
SLIDE 64

=

slide-65
SLIDE 65

“she’s a beaut.”

slide-66
SLIDE 66

hassle-free

slide-67
SLIDE 67

scalable

slide-68
SLIDE 68

(enterprisey?)

slide-69
SLIDE 69

awesome!

(stay tuned!)

slide-70
SLIDE 70