Stress-Test für HTTP-Seiten

Kürzlich war ich auf der Suche nach einem Tool, mit dem ich diesen Blog Stress-Testen konnte. Ich wollte sehen, was passiert, wenn (falls…) einmal unter Last kommt.

Es gibt verschiedene Dienste, die genau das im Internet anbieten, aber eine schnelle Suche hat nur solche zu Tage gebracht, die entweder Geld für die Tests verlangen (was ich bei der Menge des anfallenden Traffics auch verstehe) oder einen Gratis-Test nur gegen Veröffentlichung der Ergebnisse anbieten (z.B. loadimpact.com).

Also war ich auf der Suche nach einer leicht zu verwendenden Client-Lösung. Wiederum nach kurzer Web-Recherche stoß ich auf ab, was für ‘Apache Benchmark’ steht und angenehmerweise schon mit Apache ausgeliefert wird (z.B. im Paket apache-utils unter Debian/Ubuntu). Es ist ziemlich einfach zu verwenden (Details in der manpage), hält sich jedoch auch schlicht, d.h. es wird nur die angegebene URL abgefragt, keine Bilder, JavaScript, CSS oder was auch immer noch mit ausgeliefert werden würde. Aber in Verbindung mit der Netzwerk-Requestansicht der Developer-Tools des Browsers (in meinem Fall Chrome) lassen sich die langsameren Requests relativ leicht erkennen:

Chrome's Request timing zeigt, dass es Verbesserungsbedarf gibt (bzw. gab)

Chrome’s Request timing zeigt, dass es Verbesserungsbedarf gibt (bzw. gab)

Der erste Request auf die Seite selbst dauert fast 400ms. Apache-AB zeigt ein ähnliches Bild:

$ ab -c 10 -n 150 'http://manuel.reithuber.net/'
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking manuel.reithuber.net (be patient).....done
Server Software: Apache/2.2.16
Server Hostname: manuel.reithuber.net
Server Port: 80

Document Path: /
Document Length: 54520 bytes

