Mod passenger i Ruby Enterprise Edition

Posted by Piotr Sarnacki Tue, 17 Jun 2008 18:50:00 GMT

Dzisiaj opowiem wam bajeczkę o tym jak mod_passenger zeswatał ze sobą Apache’a i Railsy. :)

Jeżeli ktoś sądzi, że z tego związku nic nie będzie, to rzucam kilka zalet:
  • nie trzeba bawić się w konfigurację proxy i martwić o zajęte porty
  • nie trzeba monitorować mongreli (ja używałem do tego goda)
  • ogólna prostota użycia
  • dzięki ruby enterprise można zaoszczędzić 33% pamięci
  • upload buffering, czyli nie musimy się martwić o upload dużych plików – pliki są przesyłane do aplikacji railsowej dopiero, gdy zostaną w całości uploadowane na serwer
  • fair load balancing – zapytania są wysyłane do procesów, które mają najmniej klientów w kolejce. żeby uzyskać coś takiego używając nginxa trzeba było instalować dodatkowy plugin
  • liczba instancji aplikacji nie jest sztywno określone. używając nginxa trzeba było przewidzieć jaka liczba serwerów railsów będzie potrzebna dla danej aplikacji, jeżeli na dany serwis wchodziło mało osób niewykorzystane serwery zjadały pamięć. mod_passenger uruchamia kolejne instancje w miarę potrzeb.

Dodatkowo napisałem apache upload progress module , dzięki czemu z mod_passengerem można sklecić pasek postępu wysyłania plików na serwer (forma dokładnie taka sama jak z Nginx Upload Progress, więc jeżeli ktoś go używał, to nawet nic nie będzie musiał zmieniać w skryptach).

Mod Passenger

Aktualnie najnowszą wersją mod_passengera jest 1.9.1 (RC2), instrukcja instalacji jest na blogu phusion.

Po odpaleniu instalatora użytkownik jest prowadzony za rączkę, więc nikt nie powinien mieć probleów – lubię takie podejście, nie muszę się zastanawiać nad tym co i jak mam zrobić i kopiować i wklejać kolejnych komend.

Mod passenger sprawuje się na serwerze bardzo fajnie, do tej pory nie miałem żadnych problemów. Żeby zrestartować aplikację rails wystarczy utworzyć plik tmp/restart.txt w katalogu aplikacji.

Po instalacji można jeszcze dodać w configu apacha linijkę:
PassengerMaxPoolSize X

Zamiast X wstawiamy maksymalną liczbę instancji aplikacji odpalonych na raz. W dokumentacji twierdzą, że dla VPSa z 256 megabajtami pamięci ram dobrą wartością będzie tutaj 2, a dla serwera dedykowanego z 2GB ramu 30. Większa liczba aplikacji to więcej zajętego ramu, ale też więcej requestów do obsłużenia w danej chwili.

Ruby Enterprise Edition

O ile o mod passengerze jest dużo informacji, to o ruby enterprise edition jeszcze niewiele. Według niektórych nazwa jest nietrafiona i niefajna, niektórym nie podoba się, że phusion chce się na REE wypromować.

Mi to w zasadzie wszystko jedno jak się chłopaki z Phusion promują, kto na tym zarobi i jaka jest nazwa, o ile ta wersja będzie dobrze działała i rzeczywiście zmniejszała zużycie pamięci.

Żeby zainstalować ruby enterprise edition należy ściągnąć paczkę (najnowszą wersję paczki można znaleźć tutaj):
wget http://rubyforge.org/frs/download.php/38777/ruby-enterprise-1.8.6-20080623.tar.gz
Następnie ją rozpakować:
tar -zxvf ruby-enterprise-1.8.6-20080623.tar.gz
i uruchomić installer:
./ruby-enterprise-1.8.6-20080623/installer
Tyle mówi opis na stronie REE, ale to jeszcze nie wszystko. Na początek można stworzyć dowiązanie symboliczne dla REE:
ln -sf /opt/ruby-enterprise-1.8.6-20080623/bin/ruby /usr/bin/ruby-enterprise
Użytkownicy gentoo muszą również skopiować plik auto_gem, który automatycznie jest w tej dystrybucji dodawany do RUBYOPT:
cp /usr/lib/ruby/site_ruby/auto_gem.rb /opt/ruby-enterprise-1.8.6-20080623/lib/ruby/site_ruby

