13.10.2012

Raspberry Pi als Webserver mit PostgreSQL, Ruby und Sinatra

Ein richtiger Webserver braucht eine Datenbank, um dynamischen Content zu erzeugen und ein Framework um den Content auszuliefern. PHP und mySql wird zwar oft verwendet, ich finde das aber eher langweilig.

Deshalb habe ich auf dem RasPi die PostgreSQL-Datenbank installiert, die sehr feine Features hat und Open Source ist.

Als Framework habe ich mir Sinatra ausgesucht. Für die Datenbank-Abstraktion ist Datamapper  zuständig. Das ganze wird dann via Rack deployed. Sinatra, Datamapper und Rack  sind in Ruby geschrieben, deshalb brauchen wir auch noch einen Ruby-Interpreter. Zunächst verwende ich dazu die Standard-Ruby-Implementierung, für Testzwecke dann auch noch JRuby (Ruby-Interpreter in Java, extra Post). Ruby/Postgres/Sinatra hat den weiteren Vorteil, daß die gleiche Applikation auf Heroku laufen kann, so daß man real-World-Benchmarks fahren kann.

Die Applikation, die ich teste, holt Werte nach Geolocation aus der Datenbank, rechnet einiges daran rum und liefert das per Ajax als JSON an eine Webapp.

Auf dem RasPi ist Soft-float Debian wheezy installiert (JRuby/Java, das ich auch testen will, läuft nur mit dem Soft-Float-ABI) .

Installation, als root auf dem RasPi eingeloggt.
  1. Postgres-Datenbank, Client und Libraries: apt-get install postgresql postgresql-client libpq5 libpq-dev
  2. Ruby:  apt-get install ruby
  3. Wir benötigen noch "Bundler", mit dem Ruby alles zum Deployment zusammenschnüren kann: gem install bundler
Nun hab ich Postgres so konfiguriert, daß ich von localhost per Netzwerk auf die Datenbank komme (/etc/postgresql/9.1/main/postgresql.conf und pg_hba.conf). Anschließend Datenbank-Benutzer angelegt, den Datenbank-Dump von Heroku geholt und auf dem RasPi eingespielt.

Nun wird die Sinatra-Applikation konfiguriert (Datenbank-User/Verbindung), mit "bundle install" zusammengeschnürt und dann mit "rackup config.ru" gestartet. Die Applikation liefert identisches JSON, wie die Installation auf Heroku. Das ist fein!

Erstes Ziel erreicht: der Raspberry Pi arbeitet als Webserver und liefert dynamischen Inhalt aus einer Datenbank!

Jetzt mal sehen, wie der RasPi sich zum Heroku-Minimal-Setup schlägt.

Als Baseline wird der Apache Bench ("ab") auf Heroku losgelassen. Dort läuft die Applikation in minimaler Ausstattung in der Heroku-free-Variante.

NB: Ich verwende "ab" hier ohne Concurrency mit 500 Zugriffen

Hier die Ergebnisse von "ab" auf Heroku (500 Requests):


Concurrency Level:      1
Time taken for tests:   196.944 seconds
Complete requests:      500
Failed requests:        0
Write errors:           0
Total transferred:      659000 bytes
HTML transferred:       536000 bytes
Requests per second:    2.54 [#/sec] (mean)
Time per request:       393.888 [ms] (mean)
Time per request:       393.888 [ms] (mean, across all concurrent requests)
Transfer rate:          3.27 [Kbytes/sec] received


Percentage of the requests served within a certain time (ms)
  50%    318
  66%    331
  75%    337
  80%    340
  90%    354
  95%    375
  98%    408
  99%    493
 100%  10804 (longest request)


Der erste Request nach Heroku dauert sehr lang (etwa 10 Sekunden), Heroku fährt in der Minimalvariante erstmal den Server hoch. Die nachfolgenden Requests dauern zwischen 300ms und 500ms (inclusive Netzwerk-Latenz).

Nun das gleiche auf dem Rasberry Pi:



Requests per second:    4.91 [#/sec] (mean)
Time per request:       203.817 [ms] (mean)
Time per request:       203.817 [ms] (mean, across all concurrent requests)

Percentage of the requests served within a certain time (ms)
  50%    193
  66%    194
  75%    195
  80%    196
  90%    197
  95%    201
  98%    500
  99%    507
 100%   1707 (longest request)




Wow! Die meisten Requests werden unter 200ms beantwortet. Schneller als Heroku! Allerdings fallen auch keine Netzwerk-Latenzen an, so daß  die Werte nicht direkt vergleichbar sind.

Dabei ist die Systemauslastung des RasPi gering:

top - 22:14:41 up  4:27,  3 users,  load average: 0.61, 0.43, 0.53
Tasks:  73 total,   1 running,  72 sleeping,   0 stopped,   0 zombie
%Cpu(s): 91.5 us,  3.3 sy,  0.0 ni,  4.6 id,  0.0 wa,  0.0 hi,  0.7 si,  0.0 st
KiB Mem:    236880 total,   148012 used,    88868 free,    11276 buffers
KiB Swap:   102396 total,        0 used,   102396 free,    69740 cached

  PID USER      PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND          
 8444 pi        20   0 49952  37m 4680 S  80.3 16.3   2:41.88 ruby1.9.1        
 8970 postgres  20   0 48368 8408 6108 S  12.3  3.5   0:06.70 postgres         
 9104 postgres  20   0  4660 1372 1048 R   1.3  0.6   0:00.39 top  


Es sind noch fast 90MB RAM frei! Postgres langweilt sich. Ich bin begeistert!

Ein Test mit Concurrency 10 schafft genau die gleiche Anzahl von Requests/Sekunde. Nicht schlecht.

Fazit

Ein Raspberry Pi kann für eine einfache Sinatra-Anwendung sehr gut mit Heroku in Minimalausstattung mithalten!

Nächster Schritt: Vergleich mit Sinatra unter JRuby,

Keine Kommentare:

Kommentar veröffentlichen