mod_rubinius

Posted by Piotr Sarnacki Thu, 31 Jan 2008 09:09:00 GMT

Jakiś czas temu pisałem ,że mogą szykować się zmiany w deploymencie railsów. Dzisiaj przeczytałem, że Ezra Zygmuntowicz zatrudnił szóstego programistę, którego zadaniem będzie praca nad mod_rubinius dla serwerów Nginx i Apache. Więcej w podcaście z udziałem Ezry

Mały cytat:
More interesting things from the podcast:
  • In like one night Evan Phoenix implemented a multiple Rubinius VM running in single OS process in native threads and passing each other messages like it happens in Erlang). This can lead to a great solution to shared hostings and Ruby deployment problem David Hansson wrote about recently.
  • Rubinius may support native code compilation along side with bytecode that Rubinius VM can run. Sounds interesting. Ryan Davis is working on Rubinius at Engine Yard and his Ruby2C experiments may be useful.

Posted in  | Tags , , , , , , ,  | 2 comments | 1 trackback

Zmiany w deploymencie Ruby on Rails na horyzoncie?

Posted by Piotr Sarnacki Thu, 10 Jan 2008 18:16:00 GMT

Na blogu dreamhostu narzekają na bóle hostowania railsów. DHH (himself™) odpowiada, że developerzy z Railsów nie mają potrzeby zmian idących w kierunku ułatwienie deployment na dzielonych hostingach, ale chętnie pomogą jeżeli dostaną jakieś propozycje współpracy nad tym problemem. Na RubyInside jest artykuł, w którym autor zastanawia się co można poprawić.

Z jednej strony rozumiem podejście DHH: “nie pracujemy na dzielonych hostingach, więc nigdy nie mieliśmy potrzeby poprawy czegokolwiek”, a z drugiej strony od razu przychodzi na myśl mongrel napisany przez Zeda Shaw. W czasach “pre-mongrel” trzeba było w bólu i cierpieniach próbować zmusić lighttpd (albo apacha, wersja dla prawdziwych masochistów) do hostowania railsów via FastCGI. Gdyby nie Zed prawdopodobnie długo jeszcze przyszłoby męczyć się z takimi configami, nie sądzę, żeby DHH myślał nad jakimiś poprawkami w tym kontekście.

A wszystko zaczęło się od sławnego już artykułu Rails is a ghetto. Czyżby Zed Shaw kolejny raz, tym razem może w całkiem niezamierzony sposób, przyczynił się do poprawy sytuacji?

Mam nadzieję, że prace nad ułatwieniem deploymentu railsów niedługo się zaczną. Oznaczałoby to też poprawę uruchamiania skryptów rubiego w taki sam sposób jak skryptów php – wrzucam na serwer, wpisuję adres, dostaję wynik.

Poczekamy, zobaczymy, może coś się ruszy :)

Posted in  | Tags , , , ,  | 3 comments | 2 trackbacks

God.rb

Posted by Piotr Sarnacki Sat, 05 Jan 2008 09:40:00 GMT

Wpadłem jakiś czas temu na bardzo fajną aplikację wspomagającą deployment Ruby on Rails. god.rb monitoruje procesy i w razie potrzeby (out of memory, zbyt dużo pożartego cpu, pad serwera) restartuje je. Config, jak i sam god oczywiście, jest napisany w Ruby’im, więc można sobie nieco ułatwić pracę (wspominałem kiedyś, że nigdy nie miałem dość samozaparcia, żeby się nauczyć pisać skrypty powłoki pod linuxem?).

Aby go zainstalować należy jako root (pod ubuntu sudo) wykonać polecenie:
gem install god

Na stronie goda są podane różne configi, ale nie zakładają one scenariusza: “sporo aplikacji, taki sam config, jak to zrobić automatycznie?”. Pomyślałem sobie, że napiszę prosty config, który będzie pobierał listę aplikacji Rails z pliku i dodawał mongrele do monitorowania. Gdy na serwerze siedzi więcej aplikacji głupio byłoby kopiować config dla każdej z nich i ręcznie ustawiać numery portów i katalogi.

Pełny config z komentarzami wyjaśniającymi o co kaman (wersja tekstowa):
# run with:  god -c /path/to/config.god

require 'yaml'

# otwieramy plik ze spisem aplikacji i robimy z nich tablicę
rails_apps = File.open("/etc/god/applications", "r").readlines.collect { |app| app.strip }

for rails_app in rails_apps
  # załadujmy ustawienia danej aplikacji
  # korzystać będziemy z konfiguracji dla clusterów
  config = YAML::load(File.open(File.join(rails_app, "config/mongrel_cluster.yml")))
  config["servers"] ||= 1 # domyślnie startujemy jeden serwer

   # teraz stawiamy mongrela dla każdego portu
  ((config["port"].to_i)..(config["port"].to_i+config["servers"].to_i-1)).each do |port|  
    God.watch do |w|
      pid_file = File.join(rails_app, config["pid_file"].gsub(/\.pid$/, ".#{port}.pid"))
      w.name = "#{rails_app[/[^\/]*$/]}-mongrel-#{port}" 

      # dodajemy mongrele danej aplikacji do grupy o nazwie takiej samej jak nazwa katalogu
      w.group = "#{rails_app[/[^\/]*$/]}" 
      w.interval = 30.seconds # default      
      w.start = "mongrel_rails start -c #{rails_app} -p #{port} \
        -P #{pid_file}  -e #{config['environment']}  -d" 
      w.stop = "mongrel_rails stop -P #{pid_file}" 
      w.restart = "mongrel_rails restart -P #{pid_file}" 
      w.start_grace = 10.seconds
      w.restart_grace = 10.seconds
      w.pid_file = File.join(pid_file)

      w.behavior(:clean_pid_file)

      w.start_if do |start|
        start.condition(:process_running) do |c|
          c.interval = 5.seconds
          c.running = false
        end
      end

      w.restart_if do |restart|
        restart.condition(:memory_usage) do |c|
          c.above = 150.megabytes
          c.times = [3, 5] # 3 out of 5 intervals
        end

        restart.condition(:cpu_usage) do |c|
          c.above = 50.percent
          c.times = 5
        end
      end

      # lifecycle
      w.lifecycle do |on|
        on.condition(:flapping) do |c|
          c.to_state = [:start, :restart]
          c.times = 5
          c.within = 5.minute
          c.transition = :unmonitored
          c.retry_in = 10.minutes
          c.retry_times = 5
          c.retry_within = 2.hours
        end
      end

    end
  end
end

puts "kuniec" 
Aplikacje w pliku, który jest odczytywany na początku to ścieżki wpisane w kolejnych liniach. gdy wystartujemy goda poleceniem `god -c /sciezka/do/configu` uruchomią się mongrele dla wszystkich aplikacji. Ważne: powyższy config korzysta z konfiguracji stworzonych dla clusterów. Aby ją stworzyć należy wykonać w katalogu aplikacji:
mongrel_rails cluster::configure -e production -p 8000 -N 2

Powyższa komenda wygeneruje plik `mongrel_cluster.yml` w katalogu config aplikacji Ruby on Rails. Zostanie ustawione środowisko production, port 8000 i 2 serwery (na portach 8000 i 8001).

Żeby szczęście było pełne i niczym niezmącone można jeszcze pokusić się o napisanie skryptu startowego init.d. Oczywiście w ruby’im. A jakie to proste pokazywał kiedyś Jarek Zebiełło.

W razie wątpliwości pytajcie o szczegóły w komentarzach.

Posted in  | Tags , , , ,  | no comments | 1 trackback


Clicky Web Analytics