Po zainstalowaniu rubiego instaluje się też kilka gemów, ale to tylko podstawowe – resztę trzeba zainstalować samemu. Oczywiście można odpalić gem list i instalować kolejne gemy w danych wersjach, ale od czego mamy rubiego. Dosłownie w 2 minuty napisałem prosty skrypcik, który wyciąga nazwy i wersje gemów po czym instaluje je dla Ruby Enterprise Edition:


`gem list`.split("\n").each do |line|
  if line =~ /([0-9a-zA-Z_\-]*) \((.*)\)/
    gem, versions = $1, $2.split(", ")
    versions.each do |version|
      puts "Installing #{gem}, version: #{version}" 
      puts `ruby-enterprise /opt/ruby-enterprise-1.8.6-20080623/bin/gem install #{gem} -y --version '#{version}' 2>&1`
    end
  end
end
Teraz wystarczy dodać w configu apacha linijkę:
RailsRuby /opt/ruby-enterprise-1.8.6-20080623/bin/ruby

I możemy cieszyć się naszym własnym wypicowanym apachem z mod_passengerem w korporacyjnej wersji ;-)

Posted in  | Tags , , , ,  | 10 comments | no trackbacks

2 przydatne rzeczy w gicie

Posted by Piotr Sarnacki Tue, 03 Jun 2008 09:04:00 GMT

Usuwanie gałęzi ze zdalnego repozytorium:


git push {repository} :heads/{your_branch_here}

Usuwanie pliku z indexu bez usuwania go z systemu plików (przydatne gdy dodamy do .gitignore plik, który już istnieje):


git-update-index --force-remove sciezka/do/pliku

Taki szybki pościk ;-)

Posted in  | Tags , , , ,  | no comments | no trackbacks

Git

Posted by Piotr Sarnacki Tue, 08 Apr 2008 12:50:00 GMT

Jeżeli ktoś jeszcze nie zauważył społeczność frameworków Ruby on Rails i Merb przesiada się powoli na rozproszony system kontroli wersji Git. Na gita przechodzą Railsy, przeszedł już Merb, Rspec, sporo koderów wypuszczających popularne pluginy. Jednym słowem coś w tym musi być.

I rzeczywiście coś w tym jest.

O co chodzi? Jarosław Zabiełło na swoim blogu przedstawił kilka rozproszonych systemów kontroli wersji.

Jakie są zalety gita?

  • każdy posiadający kopię aplikacji posiada też całe repozytorium. Coś się rozwaliło? Trzeba zmienić serwer? Serwis,a na którym hostowałeś SVN’a padł? Smuteczek. Ale nie z gitem – repozytorium, które masz na dysku wystarczy.
  • Git jest dużo szybszy od SVNa
  • “Mobilność” – bardzo ważna dla mnie kwestia. Często wyjeżdżam i zdarza mi się pracować bez dostępu do netu. W przypadku SVNa musiałem wrzucić jeden mega commit z pierdylionem zmian. W przypadku gita commity lecą do repozytorium na dysku i później można je ewentualnie pchnąć (push) do publicznego repo.
  • Bardzo łatwa obsługa gałęzi. Pracując z gitem najlepiej wyrobić sobie nawyk tworzenia gałęzi przy każdej zmianie, lub grupie połączonych ze sobą zmian. Dzięki temu można pracować równolegle nad wieloma rzeczami nie zaśmiecając aplikacji. Później tylko łączymy gałęzie, które rzeczywiście są potrzebne, jeżeli coś nie wyjdzie można po prostu daną gałąź wyrzucić i po krzyku
  • dużo łatwiejsze wrzucanie zmian do projektów open source’owych, szczególnie z pomocą githuba (ale o tym za chwilę).

Ale kod leżący cały czas na dysku będzie mało przydatny. Dlatego można założyć sobie publiczne repozytorium. Stwierdziłem jakiś czas temu, że w trosce o swój czas, którego zawsze za mało, będę musiał ograniczyć wszelkie prace, których mogę stosunkowo łatwo uniknąć. Dlatego nie bawiłem się nawet w tworzenie swojego własnego publicznego repozytorium. Wygodniej skorzystać pracy innych ludzi ;-)

