katello on torquebox

140
KATELLO ON TORQUEBOX Java Loves Ruby

Upload: lzap

Post on 08-Jul-2015

552 views

Category:

Technology


1 download

DESCRIPTION

Lukáš Zapletal Katello on Torquebox / JRuby talk for Developer Conference 2013 Brno Czech Republic (English)

TRANSCRIPT

Page 1: Katello on TorqueBox

KATELLO ON TORQUEBOXJava Loves Ruby

Page 2: Katello on TorqueBox
Page 3: Katello on TorqueBox
Page 4: Katello on TorqueBox

ABOUT MELukáš Zapletal

Page 5: Katello on TorqueBox

ABOUT ME@lzap

Page 6: Katello on TorqueBox

ABOUT ME@lzap_CZ @lzap80

Page 7: Katello on TorqueBox
Page 8: Katello on TorqueBox

THEME SELECTIONBlah blah blah:

- - - - - Sky Beige Simple Serif Night Default

Page 9: Katello on TorqueBox

KATELLO

Page 10: Katello on TorqueBox

TORQUEBOX

Page 11: Katello on TorqueBox

RUBY

Page 12: Katello on TorqueBox

JRUBY

Page 13: Katello on TorqueBox

JAVA

Page 14: Katello on TorqueBox

JAVA

Page 15: Katello on TorqueBox

CATS-FREE TALK

Page 16: Katello on TorqueBox

WHAT IS KATELLO

Page 17: Katello on TorqueBox

KATELLO IS

Page 18: Katello on TorqueBox

A OPEN-SOURCE

Page 19: Katello on TorqueBox

CONTENT AND SYSTEM

Page 20: Katello on TorqueBox

MANAGEMENT STACK

Page 21: Katello on TorqueBox

FOR DATACENTERS

Page 22: Katello on TorqueBox

AND CLOUD

Page 23: Katello on TorqueBox

IF YOU TAKE ...

Page 24: Katello on TorqueBox

AND CLOUD

Page 25: Katello on TorqueBox

FOR DATACENTERS

Page 26: Katello on TorqueBox

AND CLOUD

Page 27: Katello on TorqueBox

FOR DATACENTERS

Page 28: Katello on TorqueBox

AND CLOUD

Page 29: Katello on TorqueBox

ENOUGH FUN!What the cloud is?

Page 30: Katello on TorqueBox

NISTNational Institute of Standards and Technology

Page 31: Katello on TorqueBox

NIST DEFINITIONthe NIST definition of cloud computing

Page 32: Katello on TorqueBox

NIST DEFINITION

Page 33: Katello on TorqueBox

NIST DEFINITION

Page 34: Katello on TorqueBox

NIST DEFINITION

Page 35: Katello on TorqueBox

NIST DEFINITION

Page 36: Katello on TorqueBox

NIST DEFINITION

Page 37: Katello on TorqueBox

NIST DEFINITION

Page 38: Katello on TorqueBox

NIST DEFINITION

Page 39: Katello on TorqueBox

CLOUD DEFINITIONCloud computing is a model for enabling ubiquitous,

convenient, on-demand network access to a shared pool ofconfigurable computing resources.

Page 40: Katello on TorqueBox

CLOUD DEFINITIONIt can be rapidly provisioned and released with minimal

management effort or service provider interaction.

Page 41: Katello on TorqueBox

ESSENTIAL CHARACTERISTICSon-demand service

Page 42: Katello on TorqueBox

ESSENTIAL CHARACTERISTICSbroad network access

Page 43: Katello on TorqueBox

ESSENTIAL CHARACTERISTICSresource pooling

Page 44: Katello on TorqueBox

ESSENTIAL CHARACTERISTICSrapid elasticity

Page 45: Katello on TorqueBox

ESSENTIAL CHARACTERISTICSmeasured service

Page 46: Katello on TorqueBox

SERVICE MODELSSaaSPaaSIaas

Page 47: Katello on TorqueBox

DEPLOYMENT MODELSprivate cloudcommunity cloudhybrid cloudpublic cloud

Page 48: Katello on TorqueBox

WHAT YOU CAN DO WITH KATELLO?

Page 49: Katello on TorqueBox

RED HAT SUBSCRIPTIONwhat is it and how it works

Page 50: Katello on TorqueBox

