Slide 1

Slide 1 text

Migrate to JRuby What We Learned

Slide 2

Slide 2 text

ian yang @doitian

Slide 3

Slide 3 text

Agenda • Background • How to Migrate • What We Learned

Slide 4

Slide 4 text

Background

Slide 5

Slide 5 text

Breadcrumb Payments

Slide 6

Slide 6 text

The Codebase • 4 Ruby on Rails applications • Ruby 1.9.2 and Rails 3.2.1

Slide 7

Slide 7 text

Why JRuby? • Multithreading • Memory Leak • Easy integration of libraries on JVM

Slide 8

Slide 8 text

How to Migrate

Slide 9

Slide 9 text

Choose a Deploy Strategy

Slide 10

Slide 10 text

Warbler Trinidad TorqueBox Archive File ✔ ✔ ✔ Capistrano ✔ ✔ Scheduler ✔ ✔ Background Jobs ✔ ✔ Clustering ✔

Slide 11

Slide 11 text

Warbler Trinidad TorqueBox Archive File ✔ ✔ ✔ Capistrano ✔ ✔ Scheduler ✔ ✔ Background Jobs ✔ ✔ Clustering ✔

Slide 12

Slide 12 text

JRuby-Lint https://github.com/jruby/jruby-lint

Slide 13

Slide 13 text

What We Learned

Slide 14

Slide 14 text

Gems Alternatives

Slide 15

Slide 15 text

Wiki: C Extension Alternatives https://github.com/jruby/jruby/wiki/C-Extension- Alternatives

Slide 16

Slide 16 text

Lock Compatible Version

Slide 17

Slide 17 text

gem 'rubyzip', '<1.0.0'

Slide 18

Slide 18 text

*nix to JVM

Slide 19

Slide 19 text

• No Kernel#fork • Cannot trap all signals

Slide 20

Slide 20 text

Kernel#fork → Thread.new

Slide 21

Slide 21 text

Thread-safety

Slide 22

Slide 22 text

Avoid Sharing Mutable State Between Threads

Slide 23

Slide 23 text

Global Variable ⾠ Class Variable ⾠ Class Instance Variable ⾠

Slide 24

Slide 24 text

Lazy Initialization → Preload

Slide 25

Slide 25 text

class Cvv def self.redis @@redis ||= Redis.new(...) end end ✘

Slide 26

Slide 26 text

class Cvv def self.redis @@redis end def self.redis=(r) @@redis = r end end ! # config/initializers/cvv.rb Cvv.redis = Redis.new(...) ✔

Slide 27

Slide 27 text

Thread Local Storage

Slide 28

Slide 28 text

class Processor class_attribute :skip ! def execute do_something unless self.class.skip end end ✘

Slide 29

Slide 29 text

class Processor def self.skip Thread.current['Processor.skip'] end def self.skip=(s) Thread.current['Processor.skip'] = s end end ✔

Slide 30

Slide 30 text

Atomic Variable

Slide 31

Slide 31 text

class Airlock class_variable :enabled end ✘

Slide 32

Slide 32 text

# gem 'atomic'! class Airlock! @@enabled = Atomic.new(false)! def self.enabled! @@enabled.value! end! def self.enabled=(e)! @@enabled.update { e }! end! end ✔

Slide 33

Slide 33 text

Locks require 'thread'! mutex = Mutex.new! ! Thread.new do! mutex.synchronize do! ...! end! end

Slide 34

Slide 34 text

Reference: Concurrency in JRuby https://github.com/jruby/jruby/wiki/Concurrency-in- jruby

Slide 35

Slide 35 text

Reference: Ruby Mutithreading http://www.tutorialspoint.com/ruby/ ruby_multithreading.htm

Slide 36

Slide 36 text

Resque

Slide 37

Slide 37 text

• No Fork • Jobs run in the same process • Free the resources

Slide 38

Slide 38 text

OpenSSL

Slide 39

Slide 39 text

Full OpenSSL Support gem 'jruby-openssl'

Slide 40

Slide 40 text

Different Cryptography Implementations https://github.com/jruby/jruby/issues/931

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

Cryptography Adapter • Use OpenSSL in CRuby • Use JCE directly in JRuby (java_import)

Slide 43

Slide 43 text

Tuning

Slide 44

Slide 44 text

TorqueBox + JBoss

Slide 45

Slide 45 text

Connection Pool Size

Slide 46

Slide 46 text

Thread Pool Size

Slide 47

Slide 47 text

JVM Memory

Slide 48

Slide 48 text

How To? • Benchmark • Monitoring

Slide 49

Slide 49 text

References

Slide 50

Slide 50 text

Deploying with JRuby

Slide 51

Slide 51 text

JRuby Wiki https://github.com/jruby/jruby/wiki

Slide 52

Slide 52 text

No content