Obecnie najbardziej popularne (jedyne?) serwisy oferujące hosting repozytoriów gita to: GitHub i Gitorius. Gitorius jest w pełni darmowy, ale nie można na nim trzymać prywatnych repozytoriów. Na githubie za darmo można trzymać publiczne repozytoria (ogranicza nas 100mb – jeżeli chodzi o gita to bardzo dużo), za prywatne trzeba będzie zapłacić. Na razie można jeszcze korzystać za darmo, bo serwis jest w fazie beta.

Zarejestrowałem się na Githubie kilka dni temu i przeniosłem tam 2 ze swoich projektów. Github to bardzo fajny pomysł na stworzenie społeczności koderów (napisany oczywiście w railsach). Co daje taki serwis?

  • dostęp do rss’ów poszczególnych użytkowników, projektów, feed z wiadomościami z obserwowanych projektów
  • można jednym kliknięciem zrobić kopię aplikacji (fork) – jakie są tego korzyści opisał na blogu jeden z developerów merba Michael Ivey :Contributing to merb
  • można wysłać znajomym “pull request” – czyli prośbę o uaktualnienie, na przykład po ważnej aktualizacji

Dodatkowo dostajemy wszystkie zalety gita.

No to co? Przesiadka na jasną stronę mocy, z tego fuj fuj obleśnego i niefajnego SVNa, który tak chwaliłem kiedy się z nim zapoznałem ;-)

Posted in  | Tags , , , ,  | no comments | no trackbacks

HotRuby

Posted by Piotr Sarnacki Sat, 05 Apr 2008 05:31:00 GMT

Jakiś czas temu pojawiły się wzmianki o hotruby (tylko wtedy nie miałem czasu o tym napisać). Krótko mówiąc jest to “implementacja rubiego w javascripcie”. Możemy używać rubiego w przeglądarce i we flashu.

Kod rubiego jest wysyłany do skompilowania przez skrypt cgi, skrypt cgi kompiluje go do bytecodu, po czym javascript wykonuje ów bytecode.

Na stronie HotRuby jest wzmianka o tym, że składnia języka jest w większości zaimplementowana (na pewno nie ma wyjątków), ale jak na razie większość funkcji i bibliotek nie. Na razie nie wiem do czego mogłoby mi się takie połączenie przydać, ale patrząc na dema łatwo można zauważyć, że całkiem fajne rzeczy da się stworzyć z pomocą hotrubiego. Oby tak dalej.

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

Livequery

Posted by Piotr Sarnacki Mon, 03 Mar 2008 20:41:00 GMT

Pisałem jakiś czas temu o nieinwazyjnym javascripcie w ruby on rails. Zapomniałem wtedy napisać o pluginie do jQuery, który ułatwia pracę stosując nieinwazyjny javascript.

Livequery ułatwia znacznie korzystanie ze zdarzeń. Często podczas manipulowania DOM tworzy się i/lub usuwa nowe elementy. Co gdy przypiszemy do kilku elementów jakieś zdarzenie po czym dodamy nowe elementy?

Zmontowałem prosty przykład, na którym można to sprawdzić. Do pierwszej listy linki dodawane są bez żadnych dodatków. Zwykłe:


  $('<li><a href="#">Link</a></li>').appendTo($('.without ul'));

Dlatego funkcja clicked uruchomi się tylko dla 2 pierwszych linków.

W drugim przypadku dodałem bind dla nowo stworzonego elementu:

  $('<li><a href="#">Link</a></li>').
          appendTo($('.with ul')).
          bind('click', clicked);

Zdarzenie jest więc przypisywane również dla nowych linków.

Jednak gdy ilość różnych zdarzeń zaczyna się niepokojąco powiększać, a cały interfejs strony zmienia się przy każdym prawie kliknięciu często można zapomnieć o przypisaniu zdarzeń. Nawet jeżeli ktoś nie jest zapominalski, to zapewne jest leniwy (ponoć dobrego programistę cechuje lenistwo). Na ratunek przychodzi Livequery, plugin, który sam dba o przypisywanie lub usuwanie zdarzeń w razie manipulacji DOM.

Drugi przykład# wykorzystuje już LiveQuery – jak można łatwo zauważyć nie trzeba już dopisywać żadnych dodatkowych funkcji.