Concurrency Level: 10
<strong>Time taken for tests: 29.540 seconds</strong>
Complete requests: 150
Failed requests: 0
Write errors: 0
Total transferred: 8234250 bytes
HTML transferred: 8178000 bytes
Requests per second: 5.08 [#/sec] (mean)
<strong>Time per request: 1969.323 [ms] (mean)</strong>
Time per request: 196.932 [ms] (mean, across all concurrent requests)
Transfer rate: 272.22 [Kbytes/sec] received

Connection Times (ms)
 min mean[+/-sd] median max
Connect: 11 12 2.8 11 38
Processing: 629 1936 215.9 1962 2257
Waiting: 472 1082 113.1 1097 1244
Total: 643 1948 216.0 1975 2267

Percentage of the requests served within a certain time (ms)
 50% 1975
 66% 2003
 75% 2060
 80% 2098
 90% 2167
 95% 2214
 98% 2242
 99% 2248
 100% 2267 (longest request)

Bei zehn parallelen Requests dauerte es im Schnitt fast zwei Sekunden, bis ein User seine Antwort bekommt! Und für 150 Requests war AB 30 Sekunden lang beschäftigt!

Ich wusste bereits, dass eine unoptimierte WordPress-Installation Optimierungsbedarf beim Thema Performance hat, aber damit hätte ich ehrlich gesagt nicht gerechnet (Ein Grund ist, dass bei mir aus Sicherheitsgründen PHP unter suexec läuft und unterschiedliche Websites unterschiedlichen user accounts zugeordnet sind).

Was kann man dagegen machen:

Das Stichwort hier ist Caching. Es gibt diverse WordPress-Plugins, die (z.B. unter Verwendung von memcached) statische Versionen einer Webseite zwischenspeichern. Aber ich wollte eine wirklich drastische Lösung. Wenn vorhanden, soll Apache direkt eine .html-Seite ausliefern und PHP soll gar nicht erst ausgeführt werden. Mit diesem Ziel im Auge bin ich auf das really-static WordPress Plugin gestoßen, dessen Ziel es ist, einen statischen Snapshot der WordPress-Seite zu erstellen und aktuell zu halten (es horcht auf Artikel- und Kommentar-Änderungen und aktualisiert automatisch die statischen .html-Seiten).

Es war nicht ganz so leicht, es nach meinen Wünschen einzurichten, aber jetzt werden anstatt der Artikel statische .html-Seiten ausgeliefert, die vom Plugin automatisch aktuell gehalten werden.Das really-static Plugin ist mMn noch nicht 100%ig ausgereift (Doku eher dürftig; man sollte mit der Konfiguration nicht zu sehr eigene Wege gehen wollen, da das Plugin sonst streiken könnte; und wenn das Plugin den Dienst (oder in meinem Fall den Einrichtungsassistenten) verweigert, ist die fehlende Struktur des Sourcecodes nicht unbedingt hilfreich). Aber zur Einrichtung des Plugins in einem eigenen Post mehr.

Zuguterletzt lasse ich noch einmal das Benchmark-Tool laufen, um die Performanceverbesserung zu überprüfen:


$ ab -c 10 -n 150 'http://manuel.reithuber.net/'

<em id="__mceDel">This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/</em>

Benchmarking manuel.reithuber.net (be patient).....done

Server Software: Apache/2.2.16
Server Hostname: manuel.reithuber.net
Server Port: 80

Document Path: /
Document Length: 49624 bytes

Concurrency Level: 10
<strong>Time taken for tests: 3.150 seconds</strong>
Complete requests: 150
Failed requests: 0
Write errors: 0
Total transferred: 7485900 bytes
HTML transferred: 7443600 bytes
Requests per second: 47.61 [#/sec] (mean)
<strong>Time per request: 210.022 [ms] (mean)</strong>
Time per request: 21.002 [ms] (mean, across all concurrent requests)
Transfer rate: 2320.53 [Kbytes/sec] received

Connection Times (ms)
 min mean[+/-sd] median max
Connect: 12 37 13.0 38 63
Processing: 99 169 195.8 153 2531
Waiting: 14 39 12.0 37 65
Total: 132 206 193.4 185 2543

Percentage of the requests served within a certain time (ms)
 50% 185
 66% 202
 75% 208
 80% 209
 90% 217
 95% 225
 98% 248
 99% 283
 100% 2543 (longest request)

Eine Verbesserung fast um Faktor 10, das kann sich doch sehen lassen ;)

KategorienUncategorized Tags:

Default-Netzwerkinterface in Qt unter Linux

Manchmal möchte man das Interface herausfinden, auf dem die Default-Route definiert ist.

Ich habe das z.B. verwendet, um MediaTomb daran zu hindern, im falschen Netzwerk zu horchen.

In Qt unter Linux kann man einfach das file /proc/net/route parsen:

QFile routeFile("/proc/net/route");
QString rc;

if (!routeFile.open(QFile::ReadOnly)) qWarn("Couldn't read routing information: %s", qPrintable(routeFile.errorString()));

QByteArray line;
while (!(line = routeFile.readLine()).isNull()) {
  QList&lt;QByteArray&gt; parts = line.split('\t');
  QByteArray intf = parts[0];
  QByteArray route = parts[1];
  QByteArray mask = parts[7];

  // Find make sure the destination address is 0.0.0.0 and the netmask empty
  if (route == "00000000" &amp;&amp; mask == "00000000") {
    rc = intf;
    break;
  }
}

return rc;

In der Shell würde dies z.B. so aussehen:

cut -f1,2,8 /proc/net/route --output-delimiter=:|grep 00000000:00000000$|cut -d: -f1
KategorienLinux Tags:

MP3-Support für Chromium

Ich hab’ mich in der Vergangenheit immer wieder mal mit dem HTML5 Audio Element gespielt und versucht, Icecast-Streams damit wiederzugeben. Während dies im Firefox tadellos funktioniert, macht Chrome Probleme. Der Stream lädt zwar (was im DOM Inspector zu sehen ist), aber wiedergegeben wird nichts.

Meine Vermutung war zuerst, dass Chrome (oder genauer gesagt: Chromium aus den Ubuntu-Repos) das gesamte File cached bevor er zu spielen beginnt.

Als ich heute wieder auf das Problem stieß, kam mir die Idee, dass die Unterstützung für das proprietäre MP3-Format in der  Open-Source-Version des Browsers fehlen könnte, was durch eine Websuche schnell bestätigt wurde.

Um das Problem zu lösen, reicht ein einfaches:

sudo apt-get install chromium-codecs-ffmpeg-extra

Nach einem Neustart des Browsers funktioniert nun auch die Wiedergabe von Shoutcast- bzw. Icecast-Streams im MP3-Format. Jetzt muss ich mich nur noch entscheiden, welche Javascript-Library ich als Fallback-Lösung für ältere Browser verwenden will (btw: audio.js sieht vielversprechend aus)

KategorienUncategorized Tags:

Remoteregistry aus der Ferne aktivieren

Falls der Versuch, sich mit einer Netzwerkregistrierung zu verbinden (wie im vorigen Post Remotedesktopverbindung aus der Ferne aktivieren), fehlschlägt, kann diese relativ einfach (ebenfalls übers Netzwerk) aktiviert werden.
Benötigt wird dazu nur ein erreichbarer Windows-PC mit Computerverwaltung.

Zuerst muss die Computerverwaltung lokal geöffnet werden (am einfachsten geht das mMn mit einem Rechtsklick auf den Arbeitsplatz (z.b. im Startmenü, am Desktop oder im Explorer) und anschließendem Klick auf Verwalten):

Computerverwaltung starten

Dann im Menü Aktion auf Verbindung mit einem anderen Computer herstellen:

"Verbindung mit einem anderen Computer herstellen"

Computerverwaltung: PC-Auswahl

Dann Links unter Dienste und Anwendungen auf Dienste klicken und rechts den Eintrag Remoteregistrierung auswählen. Anschließend auf Starten klicken:

Remoteregistrierungsdienst starten

Sollte der Link starten nicht sichtbar sein, kann es sein, dass der Dienst deaktiviert wurde. Dann einfach auf den Remoteregistrierungs-Eintrag rechtsklicken und die Eigenschaften aufrufen.
Im erscheinenden Fenster dann den Starttyp auf Manuell bzw. Automatisch stellen und den Dienst starten (was beim Typ Automatisch von selbst geschehen sollte).

Remotedesktopverbindung aus der Ferne aktivieren

Gerade erst gestern hatte ich das Problem, mich bei einem Kunden-PC entfernt anmelden zu müssen, bei dem die Remotedesktopverbindung deaktiviert war.

Glücklicherweise lässt sich diese aber per Registry aktivieren (welche wiederum Netzwerktauglich ist).

Dazu öffnet man einfach lokal den Registry-Editor (win+r, regedit):

Windows-Ausführungs-Dialog: "regedit"

klickt im Menü Datei auf Mit Netzwerkregistrierung verbinden

Regedit: Datei/Mit Netzwerkregistrierung verbinden

PC-Namen eingeben und bestätigen

und Navigiert zum Schlüssel

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server

Sollte hier die Verbindung fehlschlagen, liegt das sehr wahrscheinlich an einem deaktivierten Remoteregistry-Dienst am Client-Computer (Anleitung zum aktivieren: Remoteregistry aus der Ferne aktivieren)

Dort setzt ihr den Wert fDenyTSConnections auf 0:

Registry-Wert fDenyTSConnections auf 0 setzen

Quelle:
http://www.admins-tipps.de/Microsoft/Windows_2003_Server/Remotedesktop-Verbindungen_aus_der_Ferne_per_Registry_aktivieren.htm

KategorienWindows Tags: , ,

DNS Do’s and Dont’s

Hier mal ein paar Dinge, die man beim Domain-Verwalten beachten sollte und meist selbst “schmerzvoll” erfahren musste…

Mehr…

KategorienUncategorized Tags:

Barcode Scanner

Screenshot: Programm auf Barcode-Suche

Screenshot: Programm auf Barcode-Suche

Mit diesem Programm beginne ich meine Serie der Android Software Vorstellungen.

Der ZXing Barcode Scanner ist ein hilfreiches Tool, um (wie der Name schon sagt) Barcodes zu scannen.

Er ist Teil des ZXing Project (“Zebra Crossing”), einer Java-Barcode-Library, die unter der Apache License vertrieben wird.

Screenshot: eingescannter Barcode aus der Wikipedia

Screenshot: eingescannter Barcode aus der Wikipedia

Screenshot: Eingescannte ISBN eines Buchs

Screenshot: Eingescannte ISBN eines Buchs

Dabei werden neben den normalen 1D-Barcodes, wie sie auf fast jedem Produkt zu finden sind, auch zweidimensionale QR Codes erkannt.

Screenshot eines eingescannten QR-Codes

Screenshot eines eingescannten QR-Codes

Diese QR-Codes können beliebigen Text und/0der Links enthalten und werden immer häufiger eingesetzt (u.a. ab jetzt auch hier):

[sqrcode]market://search?q=pname:com.google.zxing.client.android[/sqrcode]

Beispielsweise ist im obigen Tag eine Android Market URL enthalten, die (wenn man den Code einscannt und auf “Open browser” klickt) automatisch den Android Market lädt und die entsprechende Applikation gesucht.

Als Alternative muss ich noch den ixMAT Barcode Scanner nennen, der zwar die gleiche GUI verwendet, aber mehr Barcodetypen unterstützt:

[sqrcode]market://search?q=pname:com.ixellence.ixmat.android.community[/sqrcode]

KategorienAndroid, Apps Tags:

T-Mobile G1 CheatSheet

Hier ein paar nützliche Tastenkombinationen für’s HTC Dream:
(inwieweit diese Anleitung auch für andere Android-Handys gilt, weiß ich nicht)

Android-Shortcut

  • Recent Apps
    Wenn man dne Home-Button für ein paar Sekunden hält, öffnet sich ein Fenster mit den kürzlich verwendeten Programmen

System

  • Bootloader:
    Der HTC Dream Bootloader ermöglicht es, händisch Firmware Upgrades einzuspielen.
    Bei den europäischen G1 wird dafür aber eine speziell modifizierte SD-Karte (“GoldCard”) benötigt.
    Gerät ausschalten, Kamera-Knopf halten, Power (Auflegen) drücken
    (um wieder aus dem Bootloader herauszukommen, muss ein SoftReset durchgeführt werden).
  • Soft-Reset:
    Sollte sich das Telefon einmal wider erwarten aufhängen (oder will man aus einem anderen Grund neu starten, so bietet sich der folgende Shortcut an:
    Anrufen+Menü+Auflegen
  • Hard-Reset (alle Einstellungen zurücksetzen!)
    Vor dem Verkauf oder dem gebrauchten Kauf des Handys sollte man auf jeden Fall einen Hard-Reset durchführen. Alle Programme, Daten und Einstellungen werden so gelöscht und beim nächsten Einschalten startet wieder der Einrichtungsassistent!
    Gerät ausschalten, Home+Zurück halten und Power drücken
    Alternativ lässt sich der Hard Reset auch über die Einstellungen durchgeführt werden (Einstellungen/SD-Karte und Speicher/Auf Werkszustand zurück)

Wenn ich noch andere Shortcuts finde, werde ich diese Liste natürlich ergänzen.

KategorienAndroid Tags: , , ,

Mein neues T-Mobile G1

Seit Samstag bin ich nun schon stolzer Besitzer eines HTC Dream (oder auch T-Mobile G1), das ich mir per eBay günstig ersteigert habe.
Da auf diesem Handy ein Linux-Derivat (namens Android) installiert ist, war für mich von Anfang an klar, dass ich es irgendwann mal in meinen Händen halten würde ;) .

Leider hat das Handy (nicht mehr lange ;) ) einen T-Mobile SimLock, wodurch ich mangels T-Mobile SIM mit Datenvertrag anfangs nicht gerade viel mit dem Handy anfangen konnte, da schon der Einrichtungsassistent einen Google-Account voraussetzte, zu dem er sich jedoch nicht verbinden konnte. Erst seit Android v1.5 kann die GMail-Einrichtung auf später verschoben werden (wodurch man vorher die WLAN-Verbindung einrichten kann…)

