Skip to content

Instantly share code, notes, and snippets.

@kyledrake
Last active August 2, 2016 04:31
Show Gist options
  • Select an option

  • Save kyledrake/1498932 to your computer and use it in GitHub Desktop.

Select an option

Save kyledrake/1498932 to your computer and use it in GitHub Desktop.

Revisions

  1. kyledrake revised this gist Sep 26, 2014. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions gistfile1.rb
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    # This is Geoloqi.com's Rainbows! config file. We are using this in production to run all our web apps.
    # This is Neocities' Rainbows! config file. We are using this in production to run all our web apps.
    # It works really well for us and has been heavily load tested, so I wanted to share it with the community.
    #
    # In my opinion, this is the best way to deploy a ruby web application. Unlike EventMachine based solutions,
    @@ -21,7 +21,7 @@
    #
    # There are other benefits to using Rainbows! that aren't just related to concurrency:
    #
    # * It listens to unix signals, and can add/remove/restart workers with zero downtime! Geoloqi.com
    # * It listens to unix signals, and can add/remove/restart workers with zero downtime! Neocities.org
    # has never gone offline since we launched the site several months ago.
    #
    # * It provides mechanisms for logging and pid files, which we use to feed our process monitor.
    @@ -101,7 +101,7 @@
    #
    # Using this method we get 0 downtime deploys.

    old_pid = "/var/run/geoloqi/#{name}.pid.oldbin"
    old_pid = "/var/run/neocities/#{name}.pid.oldbin"
    if File.exists?(old_pid) && server.pid != old_pid
    begin
    Process.kill("QUIT", File.read(old_pid).to_i)
  2. kyledrake revised this gist Sep 26, 2014. No changes.
  3. kyledrake revised this gist Jan 4, 2012. 1 changed file with 3 additions and 2 deletions.
    5 changes: 3 additions & 2 deletions gistfile1.rb
    Original file line number Diff line number Diff line change
    @@ -41,8 +41,9 @@
    #
    # If you're using Rubinius, check out Puma: https://github.com/evanphx/puma
    #
    # If you have a completely insane amount of traffic, want to use EventMachine and are okay with using custom
    # EM libraries for IO, check out Sinatra::Synchrony: http://kyledrake.net/sinatra-synchrony
    # If you have a completely insane amount of traffic (hint: you probably don't), want to use
    # EventMachine and are okay with using custom EM libraries for IO, check out Sinatra::Synchrony:
    # http://kyledrake.net/sinatra-synchrony
    #
    # If this is too much and/or you don't care, check out Puma. Puma is basically Zbatery with ThreadPool, and it
    # works on MRI, JRuby, and Rubinius. Ultimately I'd like to see Puma be the default web server of choice,
  4. kyledrake revised this gist Jan 4, 2012. 1 changed file with 4 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion gistfile1.rb
    Original file line number Diff line number Diff line change
    @@ -34,13 +34,16 @@
    # http://rainbows.rubyforge.org
    #
    # ALTERNATIVES
    #
    #
    # If you're using Heroku, check out Zbatery. Same as Rainbows!, but without the fork: http://zbatery.bogomip.org
    #
    # If you're using JRuby, check out: http://www.engineyard.com/blog/2011/taking-stock-jruby-web-servers
    #
    # If you're using Rubinius, check out Puma: https://github.com/evanphx/puma
    #
    # If you have a completely insane amount of traffic, want to use EventMachine and are okay with using custom
    # EM libraries for IO, check out Sinatra::Synchrony: http://kyledrake.net/sinatra-synchrony
    #
    # If this is too much and/or you don't care, check out Puma. Puma is basically Zbatery with ThreadPool, and it
    # works on MRI, JRuby, and Rubinius. Ultimately I'd like to see Puma be the default web server of choice,
    # and perhaps even have it replace Webrick as the ruby web server in the standard library.
  5. kyledrake revised this gist Jan 4, 2012. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions gistfile1.rb
    Original file line number Diff line number Diff line change
    @@ -23,7 +23,9 @@
    #
    # * It listens to unix signals, and can add/remove/restart workers with zero downtime! Geoloqi.com
    # has never gone offline since we launched the site several months ago.
    #
    # * It provides mechanisms for logging and pid files, which we use to feed our process monitor.
    #
    # * When we restart, the master process starts one copy of the worker application, and then forks it to
    # create the rest of the workers. This is -much- faster than the Mongrel/Thin approach, which has to start
    # one worker at a time (the dreaded "rolling restart").
  6. kyledrake revised this gist Jan 4, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion gistfile1.rb
    Original file line number Diff line number Diff line change
    @@ -87,7 +87,7 @@
    ##
    # When sent a USR2, Rainbows! will suffix its pidfile with .oldbin and
    # immediately start loading up a new version of itself (loaded with a new
    # version of our app). When this new Unicorn is completely loaded
    # version of our app). When this new Rainbows! is completely loaded
    # it will begin spawning workers. The first worker spawned will check to
    # see if an .oldbin pidfile exists. If so, this means we've just booted up
    # a new Rainbows! and need to tell the old one that it can now die. To do so
  7. kyledrake revised this gist Jan 4, 2012. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions gistfile1.rb
    Original file line number Diff line number Diff line change
    @@ -85,12 +85,12 @@

    before_fork do |server, worker|
    ##
    # When sent a USR2, Unicorn will suffix its pidfile with .oldbin and
    # When sent a USR2, Rainbows! will suffix its pidfile with .oldbin and
    # immediately start loading up a new version of itself (loaded with a new
    # version of our app). When this new Unicorn is completely loaded
    # it will begin spawning workers. The first worker spawned will check to
    # see if an .oldbin pidfile exists. If so, this means we've just booted up
    # a new Unicorn and need to tell the old one that it can now die. To do so
    # a new Rainbows! and need to tell the old one that it can now die. To do so
    # we send it a QUIT.
    #
    # Using this method we get 0 downtime deploys.
  8. kyledrake revised this gist Jan 4, 2012. 1 changed file with 12 additions and 1 deletion.
    13 changes: 12 additions & 1 deletion gistfile1.rb
    Original file line number Diff line number Diff line change
    @@ -30,7 +30,18 @@
    #
    # If you haven't looked at Rainbows! yet, and you're using MRI, I strongly recommend taking a look:
    # http://rainbows.rubyforge.org

    #
    # ALTERNATIVES
    #
    # If you're using Heroku, check out Zbatery. Same as Rainbows!, but without the fork: http://zbatery.bogomip.org
    #
    # If you're using JRuby, check out: http://www.engineyard.com/blog/2011/taking-stock-jruby-web-servers
    #
    # If you're using Rubinius, check out Puma: https://github.com/evanphx/puma
    #
    # If this is too much and/or you don't care, check out Puma. Puma is basically Zbatery with ThreadPool, and it
    # works on MRI, JRuby, and Rubinius. Ultimately I'd like to see Puma be the default web server of choice,
    # and perhaps even have it replace Webrick as the ruby web server in the standard library.

    Rainbows! do
    # Set the app name so we can re-use this file easily.
  9. kyledrake revised this gist Jan 4, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion gistfile1.rb
    Original file line number Diff line number Diff line change
    @@ -12,7 +12,7 @@
    #
    # This approach will likely be a little slower than EventMachine-based servers (like Thin), but I think this
    # will provide better throughput for modern web applications (which almost always deal with a lot of slower IO).
    # Best of all, you can use existing ruby software and don't have to use special EventMachine code to make IO not
    # You can use existing ruby software and don't have to use special EventMachine code to make IO not
    # block.
    #
    # The one potential caveat to this approach is that your code must be thread safe. But this problem is rare
  10. kyledrake revised this gist Jan 4, 2012. 1 changed file with 4 additions and 3 deletions.
    7 changes: 4 additions & 3 deletions gistfile1.rb
    Original file line number Diff line number Diff line change
    @@ -10,9 +10,10 @@
    # includes things like Net::HTTP and even `system commands`. Grep the MRI Ruby source code for
    # "rb_thread_blocking_region" if you'd like to explore how this works.
    #
    # This approach will likely be a little slower than EventMachine-based servers (like Thin), but most applications
    # have dependencies on remote APIs with a lot of blocking IO, so I think this will provide better throughput
    # for modern web applications (which almost always deal with a lot of slower IO).
    # This approach will likely be a little slower than EventMachine-based servers (like Thin), but I think this
    # will provide better throughput for modern web applications (which almost always deal with a lot of slower IO).
    # Best of all, you can use existing ruby software and don't have to use special EventMachine code to make IO not
    # block.
    #
    # The one potential caveat to this approach is that your code must be thread safe. But this problem is rare
    # in practice, and when in doubt, you can always wrap the action in a Mutex lock.
  11. kyledrake revised this gist Jan 4, 2012. 1 changed file with 88 additions and 41 deletions.
    129 changes: 88 additions & 41 deletions gistfile1.rb
    Original file line number Diff line number Diff line change
    @@ -1,47 +1,94 @@
    # This is Geoloqi.com's Rainbows! config file. We are using this in production to run all our web apps.
    # It works really well for us and has been heavily load tested, so I wanted to share it with the community.
    #
    # In my opinion, this is the best way to deploy a ruby web application. Unlike EventMachine based solutions,
    # it uses real ruby threads, which allows it to take advantage of the internal non-blocking IO pattern
    # in MRI.
    #
    # Contrary to popular belief, MRI doesn't block execution to wait on IO when you are using threads, even
    # with the GIL. The requests are done concurrently for anything that is based on the IO class. This
    # includes things like Net::HTTP and even `system commands`. Grep the MRI Ruby source code for
    # "rb_thread_blocking_region" if you'd like to explore how this works.
    #
    # This approach will likely be a little slower than EventMachine-based servers (like Thin), but most applications
    # have dependencies on remote APIs with a lot of blocking IO, so I think this will provide better throughput
    # for modern web applications (which almost always deal with a lot of slower IO).
    #
    # The one potential caveat to this approach is that your code must be thread safe. But this problem is rare
    # in practice, and when in doubt, you can always wrap the action in a Mutex lock.
    # If you see a thread safety problem/bug, make sure to let the author know about it so it can get fixed!
    #
    # There are other benefits to using Rainbows! that aren't just related to concurrency:
    #
    # * It listens to unix signals, and can add/remove/restart workers with zero downtime! Geoloqi.com
    # has never gone offline since we launched the site several months ago.
    # * It provides mechanisms for logging and pid files, which we use to feed our process monitor.
    # * When we restart, the master process starts one copy of the worker application, and then forks it to
    # create the rest of the workers. This is -much- faster than the Mongrel/Thin approach, which has to start
    # one worker at a time (the dreaded "rolling restart").
    #
    # If you haven't looked at Rainbows! yet, and you're using MRI, I strongly recommend taking a look:
    # http://rainbows.rubyforge.org


    Rainbows! do
    # Set the app name so we can re-use this file easily.
    name = 'website'

    # This enables the Rainbows! Thread Pool, which is best for YARV (1.9.x)
    use :ThreadPool
    client_max_body_size nil # This is set in nginx
    # keepalive_timeout 1

    case ENV['RACK_ENV'].to_sym
    when :development
    listen 9292
    when :production
    worker_processes 6
    worker_connections 32
    timeout 30
    listen "unix:/var/run/#{name}.sock", :backlog => 2048
    pid "/var/run/#{name}.pid"
    stderr_path "/var/log/#{name}.log"
    stdout_path "/var/log/#{name}.log"

    ###
    # Hardcore performance tweaks, described here: https://github.com/blog/517-unicorn
    ###

    # This loads the app in master, and then forks workers. Kill with USR2 and it will do a graceful restart using the block proceeding.
    preload_app true

    before_fork do |server, worker|
    ##
    # When sent a USR2, Unicorn will suffix its pidfile with .oldbin and
    # immediately start loading up a new version of itself (loaded with a new
    # version of our app). When this new Unicorn is completely loaded
    # it will begin spawning workers. The first worker spawned will check to
    # see if an .oldbin pidfile exists. If so, this means we've just booted up
    # a new Unicorn and need to tell the old one that it can now die. To do so
    # we send it a QUIT.
    #
    # Using this method we get 0 downtime deploys.

    old_pid = "/var/run/geoloqi/#{name}.pid.oldbin"
    if File.exists?(old_pid) && server.pid != old_pid
    begin
    Process.kill("QUIT", File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH
    # someone else did our job for us
    end

    # This is set in nginx for us, so we don't set it here.
    client_max_body_size nil

    # This is the number of worker processes there will be. You can remove/add using signals during runtime.
    # One per core isn't a bad rule of thumb, but there is still the GIL so I usually add a few more.
    worker_processes 6

    # This variable is different based on what concurrency strategy you use, but for ThreadPool it sets the
    # number of threads in the pool. Don't set this too high or else you'll starve your app. 32 works well for us.
    worker_connections 32

    # How long to hold the request open until timing out.
    timeout 30

    # Listen on a socket, and set a high backlog to avoid "resource unavailable" errors under heavy load.
    # It has been suggested that you should lower the backlog if you are using an HTTP load balancer.
    # Sockets are a little more efficient than TCP/IP, generally 5-10% faster. You may need to tweak sysctl,
    # the default settings on many unix machines don't allow the app to have enough open files to queue a lot
    # of traffic up.
    listen "unix:/var/run/#{name}.sock", :backlog => 2048

    pid "/var/run/#{name}.pid"
    stderr_path "/var/log/#{name}.log"
    stdout_path "/var/log/#{name}.log"

    ###
    # Hardcore performance tweaks, described here: https://github.com/blog/517-unicorn
    ###

    # This loads the app in master, and then forks workers. Kill with USR2 and it will do a graceful restart
    # using the block proceeding.
    preload_app true

    before_fork do |server, worker|
    ##
    # When sent a USR2, Unicorn will suffix its pidfile with .oldbin and
    # immediately start loading up a new version of itself (loaded with a new
    # version of our app). When this new Unicorn is completely loaded
    # it will begin spawning workers. The first worker spawned will check to
    # see if an .oldbin pidfile exists. If so, this means we've just booted up
    # a new Unicorn and need to tell the old one that it can now die. To do so
    # we send it a QUIT.
    #
    # Using this method we get 0 downtime deploys.

    old_pid = "/var/run/geoloqi/#{name}.pid.oldbin"
    if File.exists?(old_pid) && server.pid != old_pid
    begin
    Process.kill("QUIT", File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH
    # someone else did our job for us
    end
    end
    end
  12. kyledrake created this gist Dec 19, 2011.
    48 changes: 48 additions & 0 deletions gistfile1.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,48 @@
    Rainbows! do
    name = 'website'
    use :ThreadPool
    client_max_body_size nil # This is set in nginx
    # keepalive_timeout 1

    case ENV['RACK_ENV'].to_sym
    when :development
    listen 9292
    when :production
    worker_processes 6
    worker_connections 32
    timeout 30
    listen "unix:/var/run/#{name}.sock", :backlog => 2048
    pid "/var/run/#{name}.pid"
    stderr_path "/var/log/#{name}.log"
    stdout_path "/var/log/#{name}.log"

    ###
    # Hardcore performance tweaks, described here: https://github.com/blog/517-unicorn
    ###

    # This loads the app in master, and then forks workers. Kill with USR2 and it will do a graceful restart using the block proceeding.
    preload_app true

    before_fork do |server, worker|
    ##
    # When sent a USR2, Unicorn will suffix its pidfile with .oldbin and
    # immediately start loading up a new version of itself (loaded with a new
    # version of our app). When this new Unicorn is completely loaded
    # it will begin spawning workers. The first worker spawned will check to
    # see if an .oldbin pidfile exists. If so, this means we've just booted up
    # a new Unicorn and need to tell the old one that it can now die. To do so
    # we send it a QUIT.
    #
    # Using this method we get 0 downtime deploys.

    old_pid = "/var/run/geoloqi/#{name}.pid.oldbin"
    if File.exists?(old_pid) && server.pid != old_pid
    begin
    Process.kill("QUIT", File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH
    # someone else did our job for us
    end
    end
    end
    end
    end