I jedno zmartwienie przy pisaniu mniej ;-)

Posted in  | Tags , , ,  | no comments | no trackbacks

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

Rails 2.0 i js.erb

Posted by Piotr Sarnacki Tue, 15 Jan 2008 20:36:00 GMT

Niedawno pisałem o nieinwazyjnym kodzie javascript w railsach. Wspomniałem tam o pluginie MinusMor, który dodaje pliki ejs. Czyli kod javascript parsowany erbem. Zainstalowałem plugin w mojej aplikacji przeniesionej na rails 2.0. Kod pluginu nie działa… zacząłem przeglądać kod railsów, żeby poprawić minusmor (w internecie nie mogłem znaleźć poprawki). Po chwili przemyślenia sprawdziłem co dzieje się gdy wyrzucę plik rjs. Komunikat o błędzie:


Missing template pages/index.js.erb in view path

Git! W railsach 2.0 możemy przecież wskazać jakiego parsera mają użyć.

Tworzymy plik index.js.erb. I jeszcze mała zmiana, ustawiamy brak layoutu, żeby renderował się sam template:

respond_to do |format|
  render.html
  render.js { render :layout => false }
end

I to wszystko! Po prostu działa.

Nawet lepiej. Można zdefiniować layout, na przykład:


render.js { render :layout => 'jquery' }
a w nim można na przykład napisać:

(function ($) {
  <%= yield %>
})(jQuery);

I można używać w template’ach js.erb $ pomimo tego, że wcześniej użyło się jQuery.noConflict.

Przeszukałem później jeszcze net w poszukiwaniu informacji na ten temat i znalazłem artykuł na mad.ly o dodaniu helperów z MinusMor

Posted in  | Tags , ,  | no comments | no trackbacks

Web3.0 - boję się!

Posted by Piotr Sarnacki Sun, 13 Jan 2008 10:58:00 GMT

Pan Urbanowicz, znawca internetu, napisał tekst o (uwaga uwaga, fanfary) Web3.0! A w nim przestraszył mnie nieźle:

Ale Web 3.0 niesie ze sobą również wiele zagrożeń: naruszanie swobód obywatelskich, kradzież danych, stopniową dehumanizację czy czipy biometryczne, będące w stanie śledzić wszystkie nasze ruchy. Jak w „Raporcie mniejszości”, każdy nasz krok będzie rejestrowany przez kamery, które będą komunikować z komputerami, a te porozumiewać się z serwisami identyfikującymi twarze. Kto wie, jak daleko może posunąć się inwigilacja ze strony agencji rządowych?

Oba światy: wirtualny i rzeczywisty będę się wzajemnie przenikały, automatycznie wzrośnie ilość spamu, wirusów i hakerów. Będzie więcej dezinformacji, więcej manipulacji i więcej cenzury. Web 3.0 nie będzie nas chronił bardziej niż Web 2.0, wprost przeciwnie, będziemy jeszcze bardziej narażeni na niebezpieczeństwa. Tworzymy świat, który trudno nam zrozumieć, a co dopiero mówić o jego kontroli.

Szkoda, że nie ma nic o głodzie, wojnach, najeźdźcach z kosmosu i pani Czesi spod piątki, która awanturuje się o każdą rzecz.

Boże, miej nas w swojej opiece! Albowiem Armagedon 3.0 nadchodzi!

Posted in  | Tags , ,  | 1 comment | no trackbacks

Przyjazne adresy w Ruby on Rails

Posted by Piotr Sarnacki Sat, 12 Jan 2008 10:47:00 GMT

W dzisiejszych czasach, kiedy SEO dla niektórych jest ważniejsze od treści przyjazne adresy można zobaczyć na większości stron. Dlaczego nie wrzucić ich do naszej aplikacji? Nawet jeżeli komuś nie zależy na SEO, przyjazne adresy są… przyjazne! Użytkownik dostający linka http://foo.com/article/kolejny-artykul-o-naszej-klasie będzie miał szansę zastanowić się sekundę i nie kliknąć (nie to żebym miał coś do naszej klasy, ale boję się ostatnio lodówkę otworzyć, jeszcze szynka zacznie nawijać kogo dodała do znajomych). Same korzyści!