Da ich nicht bis zum unlocken (geht erst nach dem Wochenende) warten wollte, um das Smartphone einzusetzen, entschloss ich mich dazu, das Handy mittels händischem Downgrade zu rooten und den Einrichtungsassistent so zu auszutricksen (Anleitung folgt…). Ein Upgrade auf (irgemd eine Form von) 1.5 sollte danach ja kein Problem mehr sein.

Im Internet habe ich nach kurzer Suche eine Anleitung zur Erstellung einer so genannten Goldcard gefunden, mit der man dem Handy eine beliebige Firmwareversion unterjubeln kann (solange sie signiert ist, aber auch das kann umgangen werden, indem man nach dem rooten einen modifizierten Bootloader installiert).
So fand dann die rc7-Firmware ihren Weg aufs Handy, die den Bug enthielt, dass alle Tastatureingaben im Hintergrund auch an ein root-Terminal gesendet werden. So kann z.b. durch die Eingabe von reboot in einem beliebigen Programm ein Soft-Reset durchgeführt werden (oder auch – wenn man weiß wie – schon im Einrichtungsassistenten die WLAN-Verbindung konfiguriert werden).
Nachdem ich so das Handy endlich in einen verwendbaren Zustand gebracht habe, fing ich an, mich im Android Market nach sinnvollen Apps umzusehen (mehr dazu auch später in einem eigenen Post).
Nach wenigen Minuten erschien eine Benachrichtigung, dass eine neue Softwareversion zur Verfügung stehe. Ich hab dem Update natürlich sofort zugestimmt, da ich so wieder ein quasi unmodifiziertes Handy hatte, bei dem ich trotzdem ohne Datenverbindung die Einrichtung durchführen und so das Telefon nutzen konnte. Nach dem Update hab ich noch einmal einen Hard Reset durchgeführt, um eine konsistente OS-Basis sicherzustellen.
Wie erwartet ließ sich der Einrichtungsassistent ohne Internetverbindung abschließen und das Handy war (bis auf das vernachläßigbare Detail, dass ich damit noch nicht telefonieren kann…), einsatzbereit.
Sobald das Geld fürs unlocken ins PayPal überwiesen ist, kann ich dann auch meine geliebte Bob-SIM damit verwenden.

