Title: Dynamisch konfiguriertes virtuelles Massen-Hosting
Virtuelle Hosts

Dieses Dokument beschreibt, wie eine beliebige Anzahl virtueller Hosts mit dem Apache effizient bedient werden kann.

Motivation

Die hier beschriebenen Techniken sind interessant, wenn Ihre httpd.conf-Datei viele <VirtualHost>-Abschnitte enthält, die sich im Wesentlichen gleichen. Zum Beispiel:

NameVirtualHost 111.22.33.44
<VirtualHost 111.22.33.44>
ServerName www.customer-1.com
DocumentRoot /www/hosts/www.customer-1.com/docs
ScriptAlias /cgi-bin/ /www/hosts/www.customer-1.com/cgi-bin
</VirtualHost>
<VirtualHost 111.22.33.44>
ServerName www.customer-2.com
DocumentRoot /www/hosts/www.customer-2.com/docs
ScriptAlias /cgi-bin/ /www/hosts/www.customer-2.com/cgi-bin
</VirtualHost>
# blah blah blah
<VirtualHost 111.22.33.44>
ServerName www.customer-N.com
DocumentRoot /www/hosts/www.customer-N.com/docs
ScriptAlias /cgi-bin/ /www/hosts/www.customer-N.com/cgi-bin
</VirtualHost>

Der Grundgedanke ist es, die gesamte statische <VirtualHost>-Konfiguration durch einen Mechanismus zu ersetzen, der sie dynamisch erzeugen kann. Das hat eine Reihe von Vorteilen:

  1. Die Konfigurationsdatei ist kleiner, daher startet der Apache schneller und er benötigt weniger Speicher.
  2. Zum Hinzufügen neuer virtueller Hosts müssen nur die entsprechenden Verzeichnisse im Dateisystem eingerichtet und die DNS-Einträge vorgenommen werden. Der Apache muss nicht neu konfiguriert oder gestartet werden.

Der größte Nachteil ist, dass keine getrennten Protokolldateien für die einzelnen virtuellen Hosts angelegt werden können. Werden aber sehr viele virtuelle Hosts eingerichtet, dann ist das sowieso bedenklich, denn dafür werden sehr viele Dateideskriptoren benötigt. Es ist sinnvoller das Protokoll in eine Pipe oder einen FIFO-Stapel zu schreiben und mit einem Prozess am anderen Ende die Protokolldaten zu zerlegen und zu verteilen (sie können auch Statistiken zusammenstellen usw.).

Überblick

Ein virtueller Host wird mit zwei Informationen definiert, nämlich mit der IP-Adresse und den Inhalten des Host:-Headers der HTTP-Anfrage. Die Technik des dynamischen virtuellen Massen-Hosting basiert auf dem automatischen Einfügen dieser Informationen in den Pfadnamen der Datei, mit der die Anfrage beantwortet wird. Dies geschieht am einfachsten mit dem Modul mod_vhost_alias (bei Apache-Versionen vor der Version 1.3.6 muss das Modul mod_rewrite benutzt werden). Beide Module sind standardmäßig deaktiviert und daher muss eines von beiden beim Konfigurieren und Aufbauen des Apache eingebunden werden, wenn diese Technik benutzt werden soll.

Einige Dinge müssen "getürkt" werden, damit der dynamische virtuelle Host wie ein normaler Host aussieht. Am wichtigsten ist der Servername, mit dem der Apache selbstreferenzierende URLs usw. erzeugt. Er wird mit der ServerName-Direktive festgelegt und steht für CGI als Umgebungsvariable SERVER_NAME zur Verfügung. Der zur Ausführungszeit benutzte Wert wird mit den Einstellungen der Direktive UseCanonicalName gesteuert. Bei der Anweisung UseCanonicalName Off kommt der Servername aus dem Inhalt des Host:-Headers der Anfrage. Bei der Anweisung UseCanonicalName DNS ist er das Ergebnis einer reversiven DNS-Suche in den IP-Adressen des virtuellen Hosts. Die erste Variante wird für namensbasiertes dynamisches virtuelles Hosting und die zweite für IP-basiertes Hosting benutzt. Kann der Apache den Servernamen nicht ermitteln, weil es keinen Host:-Header gibt oder die DNS-Suche kein Ergebnis liefert, wird der Wert mit ServerName gebildet.

Auch die DocumentRoot muss vorgetäuscht werden. Sie steht über die Umgebungsvariable DOCUMENT_ROOT zur Verfügung. In einer normalen Konfiguration wird ihr Wert vom Kernmodul bei der Zuweisung von URIs zu Dateinamen benutzt, wird der Server aber für dynamisches virtuelles Hosting konfiguriert, übernimmt ein anderes Modul diese Aufgabe (entweder mod_vhost_alias oder mod_rewrite), das die Zuordnung auf eine andere Weise durchführt. Keines dieser Module übernimmt das Setzen der Variablen DOCUMENT_ROOT, so dass sie bei der Verwendung durch CGI-Skripte oder SSI-Dokumente einen irreführenden Wert enthält.

Einfache dynamische virtuelle Hosts

Der folgende Auszug aus der Datei httpd.conf implementiert das oben beschriebene virtuelle Host-Arrangement mit mod_vhost_alias auf eine generische Art.

# Den Servernamen aus dem Host:-Header nehmen
UseCanonicalName Off

# Dieses Protokollformat kann pro virtuellem Host anhand des ersten Feldes # aufgeteilt werden
LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon
CustomLog logs/access_log vcommon

# Den Servernamen in die Dateinamen einbinden
VirtualDocumentRoot /www/hosts/%0/docs
VirtualScriptAlias /www/hosts/%0/cgi-bin

Diese Konfiguration kann durch Veränderung von UseCanonicalName Off in UseCanonicalName DNS für IP-basiertes virtuelles Hosting umgewandelt werde. Der in den Dateinamen eingefügte Servername wird von der IP-Adresse des virtuellen Host abgeleitet.

Ein System mit virtuellen Homepages

Dieses Beispiel ist eine Anpassung des letzten Beispiels für Homepage-Server eines Providers. Mit einer etwas komplizierteren Konfiguration können Teile des Servernamens als Zeichenfolge für die Verwendung im Dateinamen benutzt werden, z.B. befinden sich die Dokumente für www.user.isp.com im Verzeichnis /home/user/. Es wird ein einziges cgi-bin-Verzeichnis und nicht pro virtuellem Host ein Verzeichnis benutzt.

# Einleitung wie oben

# Einen Teil des Servernamens in Dateinamen verwenden
VirtualDocumentRoot /www/hosts/%2/docs

# Ein einziges cgi-bin-Verzeichnis
ScriptAlias /cgi-bin/ /www/std-cgi/

In der Beschreibung des Moduls mod_vhost_alias finden Sie kompliziertere Beispiele für VirtualDocumentRoot-Anweisungen.

Mehrere virtuelle Hosting-Systeme auf dem gleichen Server

Mit etwas komplizierteren Konfigurationen können Sie mit den normalen <VirtualHost>-Direktiven den Bereich der verschiedenen virtuellen Hosting-Konfigurationen kontrollieren. Beispielsweise kann wie folgt eine IP-Adresse für Homepage-Kunden und eine andere für kommerzielle Kunden eingerichtet werden. Das lässt sich selbstverständlich mit konventionellen <VirtualHost>-Konfigurationsabschnitten kombinieren.

UseCanonicalName Off

LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon

<Directory /www/commercial>
Options FollowSymLinks
AllowOverride All
</Directory>

<Directory /www/homepages>
Options FollowSymLinks
AllowOverride None
</Directory>

<VirtualHost 111.22.33.44>
ServerName www.commercial.isp.com

CustomLog logs/access_log.commercial vcommon

VirtualDocumentRoot /www/commercial/%0/docs
VirtualScriptAlias /www/commercial/%0/cgi-bin
</VirtualHost>

<VirtualHost 111.22.33.45>
ServerName www.homepages.isp.com

CustomLog logs/access_log.homepages vcommon

VirtualDocumentRoot /www/homepages/%0/docs
ScriptAlias /cgi-bin/ /www/std-cgi/
</VirtualHost>
Effizienteres IP-basiertes virtuelles Hosting

Nach dem ersten Beispiel wurde angemerkt, dass es einfach für IP-basiertes virtuelles Hosting umgewandelt werden kann. Leider ist diese Konfiguration nicht sehr effizient, weil eine DNS-Suche pro Anfrage erforderlich ist. Wird das Dateisystem entsprechend der IP-Adressen aufgebaut und sich nicht an den Namen orientiert und die Protokollierung in ähnlicher Weise geändert wird, lässt sich das vermeiden. Der Apache muss dann den Dateinamen in der Regel nicht ermitteln und daher unterbleibt die DNS-Suche.

# Den Servernamen mit einer reversiven DNS-Suche ermitteln
UseCanonicalName DNS

# Die IP-Adresse in die Protokolle übernehmen, damit sie zerlegt werden können
LogFormat "%A %h %l %u %t \"%r\" %s %b" vcommon
CustomLog logs/access_log vcommon

# Die IP-Adresse in den Dateinamen einschließen
VirtualDocumentRootIP /www/hosts/%0/docs
VirtualScriptAliasIP /www/hosts/%0/cgi-bin
Ältere Versionen des Apache benutzen

Die oben aufgeführten Beispiele basieren auf mod_vhost_alias, ein Modul, das es seit der Version 1.3.6 gibt. Haben Sie eine Version ohne mod_vhost_alias, dann können Sie diese Technik wie unten gezeigt mit mod_rewrite implementieren, allerdings nur für auf Host:-Header basierende virtuelle Hosts.

Außerdem müssen noch einige Dinge für die Protokollierung beachtet werden. Die Version 1.3.6 war die erste Version mit der Protokollformat-Direktive %V. In den Versionen 1.3.0 - 1.3.3 hat die Option %v das Gleiche wie %V geleistet. In Version 1.3.4 gibt es keine Entsprechung. In allen diesen Versionen des Apache kann die UseCanonicalName-Direktive in .htaccess stehen, was bedeutet, das Anwender eine falsche Protokollierung verursachen können. Deshalb sollte die %{Host}i-Direktive benutzt werden, mit der der Host:-Header direkt protokolliert wird. Hierbei kann :port am Ende stehen, was bei %V nicht der Fall ist.

Einfache dynamische virtuelle Hosts mit <code>mod_rewrite</code>

Der folgende Auszug aus der Datei httpd.conf bewirkt das Gleiche wie das erste Beispiel. Die erste Hälfte ist vergleichbar mit dem entsprechenden Teil oben, für die Abwärtskompatibilität und für die korrekte Funktion von mod_rewrite wurden aber einige Änderungen vorgenommen. In der zweiten Hälfte wird mod_rewrite für die eigentliche Arbeit konfiguriert.

Es gibt einige besonders schwierige Kleinigkeiten: Standardmäßig wird mod_rewrite vor den übrigen URI-Umwandlungsmodulen ausgeführt (mod_alias usw.). Werden sie benutzt, muss mod_rewrite entsprechend konfiguriert werden. Außerdem muss etwas getan werden, um ein Äquivalent für ScriptAlias zu schaffen.

# Den Servernamen aus dem Host:-Header nehmen
UseCanonicalName Off

# Zerlegbare Protokolle
LogFormat "%{Host}i %h %l %u %t \"%r\" %s %b" vcommon
CustomLog logs/access_log vcommon

<Directory /www/hosts>
# ExecCGI wird benötigt, weil die CGI-Ausführung
# nicht wie ScriptAlias veranlasst werden kann.
Options FollowSymLinks ExecCGI
</Directory>

# Jetzt zum schwierigeren Teil:

RewriteEngine On

# Ein vom Host-Header abgeleiteter ServerName kann jede Form haben
RewriteMap lowercase int:tolower

## Zuerst das normale Dokument:
# Alias /icons/ zulassen - für andere Aliase wiederholen
RewriteCond %{REQUEST_URI} !^/icons/
# CGIs zulassen
RewriteCond %{REQUEST_URI} !^/cgi-bin/
# Der Kunstgriff
RewriteRule ^/(.*)$ /www/hosts/${lowercase:%{SERVER_NAME}}/docs/$1

## und jetzt zu CGIs - ein MIME-Typ muss festgelegt werden
RewriteCond %{REQUEST_URI} ^/cgi-bin/
RewriteRule ^/(.*)$ /www/hosts/${lowercase:%{SERVER_NAME}}/cgi-bin/$1 [T=application/x-httpd-cgi]

# Das war's!
Ein Homepage-System mit <code>mod_rewrite</code>

Leistet das Gleiche wie das zweite Beispiel.

RewriteEngine on

RewriteMap lowercase int:tolower

# CGIs zulassen
RewriteCond %{REQUEST_URI} !^/cgi-bin/

# Den Hostnamen überprüfen, damit RewriteRule funktioniert
RewriteCond ${lowercase:%{SERVER_NAME}} ^www\.[a-z-]+\.isp\.com$

# Den virtuellen Hostnamen bis zum Beginn des URI verknüpfen
# Das [C] bewirkt, dass die nächste Manipulation für das Ergebnis # dieser Manipulation durchgeführt wird.
RewriteRule ^(.+) ${lowercase:%{SERVER_NAME}}$1 [C]

# Den richtigen Namen erzeugen
RewriteRule ^www\.([a-z-]+)\.isp\.com/(.*) /home/$1/$2

# Das globale CGI-Verzeichnis definieren
ScriptAlias /cgi-bin/ /www/std-cgi/
Eine separate virtuelle Host-Konfigurationsdatei verwenden

Bei diesem Arrangement werden erweiterte mod_rewrite-Eigenschaften für die Umwandlung vom virtuellen Host zur DocumentRoot mit einer separaten Konfigurationsdatei benötigt. Das bietet mehr Flexibilität, verlangt aber eine kompliziertere Konfiguration.

Die Vhost.map-Datei sieht folgendermaßen aus:

www.customer-1.com /www/customers/1
www.customer-2.com /www/customers/2
# ...
www.customer-N.com /www/customers/N

In der httpd.conf-Datei steht:

RewriteEngine on

RewriteMap lowercase int:tolower

# Die Map-Datei definieren
RewriteMap vhost txt:/www/conf/vhost.map

# Behandlung der Aliase wie oben
RewriteCond %{REQUEST_URI} !^/icons/
RewriteCond %{REQUEST_URI} !^/cgi-bin/
RewriteCond ${lowercase:%{SERVER_NAME}} ^(.+)$
# Neuzuordnung auf Dateibasis
RewriteCond ${vhost:%1} ^(/.*)$
RewriteRule ^/(.*)$ %1/docs/$1

RewriteCond %{REQUEST_URI} ^/cgi-bin/
RewriteCond ${lowercase:%{SERVER_NAME}} ^(.+)$
RewriteCond ${vhost:%1} ^(/.*)$
RewriteRule ^/(.*)$ %1/cgi-bin/$1
Title: Obergrenzen für Dateideskriptoren
Virtuelle Hosts

Bei einer großen Anzahl virtueller Hosts können dem Apache die Dateideskriptoren (oder Datei-Handler) ausgehen, wenn jeder virtuelle Host andere Protokolldateien benutzt. Insgesamt benutzt der Apache für jedes einzelne Fehlerprotokoll einen Dateideskriptor, einen weiteren für jede weitere Protokolldatei-Direktive sowie 10 - 20 Dateideskriptoren für die interne Verwendung. Unix-Betriebssysteme limitieren die Anzahl der Dateideskriptoren, die von einem Prozess benutzt werden dürfen. Normalerweise liegt die Grenze bei 64 und kann gewöhnlich auf eine Obergrenze gesetzt werden.

Der Apache versucht zwar das Limit bei Bedarf hochzusetzen, das funktioniert aber nicht, wenn:

  1. das System den Systemaufruf setrlimit() nicht kennt.
  2. der setrlimit(RLIMIT_NOFILE)-Call bei einem System nicht funktioniert (siehe Solaris 2.3).
  3. die Anzahl der erforderlichen Dateideskriptoren die Obergrenze überschreitet.
  4. das System andere Obergrenzen für die Anzahl der Dateideskriptoren setzt, wie zum Beispiel eine Obergrenze für stdio-Streams mit 256 Dateideskriptoren (Solaris 2).

Wenn es zu Problemen kommt, können Sie:

  • die Anzahl der Protokolldateien reduzieren. Geben Sie in VirtualHost-Abschnitten keine Protokolldateien an, sondern schreiben Sie nur in die Hauptprotokolldateien. (Wie Sie dies tun, lesen Sie im Abschnitt Protokolldateien zerlegen.)
  • die Obergrenze für die Dateideskriptoren vorm Apache-Start mit einem Skript hochsetzen: #!/bin/sh
    ulimit -S -n 100
    exec httpd

Im Abschnitt Deskriptoren und der Apache finden Sie weitere Informationen zu Problemen mit Dateideskriptoren und wie sie zu lösen sind.

Protokolldateien zerlegen

Wenn Sie mehrere virtuelle Hosts in einer Datei protokollieren möchten, dann ist es sinnvoll, diese Datei anschließend zu zerlegen, damit eine statistische Analyse der einzelnen virtuellen Hosts möglich ist. Wie das geschieht, wird im folgenden beschrieben.

Als erstes muss den Protokolleinträgen ein Hinweis auf den virtuellen Host hinzugefügt werden. Das kann mit der Direktive LogFormat und der %v-Variablen geschehen:

LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost
CustomLog logs/multiple_vhost_log vhost

Jetzt wird eine Protokolldatei im allgemeinen Protokollformat aber mit Angabe des tatsächlichen virtuellen Host (unabhängig davon, was in der ServerName-Direktive stehen kann) am Ende der Zeile erstellt. (Mehr zur Anpassung der Protokolldateien finden Sie in der Beschreibung der Direktive Custom Log Formats.)

Soll die Protokolldatei in einzelne Bestandteile zerlegt werden (eine Datei für jeden virtuellen Host), dann benutzen Sie dafür das Programm split-logfile. Sie finden es im Apache-Verzeichnis support.

Führen Sie das Programm wie folgt aus:

split-logfile < /logs/multiple_vhost_log

Das Programm erzeugt für jeden virtuellen Host, der in der Protokolldatei auftaucht, eine Datei, wenn der Name der Vhost-Protokolldatei übergeben wird. Die Dateien erhalten die Bezeichnung Hostname.log.

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to