Dodanie przyjaznych adresów jest w aplikacji railsowej bardzo proste jeżeli trzymamy się kilku zasad. Jak to działa? ActiveRecord::Base, po którym dziedziczą udostępnia metodę to_param, która jest wykorzystywana przy generowaniu adresów.

W praktyce wygląda to tak, że jeżeli napiszemy:
link_to @article.name, articles_path(@article)
#albo
link_to @article.name, :controller => "articles", :action => "show", :id => @article

wywołana zostanie metoda to_param i @article zostanie zamieniony na jego id. Można to wykorzysta do naszych niecnych celów.

Można nadpisać to_param
  def to_param
    "#{id}-#{name.gsub(/[^a-z0-9]+/i, '-')}" 
  end

Od teraz zamiast id będzie generował się string zawierający name, na przykład: “11-tytuł-artykułu”. Hamerykanie mają mniejszy problem, bo nie mają znaków diakrytycznych i mogą to tak zostawić. gsub zamieni wszystkie znaki nie wchodzące w skład alfabetu na myślnik. U nas jest gorzej, bo nie chcemy mieć adresu: “11-tytu-artyku-u”. I weź teraz zgaduj gdzie dorzucić ogonki. Z pomocą przychodzi Obie Fernandez, który napisał najfajniejszą jaką do tej pory widziałem metodą zamieniającą znaki diakrytyczne na odpowiadające im litery alfabetu Wrzuciłem na serwer wersję z polskimi znakami diakrytycznymi. Taki plik wystarczy wrzucić do folderu initializers dla Railsów 2.0.x, albo do katalogu lib dla 1.2.x (w tym wypadku trzeba też w environment.rb dodać linijkę require ‘ascii’). Zrobiłem jeszcze jedną modyfikację – to_url_format powinien moim zdaniem w miejsce spacji i innych znaków wrzucać myślniki. Lepiej wygląda “tytul-artykulu” niż “tytulartykulu”.

Dzięki temu String udostępnia 2 nowe metody: `to_url_format` i `to_ascii`:
"zażółć gęślą jaźń".to_ascii #=> "zazolc gesla jazn" 

"zażółć gęślą jaźń".to_url_format #=> "zazolc-gesla-jazn" 
Teraz wystarczy zmodyfikować lekko to_param:
  def to_param
    "#{id}-#{name.to_url_format}" 
  end

Dzięki temu urle będą miały upragnioną formę: “12-tytul-artykulu”.

Tylko po co to id na początku? Dzięki temu obędzie się bez żadnych zmian w kontrolerach. Taki string zostanie przed wrzuceniem do bazy automatycznie skonwertowany na liczbę całkowitą. Czyli kolejna rzecz, która “po prostu działa” automagicznie. Jeżeli id będzie potrzebne w jakimś innym miejscu, w którym nie nastąpi konwersja można to zrobić ręcznie: params[:id].to_i, bo:
"11-jakis-napis".to_i #=> 11

Jaki jest minus takiej metody? Adresy mają w sobie id i tylko na podstawie tego id jest pobierany artykuł, więc czy wpiszemy /articles/11-tytul-artykulu, czy /articles/11-tralalala pobierze się ten sam artykuł.

Żeby temu zapobiec najlepiej zrobić dodatkową kolumnę, na przykład “permalink” i wpisywać do niej przekształcony adres. Np. article.permalink = article.name.to_url_format . I zamiast po id szukać po kolumnie permalink: Article.find_by_permalink(params[:id]). Oczywiście z metody to_param też trzeba usunąć id :)

Nie każdemu to drugie podejście będzie potrzebne. Dla mnie wersja z id jest o tyle lepsza, że jak nawet ktoś nie skopiuje całego adresu, albo pomyli się przy wpisywaniu (tak, czasami zdarza się, że ktoś dyktuje jakiś adres), to jest duża szansa, że dotrze na dobrą stronę. Poza tym istnieje wtedy możliwość wklejenia adresu bez dalszej części, która może być dość długa – może nie trzeba będzie korzystać z serwisów typu tinyurl.

Posted in  | Tags , , , , , ,  | 4 comments | no trackbacks

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 | no trackbacks

Older posts: 1 2 3


Clicky Web Analytics