Auf jeden Fall gibts in diesem Blog in Zukunft den einen oder anderen Post zum Thema G1 bzw. Android.

PS.: diesen Eintrag hab ich am G1 mit der Software PostBot verfasst.

KategorienAndroid Tags:

Bash history tricks

In addition to the possibility to view/edit your ~/.bash_history manually, I’ve collected some little tips for the bash history:

  • Hide single commands from the bash history
    If your command line begins with a space character, it won’t be logged.
  • Log a command for later execution
    If you’ve just typed a long command line and realized that there’s other stuff to do before executing it, jump to its beginning (with Pos1) and type ‘#’. The command will then be treated as comment and won’t be executed. As soon as you’ve finished running all the other instructions use the history to get back to your comment. Remove the ‘#’ and execute it.
  • disable .bash_history file
    one simple way to disable the .bash_history file is to remove the write permission to it:

    chmod -w ~/.bash_history

    If you first edit your .bash_history file manually you can turn it into a permanent history list with all your favourite commands.

  • use the reverse search
    press Ctrl+R and then enter your search string. To edit the command (and exit the search mode) use tab or one of the position keys.
    The reverse-i-search always brings you the first match before the current history position
  • full history processing
    The history command lists the whole saved bash command history.
    You could use it e.g. to show the last 10 commands:

    history|tail -n 10

    or to show all lines containing the word “ssh”

    history|grep ssh

  • execute the last matching command
    If you want to run a command several times without scrolling through the history all the time you can use the ‘!’ at the start of the line to execute the last line that starts with your search string, e.g.

    !ssh

    will re-run the last invocation of ssh

  • clear local history
    To clear the session history (not the one in .bash_history) call

    history -c

  • read/write history
    If you have multiple sessions running and want to get the local history of one session to another one, you can use

    history -a

    to append the local history to .bash_history in the first terminal and

    history -r

    in the second terminal to read .bash_history
    Those parameters can also be combined (read man bash for detailed information)

KategorienLinux Tags: