Image Wechsel bei Mouseover mit CSS

Diesen Effekt sieht man im Internet häufig bei Menü- oder Navigationsleisten. Ein Image ändert sich – zum Beispiel die Schrift – wenn man mit der Maus darüber fährt. Der Effekt ist eigentlich einfach, denn anhand eines MouseOver-Ereignisses muss lediglich das Image ausgetauscht werden. Dies bedeutet, dass wir auf jeden Fall zwei Images benötigen.
Bisher hat man sich bei diesem Effekt meist auf JavaScript eingelassen. Der MouseOver-Effekt wurde per JavaScript abgefangen und das Image getauscht. Heute möchten wir den Effekt ausschließlich per CSS realisieren, denn der Effekt soll auch funktionieren, wenn Benutzer JavaScript deaktiviert haben. Ferner soll der Link, der hinter dem Image steckt, auch bei mobilen Browsern funktionieren, die kein CSS können. Aber gleich vorneweg: Der CSS-Effekt, den wir heute hier beschreiben, funktioniert bei allen aktuellen mobilen Geräten, mit denen ich ihn testen konnte.


LCD, LED oder Plasma-TV

Im vorliegenden Fall benötigen wir mehrere Images auf einer Seite, die zu speziellen Informationsseiten linken sollen. Diese Boxen sollen auffallen, aber eben nicht auffallen. Schwierig? Der Gedanke bei diesen Informationsboxen ist, dass sie ihrer Farbe beraubt werden und erst bei einem überfahren mit der Maus (MouseOver) ihre eigentliche Brillanz erhalten sollen. Dadurch, dass die Images „verwischt“ sind, fallen sie nicht sofort ins Auge und stören das eigentliche Layout nicht. Auf den zweiten Blick fallen jedoch die Images eben durch die zurückgenommene Brillanz auf und sollen neugierig machen.

Verblasstes Images mittels Gimp erstellen
Wir erstellen zuerst das fertige Image. In diesem Fall benötigen wir ein Image mit abgerundeten Kanten. Das fertige Image wird verblasst. Wie wir diesen Effekt am besten realisieren, ist im Artikel „Gimp: Bild verblassen lassen“ beschrieben. Wir benötigen also zum Schluss von jedem Image zwei Versionen. Das „strahlende“ und das „verblasste“ Image.

Image-Wechsel mit CSS umsetzen
Dem Image-Wechsel möchten wir mit CSS umsetzen. Hierzu fügen wir einen Link sowie einen Span-Container im Body an der gewünschten Stelle ein. Sollte CSS nicht funktionieren, wird der Text innerhalb der Span-Tags angezeigt. Der Link als solches wird immer funktionieren.
<a href=“http://www.mein-ziel.de“><span>Linktext</span></a>

Als nächstes benötigen wir einen CSS-Bereich. Für jedes Image benötigen wir eine eigene Klasse (was der einzige Nachteil dieser Variante ist). Wir blenden als erstes den Span-Tag aus und weisen dem dazugehörigen Link das Image als Background-Image zu.
Im Mouse-Over-Fall  („hover“: wir fangen auch „Active“ und „Focus“ ab) wechseln wir das Image aus.
Wir weisen also dem Link im „Normalfall“ das helle, im Hover- bzw. MouseOver-Fall das farbintensive Bild zu:

<html>
<head>
<TITLE>Image Wechsel bei Mouseover</TITLE>

<style type="text/css">

/* WechselImage 1 */
.wechselimg1 span {
    display: none;
}
.wechselimg1:link, .wechselimg1:visited {
    display: block;
	width: 239px;
	height: 58px;
    background:         url(kaffeetraeume_hell.png);
}
.wechselimg1:hover, .wechselimg1:active, .wechselimg1:focus {
    background-image:       url(kaffeetraeume.png);
}

/* WechselImage 2 */
.wechselimg2 span {
    display: none;
}
.wechselimg2:link, .wechselimg2:visited {
    display: block;
	width: 239px;
	height: 58px;
    background:         url(fernseher_hell.png);
}
.wechselimg2:hover, .wechselimg2:active, .wechselimg2:focus {
    background-image:       url(fernseher.png);
}

/* WechselImage 3 */
.wechselimg3 span {
    display: none;
}
.wechselimg3:link, .wechselimg3:visited {
    display: block;
	width: 239px;
	height: 58px;
    background:         url(rasur_hell.png);
}
.wechselimg3:hover, .wechselimg3:active, .wechselimg3:focus {
    background-image:       url(rasur.png);
}

</style>

</head>

<body>
<H1>Image Wechsel bei Mouseover</H1>

<a href="http://www.zieldomain.de" class="wechselimg1"><span>Kaffee</span></a>
<a href="http://www.zieldomain.de" class="wechselimg2"><span>TV</span></a>
<a href="http://www.zieldomain.de" class="wechselimg3"><span>Rasur</span></a>

</body>
</html>

Gimp: Bild verblassen lassen

Um ein Bild verblassen zu lassen, gibt es mehrere Möglichkeiten, dies in Gimp zu realisieren. Der Punkt „Verblassen“ in Gimp liegt nahe, ist jedoch nur in wenigen Fällen aktiv.

Abwedeln / Nachbelichten
Eine Möglichkeit, eine Grafik verblassen zu lassen, ist der Punkt „Abwedeln/Nachbelichten“ unter „Werkzeug/Malerwerkzeug“. Nach der Auswahl einen möglichst großen Pinsel wählen, dann mit dem Werkzeug über das Image fahren. Die Belichtung kann und muss vielleicht verändert werden. Wichtig ist bei diesem Verfahren, dass jede Stelle des Images mit dem Werkzeug überfahren wurde.

Deckkraft reduzieren
Die vielleicht bessere Möglichkeit ist, die Deckkraft der Ebene zu reduzieren. Hierzu muss das Image einer Ebene zugewiesen sein. Dann kann im Fenster „Ebenen“ die Ebene ausgewählt und mittels des Schiebereglers „Deckkraft“ die Deckkraft reduziert werden. Wenn der Hintergrund durchscheint, ist das Werk vollbracht. Eventuell ist es sinnvoll, noch eine transparente Ebene in den Hintergrund zu schieben.

Bereiche/Ränder verblassen lassen
Wie man Ränder eines Bildes verblassen lassen kann, habe ich bereits im Artikel „Gimp: Bild Rand ausblenden“ beschrieben. Dort geht es um die automatisierte Ausblendung aller vier Ränder. Je nach Einstellung kann dies auch auf weniger Ränder reduziert werden.
Oft steht man jedoch vor der Aufgabe, ein Bild zu einer oder mehreren Seiten auslaufen oder verwischen lassen, damit der Rand des Bildes nicht zu hart zum Hintergrund erscheint.
Für diese Aufgabe eignet sich der Gimp-Verlaufstyp „VG nach Transparent“ hervorragend. Wenn man beispielsweise ein Bild zum Rand hin verblassen lassen möchte, nutzt man als Verlaufsfarbe Weiß. Wir legen also im Fenster „Ebenen“ eine neue transparente Ebene an, die über dem Image liegt. Dann wählen wir im Werkzeugkasten „Farbverlauf“ „VG mach Transparent“ und stellen als Farbe die Hintergrundfarbe (Weiß) ein. Nun ziehen wir das Werkzeug vom Bereich, der die Hintergrundfarbe bekommen soll, zum Bereich, an dem der Farbverlauf enden soll. Hier muss man ein wenig experimentieren, bekommt aber sehr schnell brauchbare Ergebnisse.

Verlauf mit Radierer erstellen
Manchmal möchte man nur Teile oder einzelne Bereiche verwischen, verblassen oder auslaufen lassen. Für diese Aufgabe eignet sich der Radierer gut. Man wählt dazu eine passende Größe des Radierers aus und experimentiert mit der Deckkraft. Ich fange meist mit einer mittleren Einstellung an. Ich schiebe also den Schieberegler irgendwo zwischen 40 und 60 Prozent. Nun werden einfach die Bereiche oder Kanten des Bildes „wegradiert“, was in diesem Fall ein verwischen bedeutet.

Bereiche Transparent machen
Dieses Problem stellt sich immer wieder, ist aber sehr einfach zu lösen. Unter die Bildebene eine neue, transparente Ebene, einfügen (Ebene/Neue Ebene/Einfügen – Transparent). Dann auf der Ebene mit dem Image die Bereiche auswählen, die man transparent haben möchte. Nun wählt man Löschen oder drückt STRG+X. Die Auswahl wird transparent.

Runde Ecken
Wir möchten nun nicht darüber diskutieren, ob eine Ecke rund sein kann …. Abrundungen sind in Gimp sehr schnell und leicht zu erstellen. Wir nehmen eine Grafik auf einer Ebene und wählen „Auswahl/Abgerundetes Rechteck“. Dann stellen wir den Radius der Ecken ein. Angewendet wird uns eine Maske erzeugt. Diese muss nun invertiert werden. Dann können mittels Löschen die Bereiche entfernt werden. Wenn ein transparenter Layer unter unserem Image liegt, erscheint das Image als abgerundetes Image.

Wie man eine MySQL Replikation überwacht und repariert

Wer eine MySQL-Datenbank spiegelt (Master/Slave), muss die Replikation öfters kontrollieren, denn im laufenden Betrieb können sich Fehler einschleichen und die Replikation wird gestoppt. Wer denn beispielsweise eine Webseite per Load Balancer gespiegelt hat, wird seinen Kunden nicht auf jedem Frontend-Server die gleichen Daten präsentieren. Aus diesem Grund muss die Replikation überwacht werden. Heute möchten wir uns mit der prinzipiellen Überwachung auseinandersetzen. Denn nur wer weiß, was MySQL für Fehler erzeugen kann und wie man diese per Hand bereinigt, kann sich dann Gedanken um eine Automation oder Überwachung machen.
Dass ein Fehler bei der MySQL-Replikation vorliegt, kann beispielsweise über das Syslog („/var/lib/mysql/mysqld.log“) darauf stoßen. Oder die MySQL-Konsole meldet via SLAVE STATUS einen Fehler.

So ist prinzipiell bei einem MySQL-Replikations-Fehler vorzugehen:

  1. Anmelden an der MySQL-Konsole mittels „mysql -u root –p“ [RETURN], Eingabe des Passwortes.
  2. Abfrage des Replikation-Status mit „SHOW SLAVE STATUS G”. Das “G” steht für die formatierte Ausgabe.

Wenn der Slave einen Fehler meldet, ist dieser sowie das SQL-Statement, welches den Fehler verursacht hat, in der Statusmeldung ersichtlich. Nun ist zu prüfen, wie verfahren werden soll. Eventuell soll nur der fehlerverursachende Befehl übersprungen werden. Dann ist wie folgt zu verfahren:

  1. Den Slave stoppen mit: STOP SLAVE;
  2. Den Befehl überspringen mit SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
  3. Den Slave wieder zur Replikation anfahren mit : START SLAVE;
  4. Den Replikationsprozess überwachen mit SHOW SLAVE STATUS G
  5. Die MySQL-Konsole beenden mit: quit;

Erkennen, dass die MySQL-Replikation fehlerhaft ist
Über die MySQL-Konsolen-Befehl „SHOW SLAVE STATUS G“ erfährt man alles wissenswerte über den Prozess. Neben den Parameter „Last_Error“ und „Last_Errno“ sollte auf die Parameter „Slave_IO_Running“ und „Slave_SQL_Running“ geachtet werden.. Die Parameter „Last_error“ enthalten eine Fehlernummer und gegebenenfalls ein SQL-Kommando, das einen Fehler verursacht. Aus den Parametern „Slave […] Running“ erfährt man, ob die Replikation noch läuft. Wenn einer der beiden Parameter auf „NO“ steht (oft nur Slave_SQL_Running), dann muss man sich um die Fehlerbehebung kümmern.

Gerne gesehene Fehler einer MySQL-Replikation
Wer eine Datenbank repliziert und nicht nur auf dem Master, sondern auch auf dem Slave mit den Tabellen arbeitet, kann sehr schnell zu folgendem INSERT-Problem kommen. Dann nämlich, wenn der Master Datensätze in eine Tabelle einfügt und ein oder die Slaves in diese (replizierte) Tabelle ebenfalls Datensätze hinzufügen. Selbst wenn die laufende IDs über die Tabelle per „AUTO_INCREMENT“ hinzufügt, tappt man sehr schnell in die Falle und erzeugt einen doppelten Schlüssel (Duplicated Key). Denn die INSERT-Befehl auf dem Master, der vielleicht ohne explizite Angabe einer Datensatz-ID ausgeführt wurde („AUTO_INCREMENT“), wird über das Binär-Log auf dem Slave explizit, also genau mit der ID ausgeführt, die auch auf dem Master eingefügt wurde. Fügt jetzt auch noch der Slave in diese Tabelle auf dem Slave Datensätze hinzu, kann die ID bereits vergeben sein und die MySQL-Replikation schlägt fehl. Das Verhalten ist klar, denn wenn die Replikation die Vergabe der ID dem Slave überlassen würde, könnte so der Spiegel auseinanderlaufen.

Konfiguration eines Apache Load Balancer

Nun ist es endlich soweit, wir wollen einen Apache Load Balancer konfigurieren. Die Planungen für unser Web sind abgeschlossen (Planungen zum Aufbau für einen Apache Load Balancer). Ohne hier noch einmal auf die MySQL Replikation eingehen zu wollen, stellt sich die Systemkonfiguration wie folgt da:

Server 1: DNS, NS, Load-Balancer
Server 2: cl1.domain.de
Server 3: cl2.domain.de

Wir erreichen also über domain.de Server 1 und wollen die Anfrage per Load Balancer auf einen der beiden Web-Frontend-Server (cl1 und cl2) routen.

Apache-Module aktivieren
Wir benötigen auf unseren Frontend-Server nur das Modul „mod_rewrite“. Per Putty verbinden wir uns als Root auf die Server und aktivieren das Modul:

a2enmod rewrite

Danach starten wir den Apachen neu:
/etc/init.d/apache2 force-reload

Aktuell benötigen wir keine Session serverübergreifend, da wir programmseitig sichergestellt haben, dass ein User auf einem zugeteilten Server verbleibt (und die Zugriffe nicht über einen längeren erfolgt). Ansonsten sollten wir noch folgende Rewrite-Rule auf jedem Client (mit der richtigen cl-Adresse) hinzufügen:

[…]
RewriteEngine On
RewriteRule .* – [CO=BALANCEID:balancer.cl1:.domain.de]
[…]

Konfiguration des Load-Balancer
Unser Server mit dem Load-Balancer soll unter www.domain.de erreichbar sein. Dies müssen wir per DNS sicherstellen. Ferner benötigen wir die untenstehenden Apache-Module, die wir mit dem Befehl „a2enmod“ aktivieren können.

a2enmod proxy
a2enmod proxy_balancer
a2enmod proxy_http
a2enmod status

Den Apache neu starten
Wie nach jeder Konfiguration müssen wir den Apache-Dienst neu starten:
/etc/init.d/apache2 force-reload

Der Balance-Manager
Eine schöne Geschichte ist der Balance-Manager, den der Apache mitbringt. Dieser ist via http erreichbar. Über ihn können einige Informationen zur Laufzeit abgerufen und eingestellt werden.
Der Balance-Manager benötigt ein nach Möglichkeit passwortgeschütztes Verzeichnis. Per Plesk legt man dieses über die Oberfläche an. Per Konsole gilt der untenstehende Weg:

Anlegen des Verzeichnisses „balance-manager“
mkdir /var/www/balancer-manager

User/Passwort anlagen [USER]= „admin“ oder ähnliches
htpasswd -c /var/.htpasswd [USER]

Nun öffnen wir einen Texteditor
vi /var/www/balancer-manager/.htaccess

Eingabe im Editor
AuthType Basic
AuthName „Members Only“
AuthUserFile /var/.htpasswd
<limit GET PUT POST>
require valid-user
</limit>

So, nachdem nun die Vorbereitungen für den Balance-Manager abgeschlossen wurden, kommen wir zur eigentlichen Konfiguration. Diese findet in der Datei „vhost.conf“ (unter Plesk in „/var/www/vhost/domain.de/conf/“) statt.

Debian-Installationen gehen so vor:

cp /etc/apache2/sites-available/default /etc/apache2/sites-available/default_orig
cat /dev/null > /etc/apache2/sites-available/default
vi /etc/apache2/sites-available/default

Hinzufügen in der Config-Datei
Achtung, beachten Sie die „/“! Dies ist meist eine Fehlerquelle.
Hinweis für Plesk-Nutzer: In die vhost.conf gehört nur der Teil ab (inklusive) „ProxyRequests Off“ bis „</Location>“ (inklusive).

NameVirtualHost *
<VirtualHost *>
        ServerName www.domain.de
        ServerAlias domain.de
        DocumentRoot /var/www/
        ProxyRequests Off

        <Proxy *>
          Order deny,allow
          Allow from all
        </Proxy>

        ProxyPass /balancer-manager !
        ProxyPass / balancer://mycluster/ stickysession=BALANCEID nofailover=On
        ProxyPassReverse / http://cl1.domain.de/
        ProxyPassReverse / http://cl2.domain.de/
        <Proxy balancer://mycluster>
          BalancerMember http://cl1.domain.de  route=cl1
          BalancerMember http://cl2.domain.de  route=cl2
          ProxySet lbmethod=byrequests
        </Proxy>

        <Location /balancer-manager>
          SetHandler balancer-manager

          Order deny,allow
          Allow from all
        </Location>
</VirtualHost>

Zur Erklärung:

ProxyPass /balancer-manager !
Verzeichnisse, die hier mit „ProxyPass“ und „!“ angegeben sind, werden vom Load-Balancer ausgenommen; sie werden also lokal aufgerufen. Wenn Web-Statistiken wie Webalizer oder AWStats aktiviert sind, sollte dieses Verzeichnis ebenfalls hier aufgeführt werden.

ProxyPass / balancer://mycluster/ stickysession=BALANCEID
Wenn Cookies/Sessions serverübergreifend gelten sollen, muss hier die BALANCEID mit der Rewrite-Rule auf den einzelnen Frontend-Servern übereinstimmen.

ProxyPassReverse / http://cl2.domain.de/
Hier werden die einzelnen Frontend-Server aufgeführt. Auch wenn das System produktiv ist, kann hier jederzeit ein Server hinzu- oder weggenommen werden.

Apache-Dienst neu starten
/etc/init.d/apache2 force-reload

Hinweis für Plesk-Nutzer
Die Datei vhost.conf ist eventuell nicht vorhanden. Diese kann per Texteditor angelegt werden. Jedoch muss explizit nach jeder Änderung an der Datei der untenstehende Befehl ausgeführt werden, damit die Änderungen in der vhost.conf auch in die globale Apache-Conf übernommen wird.
/usr/local/psa/admin/sbin/websrvmng –reconfigure-vhost –vhost-name=[VHOST-NAME]

Weitere Konfigurationsmöglichkeiten
Dem BalanceMember können noch weitere Werte wie beispielsweise
BalancerMember http://:8080 min=10 max=50 loadfactor=2
BalancerMember http://:8080 min=5 max=25 loadfactor=1
mitgegeben werden.

Loadfactor: Dieser bestimmt die Gewichtung eines Balancer-Mitglieds. Wenn dieser nicht angegeben wird oder für alle Member gleich ist (zum Beispiel je 50), dann bedeutet dies, dass der Balancer jedem Frontend gleich viele User zuteilt. Wenn ich einem Mitglied eine geringere Zahl als einem anderen Frontend zuteile, wird dieser Server mit weniger User belastet.

Status: Status eines Balancer-Mitglieds
Cluster-Set lbmethod: Vom Balancer zur Anfragen-Verteilung verwendete Methode, entweder anhand der Anzahl (»byrequests« ) oder anhand des Datenaufkommens (»bytraffic« ) der Anfragen
Min: Minimale Anzahl ständig offener Backend-Verbindungen
Max: Maximale Anzahl ständig offener Backend-Verbindungen
Maxattempts: Maximale Anzahl zu tätigender Versuche bevor die Anfrage abgewiesen wird stickysession Name eines von den Backend-Server verwendeten, persistenten Cookies

Planungen zum Aufbau für einen Apache Load Balancer

In den Artikeln „MySQL Cluster oder Hot-Stand-By Lösung? Eine Frage der Hochverfügbarkeit“ und „MySQL Replikation (Master/Slave) einrichten„haben wir uns mit der Master/Slave-Funktionalität zur Replikation von MySQL beschäftigt. Der Grund für diese Tätigkeit war die Planung eines Web-Clusters, welches wir mit einfachen Mitteln erreichen wollen. Im heutigen Teil möchten wir uns mit dem Load-Balancer beschäftigen.

Anfänglich sind wir davon ausgegangen, dass wir einen MySQL-Master Server haben. Alle Clients bzw. alle Frontend-Server sollten via Webservice ihre Datenbankergebnisse abholen. Diese Architektur hätte zur Folge gehabt, dass der Datenbankserver geclustert werden muss. Planungen zur Folge gab es die Annahme, dass ein Frontend-Server genügen würde.
Schnell hat sich als eigentliche Schwachstelle der MySQL-Master-Server erwiesen, über den alle MySQL-Anfragen liefen. Da dieser Server auch regen Kontakt zum eigentlichen Datenbank-Master-PC in einem lokalen Netzwerk hält und auch noch als Fileserver „missbraucht“ wird, musste die Planung geändert werden. In der aktuellen Planung soll der Datenbank-Master PC nur noch die Datenbank für die Replikation bereitstellen. Alle Web-Frontend-Server haben eine eigene lokale MySQL-Datenbank, die als Slave für die Replikation dient. Jeder Web-Frontend-Server hat somit eine eigene Datenbank-Instanz, kann lokal die Anfragen behandeln und fällt im Fehlerfall als eine Komponente aus.

Folgende Gedanken liegen der aktuellen Planung zu Grunde

  • Web-Frontends zu clustern und auch noch einen geclusterten Datenbank-Server zu betreiben, bedeutet größere Wartung
  • Lokale MySQL-Instanzen bedeuten geringere Netzlast bei einer Anfrage bei keinen Mehrkosten, da MySQL lizenzfrei ist.
  • Die MySQL-Datenbank-Ausfallsicherheit ist noch größer, da mit jedem weiteren Web-Frontend die Anzahl der Spiegelung steigt.
  • Der MySQL-Master Server kann zu Wartungszwecken jederzeit abgeschaltet werden.

Ein Vorteil dieser Planung ist, dass jederzeit bei steigender Last der Webseite ein neuer Server in die „Farm“ hinzugefügt werden kann. Die Installation und Konfiguration des neuen „Farm-Mitglieds“ ist binnen weniger Stunden erledigt. Die Integration über den Apache Load Balancer bedeutet keinen nennenswerten Ausfall des Systems (apache restart notwendig).

Hot-Stand-By-Server als letzte Rettung
Auch der MySQL-Master Server könnte über die Konfiguration des Apache Load-Balancer als limitiertes Farmmitglied dienen. Er würde so, seiner eigenen Auslastung entsprechend, weniger Besucher als die vollwertigen Frontend-Server zugeteilt bekommen. Dieser Server kann jedoch auch als Hot-Standby-Server dienen. Wenn alle Frontend-Server ausfallen würden, könnte dieser als verbleibender Server die Anfragen beantworten. Dieser Fall sollte jedoch nie eintreten, da der Server mit der auf ihn zukommenden Last relativ schnell an seine Grenzen stoßen würde.

Zu bewerten ist noch, auf welchem Server der Load-Balancer installiert wird und ob mit einem Load-Balancer auszukommen ist. Aktuell ist der Load-Balancer auf einer separaten Maschine, die auch als Nameserver fungiert, installiert. Bei Ausfall dieser Maschine ist das Web nicht mehr erreichbar.

Die Konfiguration des Load-Balancers werden wir im nächsten Schritt behandeln.

Apache MaxClients mpm_prefork_module optimal einstellen

Der Apache-Webserver hat in seiner Config-Datei eine Möglichkeit, die maximale Benutzerzahl sowie die gleichzeitig laufenden Prozesse/Threads zu beschränken. Hintergrund dieser Serverlimitierung ist, dass der Server und nicht unter Last zusammenbricht, denn die Anzahl der möglichen Threads und gleichzeitige Userzugriffe hängen stark vom Speicher im Server und dessen CPU ab.

Wenn der Server schon bei wenigen Usern „streikt“, gibt ein Blick in das Apache error.log Auskunft. Ist darin ein Eintrag wie folgt ersichtlich, ist dies ein klarer Hinweis auf die Serverlimitierung innerhalb der apache2.conf-Datei:

[error] server reached MaxClients setting, consider raising the MaxClients setting

Es ist dann höchste Zeit, sich mit der Datei „/etc/apache/apache2.conf” (oder „/etc/apache2/apache2.conf”) auseinanderzusetzen. Wir finden im Abschnitt „mpm_prefork_module“ ähnliche Werte:

# prefork MPM
# StartServers: number of server processes to start
# MinSpareServers: minimum number of server processes which are kept spare
# MaxSpareServers: maximum number of server processes which are kept spare
# MaxClients: maximum number of server processes allowed to start
# MaxRequestsPerChild: maximum number of requests a server process serves
#war 1,1,5,10,0
<IfModule mpm_prefork_module>
StartServers       6
MinSpareServers    3
MaxSpareServers    3
MaxClients        100
    MaxRequestsPerChild   1000
</IfModule>

Was bedeuten die einzelnen Werte?

MaxClients: Dieser Parameter bestimmt die Anzahl der Apache Prozesse und somit die maximale Anzahl der Client Verbindungen, die vom Webserver zugelassen werden (Voraussetzung: prefork MPM). Wenn worker MPM verwendet wird, limitiert der Wert die Anzahl der Threads, die für die Clients zur Verfügung stehen.

MinSpareServers: Bei Verwendung von prefork MPM kann mit diesem Parameter definiert werden, wie viel unbeschäftigte (spare) Prozesse dem Apachen mindestens zur Verfügung stehen. Wenn eine neue Anfrage an den Webserver gestellt werden, nimmt der Apache einen dieser unbeschäftigten Prozesse. Dadurch wird die Anfrage schneller beantwortet, da dafür nicht ein neuer Prozess erstellt werden muss.

MaxSpareServers: Dieser Parameter legt fest, wie viel unbeschäftigte Prozesse maximal vorgehalten werden. Dieser Wert soll nicht zu hoch angesetzt werden, da jeder Prozess, auch wenn er „unbeschäftigt ist“, dann unnötig Arbeitsspeicher belegt.

ThreadsPerChild: Dieser  Parameter legt fest, wie viel Threads pro Prozess zugelassen werden sollen.
StartServers: Dieser Parameter legt fest, wie viel Prozesse beim Serverstart erstellt werden sollen.
MaxRequestsPerChild: Der Parameter MaxRequestsPerChild legt die maximale Anzahl von Anfragen fest, die ein Kindprozess während seiner Lebenszeit bearbeitet. Nachdem diese Grenze erreicht wurde, wird dieser Kindprozess terminiert. Ein MaxRequestsPerChild von 0 bedeutet, dass ein Kindprozess niemals endet.
Die Begrenzung von MaxRequestsPerChild (ungleich Null) hat folgende Vorteile:

  1. Sollte ein Prozess aufgrund eines Fehlers „Amok laufen“, begrenzt dieser Wert die Menge an Arbeitsspeicher, die der fehlerhafte Prozess belegen kann.
  2. Die Anzahl der Prozesse werden reduziert, wenn die Last des Servers nach einer hohen Auslastung wieder zurückgeht.

Apache-Default-Werte und empfohlene Werte
StartServers: 5
MinSpareServers: 5
MaxSpareServers: 10
MaxClients: 256
MaxRequestsPerChild: 0 oder 10000
MaxClients: Wenn dieser Wert größer als 256 gesetzt wird, muss zusätzlich der Parameter ServerLimit entsprechend erhöht werden.

Ein Plesk-Server (Parallels Virtuozzo-Server) bricht unter weniger User-Last ein
Interessant ist die Standard-Einstellung von virtualisierten Servern, beispielsweise von Webservern, die mit Parallels Plesk virtualisiert sind. Hier findet man folgende Werte:

StartServers       1
MinSpareServers    1
MaxSpareServers    5
MaxClients        10
MaxRequestsPerChild   0

Diese Einstellung bedeutet, dass der Server nur maximal 10 Clients zulässt. Dieser Werte können sich sehr schnell als „Flaschenhals“ erweisen und den Zugriff von Benutzern verhindern. Der Gedanke von Plesk ist klar: Auf dem Gesamtsystem sorgen diese Einstellungen dafür, dass die virtualisierten Server mit minimalen Zugriffen laufen und somit das Gesamtsystem nicht übermäßig belasten. Jedoch sind diese Werte, gerade bei aktueller Hardware, mehr als unpassend. Eine Erhöhung der Werte auf die Apache-Standard-Werte sollte ein erster Anhaltspunkt für die Performance-Optimierung sein. Nachdem man mit dieser Werten weitere Erfahrungen gesammelt hat, können diese Werte weiter optimiert werden.

Apache Restart nach Änderungen an der apache2.conf
Eine Änderung der Werte in der Apache-Config wirkt sich erst aus, nachdem der Apache Webserver neu gestartet wurde.

/etc/init.d/apache2 restart

SharePoint 2010: Website-Vorlage per SharePoint-Designer 2010 hinzufügen

Einer Website eine neue Site hinzufügen, ist in SharePoint keine große Sache. Klicken Sie hierfür auf „Websiteaktionen“, „Neue Seite“ und vergeben der neuen Seite einen Namen. Wenn Sie eine Seite mit einem bestimmten Aufbau und Webpartzonen anlegen möchten, empfehle ich dies aus der „Inhalts- und Strukturübersicht“ (Websiteeinstellungen,  Websiteinhalt und –struktur, Seiten) über „Seiten“, „Neu“ und „Seite anlegen“ zu erledigen. Hier können Sie auch das Seitenlayout anhand der von Microsoft bereits vorgegebenen Webseiten bestimmen.

Je nach Gestaltungsvorlage und Anforderung werden Sie jedoch mit diesen Vorlagen nicht auskommen. Wenn zum Beispiel eine Vorlage mit vier Spalten nebeneinander gewünscht wird, werden Sie diese Vorlage hier vergeblich suchen.

Weitere Vorlagen im SharePoint Designer 2010
Der Sharepoint-Designer 2010 bietet Ihnen neben weiteren Gestaltungsmöglichkeiten auch weitere Websitevorlagen mit Webpartzonen, die fast jeden Wunsch abdecken. Der SharePoint-Designer 2010 ist inzwischen kostenfrei über Microsoft zum Download erhältlich.
Laden Sie den SharePoint Designer herunter und installieren Sie ihn auf einem lokalen PC oder auf einem Member Ihrer SharePoint-Farm. Verbinden Sie sich auf Ihre Website mit dem Designer. Klicken Sie in der Navigation auf den Eintrag „Websiteseiten“. In der Ribbon-Leiste oben unter dem Karteikartenreiter „Seiten“ befindet sich der Ribbon „Webpartseite“. Klicken Sie das Ribbon an. Es öffnet sich eine Vorschau. Dort finden Sie weitere Websitevorlagen, unter anderem ein vierspaltiges Layout. Wählen Sie das gewünschte Layout aus und vergeben Sie der Seite einen Namen. Da die Vorlage uns nur als Vorlage dient, langt ein Titel wie „4-spalitig-layout.aspx“ oder ähnliches.

Wenn Sie nun in SharePoint (Browser) auf „Websiteaktionen“, „Inhalt und Struktur verwalten“ klicken, können Sie auf die Kategorie „Websiteseiten“ wechseln. Dort finden Sie nun die eben im SharePoint-Designer angelegte Seite.

Eine Seite kopieren oder verschieben in SharePoint
Die Vorlage, die wir eben erstellt haben, wurde unter „Websiteseiten“ abgelegt. Je nach Anforderung und Web möchten wir die Seite jedoch unter „Seiten“ abgelegt haben. Wir klicken auf die Kategorie „Websiteseiten“ und erhalten im Contentbereich unsere angelegte Seite. Wenn wir nun über den Titel der ASPX-Seite fahren, sehen wir rechts daneben einen Pfeil nach unten. Wir klicken darauf und ein Kontextmenü öffnet sich.

Mittels der Auswahl Kopieren können wir nun unsere Vorlage kopieren. Wir wechseln in die Kategorie „Seiten“, wählen mittels rechter Maustaste das Kontextmenü an, klicken auf „Einfügen“ und geben unserer eben kopierten Seite einen passenden Namen.

Nacharbeit einer Sharepoint-Seite
Natürlich haben wir unserer Vorlage eben weder Content, also Inhalt, noch irgendwelches Design oder Webparts verpasst. Dies hätten wir vor dem Kopieren im SharePoint-Designer erledigen können. In diesem Fall ging es nur um prinzipiellen Weg wie auch um die Möglichkeit, ohne WSP-Dateien und „Lösungen“ zu erstellen, eine einfache Seite mittels des SharePoint Designers zu erstellen und kopieren.

C# Images in DataGridView anzeigen

Der Wunsch, ein Image (Bild) in einem DataGridView in C# anzuzeigen, ist nicht vielfältig. Von kleinen Icons oder einer Statusanzeige, Thumbnails bis hin zur tabellarischen Anzeige von Bildern in einer Bildersammlung. Allen Anwendungsarten gemein ist, selten das gleiche Image in jeder Spalte angezeigt werden soll. Wer sich mit einem Image (und immer dem gleichen) in einer Spalte begnügt, kann das Image per Eigenschaft in Visual Studio hinzufügen, oder wie unten dynamisch anzeigen

//Ein Image einem DataGridView hinzufügen (jeder Zeile das gleiche Image)
Image myimage = new Bitmap("c:\mein_image.jpg");
DataGridViewImageColumn dgv_pic = new DataGridViewImageColumn(false);
dgv_pic.ImageLayout = DataGridViewImageCellLayout.Normal;
dgv_pic.Image = myimage;
dataGridView1.Columns.Add(dgv_pic);

Unterschiedliche Images aus einer Resource kann man wie im folgenden Beispiel anzeigen. Dieser Code hat den Nachteil, dass es nur Sinn macht, wenige verschiedene Images anzuzeigen. Hier wird eine Statuslampe (rot/grün) angezeigt:

//Lade die Images aus Resource
Image lampe_rot = Resource1.lampe_rot;
Image lampe_gruen = Resource1.lampe_gruen;

DataGridView dgv = new DataGridView();
DataGridViewImageColumn dgv_pic = new DataGridViewImageColumn(false);
DataGridViewColumn dgv_text = new DataGridViewTextBoxColumn();

//Füge die Colums hinzu
dgv.Columns.Add(dgv_pic);
dgv.Columns.Add(dgv_text);

//Hier warden manuell zwei Rows hinzugefügt
dgv.Rows.Add(2);

dgv[0, 0].Value = (Image)lampe_gruen;
dgv[0, 1].Value = (Image)lampe_rot;
dgv[1, 0].Value = "Server A";
dgv[1, 1].Value = "Server B";

Wenn ein DataGridView an eine Quelle gebunden ist (bindingSource), wird man einen anderen Weg einschlagen müssen. Dies gilt auch für den Fall, dass in jeder Zeile ein eigenes Bild angezeigt werden soll:

//dataGridView1 ist vorhanden und mit Daten gebunden
//Erstelle die Image-Spalte
DataGridViewImageColumn dgvic = new DataGridViewImageColumn(false);
dataGridView1.Columns.Add(dgvic);
               

//Gehe die Rows durch
for (int row = 0; row < dataGridView1.RowCount; row++)
{
//Lokales laden des Images
Image webImage = new Bitmap("c:\my_image.jpg");

//Image in DataGrid einfügen
      dataGridView1.Rows[row].Cells[0].Value = webImage;
//Höhe der Spalte an Image anpassen
      dataGridView1.Rows[row].Height = webImage.Height;
}

Wir gehen also jede Zeile durch und laden in diesem Beispiel jeder Zeile das Image „my_image.jpg“ hinzu. Wenn der Dateiname in der Zeile bekannt ist, kann dieser Aufruf natürlich (und sinnvollerweise) dynamisch erfolgen.

Image per http (webResponse) in DataGridView anzeigen
Oftmals haben wir in unserem dataGridView eine URL zur einem Image, das wir als Thumbnail (Vorschaubild) in unserer Tabelle anzeigen möchten. Dann können wir das Image nicht per Image webImage = new Bitmap() laden, sondern müssen es per WebRequest anfordern. Hierzu benötigen wir „using System.Net”.
Wir nutzen den gleichen Code wie im Beispiel oben, ersetzen jedoch „Image webImage“ („Lokales laden des Images“) mit folgendem Code:

//Laden des Images per http
//using System.Net;
string picUri = "http://domain.de/images/my_image.gif";
WebRequest requestPic = WebRequest.Create(picUri);
WebResponse responsePic = requestPic.GetResponse();

/Wandel den http-Stream zu Image
Image webImage = Image.FromStream(responsePic.GetResponseStream());

Zu beachten gilt, dass der Zugriff per WebRequest hinter einem Proxy (in Firmen sicherlich Standard) so nicht funktioniert. Der folgende Code zeigt einen Request über einen WebProxy:

WebRequest request = WebRequest.Create(sURL);
WebProxy proxy = new WebProxy(sWebProxy, Convert.ToInt32(sPort));
//            proxy.UseDefaultCredentials = true;
proxy.Credentials = new NetworkCredential(sUser, sPasswort, sDomain);
request.Proxy = proxy;
WebResponse response = request.GetResponse();

MySQL Replikation auf den Slave-Servern einrichten und starten

Im Artikel „MySQL Cluster oder Hot-Stand-By Lösung? Eine Frage der Hochverfügbarkeit“ haben wir die Vorbereitungen zu unserer MySQL-Replikation getroffen. Im Artikel „MySQL Replikation (Master/Slave) einrichten“ haben wir das der Replikation zugrundeliegende Logfile eingerichtet und ein Abbild der zu sichernden Datenbank erstellt. Dieses muss nun auf alle MySQL-Slave-Server kopiert werden. Wenn mehrere Slave-Server eingerichtet werden sollen, müssen die folgenden Schritte auf jedem Slave-Server durchgeführt werden.

Wir haben die Master-DB („mysql-snapshot.tar“) auf dem Slave-Server in den Ordner „/var/lib/mysql“ kopiert. Über eine Putty-Shell stoppen wir den MySQL-Server und entpacken die Master-Datenbank:

/etc/init.d/mysql stop
cd /var/lib/mysql
tar -xvf mysql-snapshot.tar

Die my.cnf auf dem Slave anpassen
Nun müssen wir die „my.cnf“ auf dem Slave anpassen. Wichtig ist auf jeden Fall, dem Slave eine eigene Server-ID zu geben. Jeder MySQL-Server in unserer Replikation benötigt eine eigene eindeutige ID. Wir öffnen die my.cnf mit einem Texteditor unserer Wahl:

nano /etc/mysql/my.cnf

server-id = 2
replicate-do-db = this_db [optional]

Das Logfile auf dem Master enthält alle Änderungen der Master-Datenbank. Wenn wir nur eine einzelne Datenbank replizieren möchten, können wir den Slave mittels „replicate-do-db“ anweisen, nur die Datenbank „this_db“ zu replizieren.
Ebenfalls optional ist die Angabe von Tabellen. Zu beachten gilt, wenn der Befehl „replicate-do-table“ einmal im Logfile verwendet wird, muss jede zu replizierende Tabelle aufgeführt werden (im untenstehenden Beispiel werden nur die drei benannten Tabellen repliziert).

#replicate-do-table beschränkt die Replikation auf einzelne Tabellen, falls nicht die gesamte Datenbank repliziert werden soll.
replicate-do-table = shopdb.customer
replicate-do-table = shopdb.order
replicate-do-table = shopdb.tracking

Den MySQL Slave wieder starten
/etc/init.d/mysql start

Dem MySQL-Slave mitteilen wer sein Master ist
Die Replikation geht von den einzelnen Slaves aus. Der Slave greift mit dem Replikationskonto (das wir im Artikel „MySQL Replikation (Master/Slave) einrichten“ angelegt haben) auf den Master zu.

Mittels MySQL-Konsole setzen wir folgenden Befehl ab:

CHANGE MASTER TO MASTER_HOST='<host>‘, MASTER_USER='<Replikations-User>‘, MASTER_PASSWORD='<passwd>‘, MASTER_LOG_FILE=’mysql-bin.<Hier die aktuelle Dateiangabe>, MASTER_LOG_POS=<Die Position vom Master>;

<host>: Name oder besser, die IP des Masters
<Replikations-User>: Name des Replikations-User auf dem Master (hier: „repl“)
<passwd>: Das Passwort des Replikations-User
MASTER_LOG_FILE: Beispielsweise „mysql-bin.000001“ (siehe notierte Angaben aus dem Start der Master-Replikation)
MASTER_LOG_POS: Beispielsweise „100“ (siehe notierte Angaben aus dem Start der Master-Replikation)

Wenn nach diesem Befehl keine Fehlermeldung erscheint, ist die Replikation schon fast perfekt.

Replikation anfahren
Mittels MySQL-Konsole starten wir Replikation:
START SLAVE;

Wenn alles ordnungsgemäß eingegeben wurde, führt der Slave ab sofort die Replikation durch. Mittels des MySQL-Konsolen-Befehls

show slave statusG

kann der Status der Replikation jederzeit abgerufen werden. Die Replikation stoppt bei einem Fehler.
Sobald ein Slave mit der Replikation begonnen hat, finden wir in seinem Datenverzeichnis unter „var/lib/mysql“ zwei Dateien namens master.info und relay-log.info. Der Slave verwendet diese beiden Dateien um zu vermerken, welcher Teil der Masterlogs bereits abgearbeitet wurde.

Über diese Schritte können so alle weiteren Slaves in die Replikation einbezogen werden. Nun benötigen wir noch das Wissen, wie wir mit Fehler der Replikation umgehen und wie wir diese überwachen. Über dieses Thema beschäftigen wir uns in einem weiteren Artikel.

MySQL Replikation (Master/Slave) einrichten

Im Artikel „MySQL Cluster oder Hot-Stand-By Lösung? Eine Frage der Hochverfügbarkeit“ haben wir die Vorüberlegung getroffen, wie wir unser System aufbauen möchten. Da wir einen Master-MySQL-Server und mehrere Slave-MySQL-Server haben und die Daten nicht jederzeit zu 100 Prozent synchron sein müssen, können wir die MySQL Replikation (Log-Shipping) nutzen. Ein weiterer Nachteil dieser Lösung ist, dass keine Daten auf dem Slave-Server verändert werden sollten/dürften, da sonst die Datenbestände auseinanderlaufen. Da in unserem Fall hauptsächlich Abfragen getätigt werden und SQL-Inserts nur zur Besucherstatistik dienen, kann das Zusammenführen dieser statistischen Daten über einen Cron-Job nachts erfolgen. Dieser sendet die Tagesdaten an den Master-Server, der diese Daten zentral aufbereitet. Die Replikation dieser Daten ist nicht gewünscht.

Weitere vorbereitende Überlegungen
Damit die MySQL-Replikation auch ordnungsgemäß funktioniert, sollten die MySQL-Versionen zwischen Master und Slave übereinstimmen. Kleine Versionsunterschiede können kein Problem sein, können aber auch zu zeitraubenden Fallen werden. In meinem Testsystem nutze ich unterschiedliche Versionen; es klappt einwandfrei. Allerdings muss dies nicht für alle Versionsdifferenzen gelten. Um die installierte MySQL-Version der einzelnen Server zu prüfen, können wir folgenden Befehl (Putty-Konsole) nutzen:

Prüfe die MySQL-Version
Putty: mysql -h localhost -V

Mit Netz und doppelten Boden
Wenn irgendwie möglich, sollte vor Start von jedem Member (Master und Slave) Images gemacht werden. Bei den folgenden Schritten kann die MySQL-Datenbank fehlerhaft werden, was bei softwaregestützten Webservern (Plesk, Confixx) zu einem Ausfall führen kann!

Einrichtung der MySQL-Replikation auf dem Master-Server
Als erstes müssen wir auf den MySQL-Master-Server einen Replikations-Benutzer anlegen. Weitere Informationen zu diesem Thema hält die MySQL-Seite vor. Wir öffnen eine Putty-Sitzung mit dem Master-Server und loggen uns in die MySQL-Konsole ein:

MASTER:
mysql -u root -p [RETURN]

MySQL-Replikations-Benutzer anlegen
Nehmen wir nun an, dass unsere Domäne mydomain.com heißt und wir ein Konto mit dem Benutzernamen „repl“ erstellen wollen. Dieses Konto nutzen die Slave-Server unter Angabe des Passworts „slavepass“ und stellen so die Verbindung Slave-Master her. Hier sehen wir also, dass der Zugriff (lesend) vom Slave oder den Slaves zum Master funktioniert.
Das Replikations-Konto erstellen wir mit folgender GRANT-Anweisung (Hinweis: Wir benötigen an dieser Stelle Root-Rechte):

mysql> GRANT REPLICATION SLAVE ON *.*
-> TO ‚repl’@’%.mydomain.com‘ IDENTIFIED BY ’slavepass‘;

My.conf auf dem Master anpassen
Nun öffnen wir mit einem Texteditor unserer Wahl die „etc/mysql/my.cnf“ und setzen die untenstehenden Werte (je nach Installation sind diese Werte vorhanden; wir entfernen lediglich die Auskommentierung „#“)

server-id = 1
log_bin = /var/log/mysql/mysql-bin.log

Was bewirkt diese Änderung: Wir teilen MySQL mit, dass dies der Server 1 ist. Alle an der Replikation beteiligen Server benötigen eine eigene (unterschiedliche ID). Per Eintrag „log_bin“ weisen wir MySQL an, dass alle Datenbankänderungen ab sofort geloggt werden sollen (an der Stelle: /var/log/mysql/mysql-bin.log)

Den MySQL-Server restarten
Damit die Änderungen aus der my.conf auch greifen, muss der MySQL-Dienst neu gestartet warden:

/etc/init.d/mysql restart

Nun müssen wir den aktuellen Stand der Datenbank sichern. Dieser Datenstand wird auf die Slaves verteilt. Alle folgenden Transaktionen auf den Slaves erfolgen dann über das Log-Shipping.

Vorbereitung für das Abbild der Master Datenbank erstellen
Über die MySQL-Konsole sperren wir alle Schreibzugriffe auf die Datenbank:

FLUSH TABLES WITH READ LOCK;

Position vom Master-Logfile notieren
Der folgende Schritt ist sehr wichtig. Wir notieren uns die aktuelle Position vom Master-Logfile. Diese Daten benötigen wir später beim Start der Slave-Synchronisation (Abschreiben oder Hardcopy)

SHOW MASTER STATUS;

Abbild vom aktuellen Stand der Master Datenbank erstellen
Wir öffnen via Putty eine weitere Sitzung. Die Putty-Sitzung mit dem „LOCK“ lassen wir bestehen und schließen sie nicht! Mit dem folgenden Code gehen wir in das MySQL-Verzeichnis und sichern die Datenbank:

cd /var/lib/mysql
tar -cvf /root/mysql-snapshot.tar

ACHTUNG: Zu beachten gilt hier, dass wir so ALLE Datenbanken des MySQL-Servers sichern (und später auch wiederherstellen). Je nach Server-Verwaltungssoftware (zum Beispiel Plesk) sind diese Daten auch in der MySQL-Datenbank gespeichert. Wenn wir diese Daten auf dem Slave-Server einspielen, überschreiben wir die MySQL-Plesk-Daten (oder andere MySQL-Einträge) auf dem Slave-Server. Ich gebe an dieser Stelle einmal zu, dass ich so schon einmal einen Plesk-Webserver „zerschossen“ habe).

Wollen wir also nur eine Datenbank replizieren („this_db“), nutzen wir folgenden Befehl:
shell> tar -cvf /root/mysql-snapshot.tar ./this_db

Die Datenbank auf dem Master wieder freigeben
Über unsere bestehende MySQL-Konsole setzen wir folgenden Befehl ab:

UNLOCK TABLES;

Nun haben wir also den Master-Server für die MySQL-Logfile-Replikation vorbereitet und ein Abbild der Master-Datenbank erstellt. Im Artikel „MySQL Replikation auf den Slave-Servern einrichten und starten“ beschäftigen wir uns mit den Slave-Servern.