Ein paar Tipps zur Apache2 konfiguration

Apache wird nachgesagt ein eher behäbiger und vorallem speicherfressender Webserver zu sein. Das mag bei schlechter Konfiguration auch stimmen.

Ich selber betreibe Apache auf allen Webservern unter meiner Fuchtel und habe noch nie besondere Performanceprobleme bemerkt (ausser natürlich bei aufwendigen MySQL-Abfragen via PHP, aber das ist eine ganz andere Geschichte).

Zunächst sollte man sich über die Hardware, welche einem zur verfügung steht im Klaren sein. Das ist vor allem bei V-Servern nicht immer einfach, hier sollte man so kalkulieren, dass einem ein Drittel der Host-CPU-Kerne zur verfügung stehen.

Auf den meisten Apache2-Servern wird MPM-Prefork laufen, da die meisten Webserver mit allerlei Scriptsprachen (vor allem PHP) ausgestattet sind. Apache benutzt Forking (oder Threading) um mehrere Surfer gleichzeitig mit Internetseiten bedienen zu können, alle Anfragen die nicht sofort von einem “Worker” abgearbeiten werden können werden in eine Warteschlange gesteckt und bald möglichst bedient.

Folgendes ist ein Beispiel aus einem 12-Kern-System, die einzelnen Werte erkläre ich dann sofort.

<IfModule mpm_prefork_module>
    StartServers         12
    MinSpareServers      12
    MaxSpareServers      12
    MaxClients           24
    MaxRequestsPerChild  50
</IfModule>

StartServers sagt Apache wie viele Prozesse nach starten des Servers sofort verfügbar sein sollen.

MinSpareServers sagt Apache wie viele Prozesse mindestens immer zur freien verfügung stehen sollen.

MaxSpareServers sagt Apache wie viele Prozesse er höchstens im vorraus starten darf.

MaxClients sagt Apache wie viele Prozesse er höchstens insgesamt starten (MixSpareServers startet bei erreichen des Wertes auch keine neuen Prozesse mehr) darf.

MaxRequestsPerChild sagt Apache nach wievielen bedienten Anfragen ein Prozess beendet oder neu gestartet werden soll (je nach bedarf). Das schützt vorallem vor extremen Speicheranhäufungen der Apache-Prozesse.

Generell empfiehlt es sich im leerlauf für jeden CPU-Kern einen Prozess zu haben, so können im Beispiel schonmal 12 Surfer gleichzeitig bedient werden. Maximal darf Apache 24, also theoretisch zwei Prozesse für pro Kern starten, was auch Problemfrei funktioniert, da die wenigsten Anfragen wirklich Leistung benötigen. Bei einer 2 GHz-CPU kann man auf einem durchschnittlichen Webserver auf welchem PHP-Anwendungen laufen getrost bis zu fünf Prozesse pro Kern als Maximalwert angeben.

Bei HyperThreading CPUs muss man ein bisschen experimentieren und von den ganzen tollen HT-Kernen die man so hat in der Konfiguration ggf. einen oder zwei abziehen. Da habe ich leider keine Erfahrung.

Als letzten Tipp: Wenn Apache anfängt die Warteschlange zu benutzen steht das meistens auch im globalen Log von Apache. Wenn man einen solchen Eintrag findet nicht gleich in Panik geraten, sondern das System mal eine Runde beobachten. Sollte es sich wirklich um Prozessmangel handeln, addiert man die Kernzahl auf den MaxClients wert drauf und läd Apache neu.

Hoffe das gibt einigen eine Idee, eigene Erfahrungen dürfen sehr gerne in Kommentaren geteilt werden!

Minecraft-Server mit Screen steuern

Das man Minecraft-Server via

screen -dmS meinserver java -jar minecraft-server.jar -Xmx1G

in den Hintergrund starten lassen, man dann via

screen -r meinserver

wieder in die Minecraft-Konsole gelangt und zuletzt mit dem Tastenkürzel Ctrl+A, D die Minecraft-Konsole wieder verlässt sollte ein alter Hut sein.

Ich möchte hier vorstellen, wie man einfache Befehle (zB für Backups) auch ausführen kann ohne in die Mc-Konsole wechseln zu müssen. Diese Variante funktioniert mit allen gängigen Minecraft-Servern, wie z.B. Bukkit.

Im laufe des Artikels wird ein Bash-Steuerscript erstellt, welches dazu dient Befehle direkt ausführen zu können und dann ein simples Backups-Script erstellt welches das Steuerscript nutzt.

Fangen wir also an, zunächst schreiben wir uns das Grundgerüst des Steuerscriptes:

#!/bin/bash
 
# der Dateiname der Server-Jar, darf auch ein absoluter Pfad sein
SERVER_NAME="minecraft_server.jar"
 
# der Name der Screen-Session die Erstellt und verwaltet wird
SCREEN_NAME="meinserver"
 
if [ $# -gt 0]; then
    case $1 in
    "start")
        ;;
    "stop")
        ;;
    "restart")
        ;;
    "save-off")
        ;;
    "save-on")
        ;;
    "save-all")
        ;;
    "say")
        ;;
    "--help")
        ;;
    esac;
else
    $0 --help;
fi;

Nun kann man schon grob erahnen wo das ganze hin führen wird. Wir werden in der Lage sein, den Server von der normalen Linux-Konsole aus zu stoppen, zu starten, neu zu starten, die Welt zu speichern und etwas als [SERVER] zu sagen. Des weiteren schreiben wir uns auch eine Hilfe, damit wir nicht vergessen wie das Script zu bedienen sein wird.

Zunächst schreiben wir uns eine Helfs-Funktion, welche einen Befehl ausführt:

mc_cmd() {
       screen -S $SCREEN_NAME -p 0 -X stuff "`printf "$*\r"`";
}

Die Bereiche Start, Stop und Restart werden um die folgenden Zeilen ergänzt:

        "start")
                echo -n "Starting minecraft... ";
                screen -dmS $SCREEN_NAME java -Xmx1536M -Xms64M -jar $SERVER_NAME && echo "OK";
                ;;
        "stop")
                say "Stoppe in 5 Sekunden.";
                sleep 5;
                echo -n "Stopping minecraft... ";
                mc_cmd stop && echo "OK";
                ;;
        "restart")
                $0 stop;
                sleep 5;
                $0 start;
                ;;

Zusätzlich bauen wir noch wrapper für save und say ein:

        "save-off")
                mc_cmd save-off && echo "save-oFF.";
                ;;
        "save-on")
                mc_cmd save-on && echo "save-oN.";
                ;;
        "save-all")
                mc_cmd save-all && echo "save-ALL.";
                ;;
        "say")
                say $2;
                ;;

Zum Schluss die Hilfe:

        "--help")
                echo "Usage: ./run.sh <Command> [<Options>]";
                echo "";
                echo "Available commands are:";
                echo "  start          Starts the server.";
                echo "  stop           Stops the server.";
                echo "  restart        Restarts the server.";
                echo "  save-off       Turns level saving off.";
                echo "  save-on        Turns level saving on.";
                echo "  save-all       Saves the level.";
                echo "  say <msg>      Prints <msg> to the game chat.";
                ;;

Nun das Backup-Script, welche den Ordner “world” in einen Tarball mit Timestamp packt. Das Script von oben wird unter ./run.sh aufgerufen.

#!/bin/bash
./run.sh say "[BACKUP] Starte. Speichere Welt...";
./run.sh save-off;
./run.sh save-all;
cp -R world bak_tmp && ./run.sh say "[BACKUP] Gespeichert, komprimiere ...";
./run.sh save-on;
nice -n +5 tar -cf - bak_tmp | nice -n +5 gzip -9 - > world-$(date "+%d-%m-%Y_%H-%M").tar.gz;
rm -R bak_tmp;
./run.sh say "[BACKUP] Alles Fertig.";

Nicht vergessen, beiden Scripten ausführungsrechte zu geben (via chmod u+x scriptname.sh). Dann Spaß beim Minecraft-Fernsteuern haben!

Wer rausfindet, wie man prüft ob eine Screen-Sitzung noch läuft darf das gerne in die Kommentare schreiben!

Lese-/Schreib-Cache beim Dell PERC H200 aktivieren

Die in Dell-Servern standardmäßig verbauten PERC RAID-Controller bieten umfangreiche Konfigurations- und RAID-Möglichkeiten. Bei den Standardeinstellungen von neuen RAID-Verbunden wurde allerdings die Failsafe-Variante gewählt, was nicht nur unperformant ist sondern auch arge Probleme auf Servern mit hoher Festplattenaktivität mit sich ziehen kann.

Der Controller bietet die Möglichkeit einen Lese- sowie Schreib-Cache zu aktivieren. Der Lesecache ist standardmäßig aktiviert, jedoch nicht der Schreibcache, was dazu führt, dass Schreibzugriffe das System verlangsamen oder sogar aufhalten. Beim Versuch den Schreibcache im BIOS zu aktivieren, versucht eine Warnmeldung vor möglichem Dateiverlust einem dies wieder aus zu reden. Ganz unrecht hat die Warnmeldung nicht, in abartig seltenen Fällen (z.B. bei einem Stromausfall) gehen Daten, welche sich noch im Schreibcache befanden, verloren (da die Daten ja noch im Cache und nicht auf der Festplatte waren). Da das aber ein gut kalkulierbares Risiko ist (zumindest in europäischen Rechenzentren) und man sowieso ständig Backups auf andere Server zieht, kann man den Cache getrost aktivieren.

Wer schon eine bestehende RAID-Konfiguration hat und nicht ins BIOS-Menü möchte, kann den Cache auch nachträglich via OpenManage aktivieren. Der Befehl über das Kommandozeilentool lautet:

omconfig storage vdisk action=changepolicy controller=0 vdisk=0 diskcachepolicy=enabled
# die nummern für controller= und vdisk= entsprechend anpassen
# der befehl setzt alle policy-optionen auf caching (lesen und schreiben)

Weitere Informationen finden sich im OpenManage Manual unter http://support.dell.com/support/edocs/software/svradmin/1.9/en/stormgmt/cli.html#1093196

Viel Erfolg, und wie immer eigene Erfahrungen und Infos in die Kommentare!

Wie man eigene Dijits/Dojo Widgets schreibt (HowTo)

Dojo erfreut sich immer größerer Beliebtheit, so auch die Dijits aus der Dojo-Dijit-Bilbiothek. Nun ist man nicht auf die vor gefertigten Dijits beschränkt, sondern kann auch eigene erstellen. Dazu benötigt man HTML und JavaScript-Erfahrungen.

So, nicht viel geschwafel, sondern direkt los legen. Zuerst importiert man die Basisklassen:

dojo.require("dijit._Widget");
dojo.require("dijit._Templated");

dijit._Widget ist die Basisklasse für Dijits generell und dijit._Templated ist ein sehr nützlicher Dijit-Zusatz zur Markup-Verwaltung.

Danach erstellt man seine Klasse mittels dojo.declare, wobei wir uns der zuvor geladenen “Mix-Ins” bedienen. In die hinteren geschweiften Klammern kommt gleich unser eigentlicher Code.

dojo.declare("my.widget", [ dijit._Widget, dijit._Templated ], {});

In dem Beispiel hier werden wir einfach “Hallo Welt” ausgeben, um zu verstehen wie Dijits aufgebaut sind. Dazu schreiben wir uns erst ein bisschen Markup (HTML) in die Code-Klammern:

{
    templateString: "<div data-dojo-attach-point='ausgabeDiv'></div>",
    postCreate: function () {}
}

Die Namen, die man Elementen via data-dojo-attach-point gibt, lassen sich nach postCreate als Eigenschaften in this verwenden. postCreate ist also so zu sagen der Konstruktor.

Dennoch schreiben wir uns erst eine Funktion, welche “Hallo Welt” in unser Div schreiben soll:

    schreibHalloWelt: function ()
    {
        this.ausgabeDiv.innerHTML = "Hallo Welt!";
    }

Dann rufen wir das ganze im postCreate einfach auf:

this.schreibHalloWelt();

Sodass der gesamte Code am Ende so aussieht:

dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.declare("my.widget", [ dijit._Widget, dijit._Templated ], {
    templateString: "<div data-dojo-attach-point='ausgabeDiv'></div>",
 
    postCreate: function () 
    {
        this.schreibHalloWelt();
    },
 
    schreibHalloWelt: function ()
    {
        this.ausgabeDiv.innerHTML = "Hallo Welt!";
    }
});

Ein solches Dijit erstellt man später ganz normal durch den Namen, den man Ihm gegeben hat, in HTML z.B. so:

<div data-dojo-type="my.widget" data-dojo-props=""></div>

Über die data-dojo-props lassen sich Eigenschaften der Klasse ändern, da in diesem Beispiel aber keine Eigenschaften vorhanden sind, klappt das hier auch nicht.

Viel Erfolg, und eigene Erfahrungen und Infos gerne in den Kommentaren schreiben!