SUBSCRIPTION MANAGEMENTimport Red Hat subscriptions from Portalcreate your own products and subscriptionsregister machines and consume themsee some statistics and graphs

Page 51: Katello on TorqueBox

CONTENT MANAGEMENTsync RPM content from CDNsync RPM content from other repositoriessync puppet content from Puppet Forgeseparate content into environments and content viewspromote contentconsume content using yum or puppetremote install/upgrade content

Page 52: Katello on TorqueBox

THERE IS FOREMAN

Page 53: Katello on TorqueBox

PROVISIONINGregister installation treesprepare provisioning templatesprovision bare-metal/virtual systemsmaintain registry of all systems

Page 54: Katello on TorqueBox

CONFIGURATION MANAGEMENTimport Puppet classes into Foreman databaseassign classes to hosts (existing or provisioned)assign parameters to classescollect info from Facter and Puppetcreate statistics and graphs

Page 55: Katello on TorqueBox

KATELLO UI

Page 56: Katello on TorqueBox

KATELLO UI

Page 57: Katello on TorqueBox

KATELLO UI

Page 58: Katello on TorqueBox

RED HAT PRODUCTSSubscription Asset Manager (SAM)CloudForms System Engine

Page 59: Katello on TorqueBox

WHAT IS TORQUEBOX AND JRUBY

Page 60: Katello on TorqueBox

JRUBYRuby 1.8/1.9 on JVMmature and stable projectJIT and AOTbidirectionalis in Fedora

Page 61: Katello on TorqueBox

TORQUEBOXapplication platform for Ruby on Rails, Sinatra...runs atop of JBoss ASoffers services like messaging, scheduling, cachingallows use of clustering, load-ballancing and HAuses standards where possible

Page 62: Katello on TorqueBox

WHY SHOULD WE CARE?why to port to JVM

Page 63: Katello on TorqueBox

WHY SHOULD WE CARE?memory :-)

Page 64: Katello on TorqueBox

WHY SHOULD WE CARE?performance (skipping for this talk)

Page 65: Katello on TorqueBox

WHY SHOULD WE CARE?

Page 66: Katello on TorqueBox

MEMORY IS THE ISSUEbefore that we need to cover threads

Page 67: Katello on TorqueBox

MRI RUBY 1.8green threads

Page 68: Katello on TorqueBox

MRI RUBY 1.9native threads with GIL

Page 69: Katello on TorqueBox

GLOBAL INTERPRETER LOCKany time one thread is running _Ruby_ codeno other thread can be running _Ruby_ code

Page 70: Katello on TorqueBox

GLOBAL INTERPRETER LOCK

Page 71: Katello on TorqueBox

GLOBAL INTERPRETER LOCKsignificant barrier to parallelismdoes _not_ limit I/O by the designbut many native rubygems also limits I/O

Page 72: Katello on TorqueBox

STATE OF THREADING IN MRI RUBYnot the best

Page 73: Katello on TorqueBox

FORKING SERVERS IN MRI RUBYthreads are not the only options for web concurencyprocess forking can do the thing tooLinux is good in forkingunfortunately MRI Ruby can't leverage COW memory

Page 74: Katello on TorqueBox

FORKING SERVERS IN MRI RUBYRuby Enterprise Edition solves this for 1.8Ruby 1.9 has many REE optimalizations (but not COW)Ruby 2.0 will finally deliver COW-friendly forking(bitmaps)

Page 75: Katello on TorqueBox

STATE OF FORKING IN MRI RUBYnot the best

Page 76: Katello on TorqueBox

DEPLOYMENT OPTIONS WITH RUBYThe Ruby community has always insisted that performance

is not an issue while constantly searching for higherperformance web servers and application stacks. -- Greg

Weber

Page 77: Katello on TorqueBox

DEPLOYMENT OPTIONS WITH RUBYevented programming (reactor pattern) brings some

parallelism

Page 78: Katello on TorqueBox

DEPLOYMENT OPTIONS WITH RUBYforking - phusion passenger, unicornevented - thin, goliath, vert.xthreaded - mongrel, torquebox

Page 79: Katello on TorqueBox

DEPLOYMENT OPTIONS WITH RUBYcombination of forking + eventedcombination of threaded + eventedcombination of threaded + forking

Page 80: Katello on TorqueBox

DEPLOYMENT OPTIONS WITH RUBYthe issue with evented servers (thin) is granularity

Page 81: Katello on TorqueBox

DEPLOYMENT OPTIONS WITH RUBYcontroller - sql* - render - response*controller - sql* - render - response*controller - sql* - render - response*

Page 82: Katello on TorqueBox

DEPLOYMENT OPTIONS WITH RUBYto unleash power of evented processing, you need to rewrite

your application (fibers, goliath, node.js, vert.x, asyncsinatra)

Page 83: Katello on TorqueBox

DEPLOYMENT OPTIONS WITH RUBYthere are not many options for threading setups

Page 84: Katello on TorqueBox

SO WHEN TO CONSIDER JRUBY?you have an app that is not build around evented patternyour app takes decent amount of memoryyour app also contains lots of I/O operations (SQL,messaging, REST calls)you want to scale up

Page 85: Katello on TorqueBox

WARNINGI did not cover Rubinius or REE which partially solves some

of these issues

Page 86: Katello on TorqueBox

BY THE WAYthe following languages have concurrency built in the

runtimeerlanghaskellgoogle go

Page 87: Katello on TorqueBox

AND WHAT'S JAVA

Page 88: Katello on TorqueBox

BEFORE YOU START

Page 89: Katello on TorqueBox

TRY WITH JRUBY FIRSTinstead of torquebox

Page 90: Katello on TorqueBox

SLOW STARTjruby start a little bit slower

Page 91: Katello on TorqueBox

OPTIMIZE JRUBY START# JAVA_OPTS="-client -Djruby.compile.mode=OFF" \bundle exec rails server

Page 92: Katello on TorqueBox

OPTIMIZE JRUBY START# JRUBY_OPTS="--1.9 -J-XX:+CMSClassUnloadingEnabled \-J-XX:+UseConcMarkSweepGC \-J-XX:MaxPermSize=256m -J-Xmx1800m" \bundle exec rails server

Page 93: Katello on TorqueBox

OPTIMIZE JRUBY START# jruby --ng-server &# bundle exec rails server

Page 94: Katello on TorqueBox

KATELLO START IN DEV$ time bundle exec rake environment

real 0m19.876suser 0m18.244ssys 0m0.764s

Page 95: Katello on TorqueBox

KATELLO START IN PROD$ time rake environment

real 0m13.322suser 0m9.979ssys 0m2.817s

Page 96: Katello on TorqueBox

RUBYGEMS ARE SLOWmultiple directories approachruby needs to walk the treemany stat/open calls with ENOENTbundler adds more dirsrvm/rbenv adds even more dirs

Page 97: Katello on TorqueBox

HOW RUBY HANDLES REQUIRE# strace rake environment 2>&1 | grep ENOENT...open("x/ldap_fluff-0.1.3/lib/singleton.rb", O_RDONLY) = -1 ENOENTopen("x/net-ldap-0.3.1/lib/singleton.rb", O_RDONLY) = -1 ENOENT open("x/jshintrb-0.2.1/lib/singleton.rb", O_RDONLY) = -1 ENOENT open("x/js-routes-0.6.2/lib/singleton.rb", O_RDONLY) = -1 ENOENTopen("x/jammit-0.6.5/lib/singleton.rb", O_RDONLY) = -1 ENOENTopen("x/yui-compressor-0.9.6/lib/singleton.rb", O_RDONLY) = -1 ENOENTopen("x/i18n_data-0.3.3/lib/singleton.rb", O_RDONLY) = -1 ENOENT...

Page 98: Katello on TorqueBox

HOW RUBY HANDLES REQUIREO(n^2)

Page 99: Katello on TorqueBox

HOW RUBY HANDLES REQUIREoptimized in ruby 2.0

Page 100: Katello on TorqueBox

HOW RUBY 2.0 HANDLES REQUIREO(n^2) - k

Page 101: Katello on TorqueBox

HOW RUBY HANDLES REQUIREenough theory!

Page 102: Katello on TorqueBox

RUBYGEMS IN KATELLO# bundle install | wc -l120

Page 103: Katello on TorqueBox

KATELLO STAT/OPEN MISSES IN PROD# strace bundle exec rake environment 2>&1 | grep ENOENT | wc -l4023

Page 104: Katello on TorqueBox

KATELLO STAT/OPEN MISSES IN DEV# strace bundle exec rake environment 2>&1 | grep ENOENT | wc -l172342

Page 105: Katello on TorqueBox

KATELLO STAT/OPEN MISSES IN DEV

Page 106: Katello on TorqueBox

RUBYGEMS ARE SLOWand it's not getting better

Page 107: Katello on TorqueBox

RUBYGEMS ARE SLOWavoid bundleravoid rvm/rbenvuse bundler_ext

Page 108: Katello on TorqueBox

PORTING ISSUES

Page 109: Katello on TorqueBox

BINARY FILESwriting to a binary file needs b-flag

Page 110: Katello on TorqueBox

BINARY FILESFile.open("thefile.bin", 'wb') do |f| f.write(stuff)end

Page 111: Katello on TorqueBox

ACTIVERECORDinstall proper gems

Page 112: Katello on TorqueBox

ACTIVERECORDif defined? JRUBY_VERSION gem 'activerecord-jdbc-adapter' gem 'jdbc-postgres', gem 'activerecord-jdbcpostgresql-adapter',else gem 'pg'end

Page 113: Katello on TorqueBox

ACTIVERECORDvarious versions (rails 3.0 vs new adapter)

Page 114: Katello on TorqueBox

ACTIVERECORDERROR undefined method collect' for "created_at DESC":String (NoMethodError).../activerecord-jdbc-adapter-1.2.6/lib/arjdbc/postgresql/adapter.rb:620:in distinct'...

Page 115: Katello on TorqueBox

OTHER ISSUESimproper rails namespace:-)

Page 116: Katello on TorqueBox

RUBY AND SYSTEMTAP

Page 117: Katello on TorqueBox

WHAT IS SYSTEMTAPfree software infrastructure to simplify the gathering of

information about the running Linux system

Page 118: Katello on TorqueBox

WHY SYSTEMTAP IS USEFULno need to modify your appno need to restart it

Page 119: Katello on TorqueBox

WHY SYSTEMTAP IS USEFULsteep learning curveC-like syntax

Page 120: Katello on TorqueBox

WHY SYSTEMTAP IS USEFULvery low-levelsupports high-level (JVM, Python, Ruby)

Page 121: Katello on TorqueBox

WHY SYSTEMTAP IS USEFULpart of RHEL and Fedorakernels are systemtap readyRuby extension part of RHEL 6.2 (RHSA-2011-1581)

Page 122: Katello on TorqueBox

WHY SYSTEMTAP IS USEFULproject documentation and wikiRHEL6 SystemTap Beginners Guide

Page 123: Katello on TorqueBox

INSTALL SYSTEMTAP# yum -y install \systemtap \systemtap-runtime \kernel-debuginfo-uname -r \kernel-debuginfo-common-uname -i -uname -r \kernel-devel-uname -r

Page 124: Katello on TorqueBox

UC1: HUNTING FILE CHANGE# touch /test

Page 125: Katello on TorqueBox

UC1: HUNTING FILE CHANGE# ls -i /test274

Page 126: Katello on TorqueBox

UC1: HUNTING FILE CHANGE# ll /dev/md-0brw-rw----. 1 root disk 253, 0 Apr 17 10:23 /dev/dm-0

Page 127: Katello on TorqueBox

UC1: HUNTING FILE CHANGE# cat filechange.stpglobal ATTR_MODE = 1probe kernel.function("setattr_copy")!, kernel.function("generic_setattr")!, kernel.function("inode_setattr") { dev_nr = $inode->i_sb->s_dev inode_nr = $inode->i_ino

if (dev_nr == MKDEV($1,$2) # major/minor device && inode_nr == $3 && $attr->ia_valid & ATTR_MODE) printf ("%d %s(%d) %s 0x%x/%u %o %d\n", gettimeofday_us(), execname(), pid(), probefunc(), dev_nr, inode_nr, $attr->ia_mode, uid())}

Page 128: Katello on TorqueBox

UC1: HUNTING FILE CHANGE# stap -v filechange.stp 253 0 274 &# chmod 600 /test1334676922011223 chmod(6157) generic_setattr 0xfd00000/274 100600 0

Page 129: Katello on TorqueBox

UC2: DOWN THE RUBY STACK# cat factorial.rbdef factorial n f = 1; for i in 1..n; f *= i; end; fendputs factorial 42

Page 130: Katello on TorqueBox

UC2: DOWN THE RUBY STACK# cat calls.stp probe ruby.function.entry{ printf("%s => %s.%s in %s:%d\n", thread_indent(1), classname, methodname, file, line);}probe ruby.function.return{ printf("%s <= %s.%s in %s:%d\n", thread_indent(-1), classname, methodname, file, line);}

Page 131: Katello on TorqueBox

UC2: DOWN THE RUBY STACK# stap calls.stp -c "ruby factorial.rb"1405006117752879898543142606244511569936384000000000 0 ruby(16160): => Module.method_added in factorial.rb:1 13 ruby(16160): <= Module.method_added in factorial.rb:1 0 ruby(16160): => Object.factorial in factorial.rb:5 25 ruby(16160): => Range.each in factorial.rb:2 61 ruby(16160): => Fixnum.* in factorial.rb:2 ... 705 ruby(16160): <= Bignum.* in factorial.rb:2 712 ruby(16160): <= Range.each in factorial.rb:2 718 ruby(16160): <= Object.factorial in factorial.rb:2 0 ruby(16160): => Object.puts in factorial.rb:5 20 ruby(16160): => Bignum.to_s in factorial.rb:5 38 ruby(16160): <= Bignum.to_s in factorial.rb:5 53 ruby(16160): => IO.write in factorial.rb:5 74 ruby(16160): <= IO.write in factorial.rb:5 81 ruby(16160): => IO.write in factorial.rb:5 99 ruby(16160): <= IO.write in factorial.rb:5 106 ruby(16160): <= Object.puts in factorial.rb:5

Page 132: Katello on TorqueBox

UC2: DOWN THE RUBY STACK# cat rubycount.stp global fn_calls;probe ruby.function.entry{ fn_calls[classname, methodname] <<< 1;}

probe end { foreach ([classname, methodname] in fn_calls- limit 30) { printf("%dx %s.%s\n", @count(fn_calls[classname, methodname]), classname, methodname); }

delete fn_calls;}

Page 133: Katello on TorqueBox

UC2: DOWN THE RUBY STACK# stap rubycount.stp -c "ruby factorial.rb"140500611775287989854314260624451156993638400000000021x Bignum.*21x Fixnum.*2x IO.write1x Module.method_added1x Range.each1x Bignum.to_s1x Object.puts1x Object.factorial

Page 134: Katello on TorqueBox

UC3: RUBY "TOP"# cat ./ruby-top-modified.stpglobal fn_calls[10240];probe ruby.function.entry { if (isinstr(file, "katello")) fn_calls[pid(), file, methodname, line] <<< 1;}probe timer.ms(4000) { ansi_clear_screen() printf("%6s %80s %6s %25s %6s\n", "PID", "FILENAME", "LINE", "FUNCTION", "CALLS") foreach ([pid,filename,funcname,lineno] in fn_calls- limit 15) { printf("%6d %80s %6d %25s %6d\n", pid, filename, lineno, funcname, @count(fn_calls[pid, filename, funcname, lineno])); } delete fn_calls;}

Page 135: Katello on TorqueBox

BUNDLER_EXT

Page 136: Katello on TorqueBox

BUNDLER_EXThttp://rubygems.org/gems/bundler_ext

https://github.com/aeolus-incubator/bundler_ext

Page 137: Katello on TorqueBox

BUNDLER_EXT# cat Gemfilegem 'rails', '3.0.10'gem 'json'gem 'rest-client', :require => 'rest_client'gem 'jammit', '>= 0.5.4'gem 'rails_warden', '>= 0.5.2'gem 'net-ldap'gem 'oauth'gem 'ldap_fluff'

Page 138: Katello on TorqueBox

BUNDLER_EXTif File.exist?(File.expand_path('../../Gemfile.in', __FILE__)) require 'bundler_ext' BundlerExt.system_require(File.expand_path('../../Gemfile.in', __FILE__), :group1, :group2, Rails.env)else Bundler.require :group1, :group2, Rails.envend

Page 139: Katello on TorqueBox

WE ARE DONE

Page 140: Katello on TorqueBox

CREDITSGreg Weber - http://blog.gregweber.info/posts/2011-06-16-high-performance-rb-part3Ilya Grigorik -http://www.igvita.com/2008/11/13/concurrency-is-a-myth-in-ruby/inc.com - finish line picand world-famouse memegenerator.net