Apache HTTP Server Version 2.0

Architektur


[ Seminar Linux und Apache ] ... [ Inhaltsübersicht ] ... [ Funktionsweise ]


Übersicht: Architektur

Nach oben

Apache ist ein modularer Server. Nur die grundlegende Basis-Funktionalität ist direkt im Server-Kern enthalten. Zusätzliche Features können durch Module Apache hinzugefügt werden.
Durch Verfügbarkeit des Apache-Quellcodes und eines APIs ist es jedermann möglich die Fähigkeiten des Servers zu erweitern und seinen Bedürfnissen anzupassen.

Architektur bis Version 1.3

Bis zu Version 1.3 ist die dem Webserver zu Grunde liegende Architektur weitgehend gleich geblieben.

Laufzeitverhalten:
Bis zur Apache Version 1.2.x unterstützte der Webserver nur die verschiedenen Unix-Betriebssysteme. Unter Unix ist es im Gegensatz zu Windows möglich Prozesse zu kopieren.
(man 2 fork:
fork creates a child process that differs from the parent process only in its PID and PPID, and in the fact that resource utilizations are set to 0. File locks and pending signals are not inherited.)

Apache arbeitete als sogenannter Preforking-Server: der gestartete Prozess legt zu Beginn eine in der Konfigurationsdatei angegebene Anzahl von Kopien seiner selbst an, die auf eingehende Anragen warten. Falls mehr http-Anfragen eingehen als die vorhandene Prozessanzahl beantworten kann, werden rechtzeitig weitere Kopien des Ursprungsprozesses angelegt.

Apache wurde in der Version 1.3 auf die Windows-Plattform portiert.
Unter Windows ist das Kopieren laufender Prozesse jedoch nicht möglich. Man kann lediglich komplett neue Prozesse erzeugen, was aber bedeuten würde, jedes mal die gesamte Startphase von Apache inklusive der Verarbeitung der Konfigurationsdirektiven zu durlaufen.
Da dies zu ineffizient wäre, wurde für dieses Betriebssystem ein anderes Laufzeitverhalten implementiert.

Unter Windows gibt es zwei Apache-Prozesse. Einer ist für die Beantwortung der HTTP-Anfragen zuständig. Der andere überwacht diesen Prozess, um ihn neu zu starten, falls er abstürzen sollte. Innerhalb des Arbeitsprozesses, der die Anfragen beantwortet, laufen mehrere Threads. Je nach Beanspruchung des Servers werden Threads angelegt oder wieder aus dem Speicher entfernt. So wie die Prozesse bei der Unix-Version Prozesse geforkt und gekillt werden.

Um diese beiden Laufzeitverhalten (Threads/Prozesse) zu realisieren mussten im Apache-Quelltext die Teile, die für das Erzeugen der Kind-Prozesse verantwortlich waren, umgeschrieben werden.
Im Code wurde durch "#ifdef"-Anweisungen zwischen den beiden Versionen unterschieden.
Dadurch wurde der Code schwierig zu pflegen und es würde noch unübersichtlicher, wenn man weitere Laufzeitverhalten implementieren wollte..

Nach oben

die neue Architektur

Ziel war es Apache leichter portierbar zu machen.
Dieses Ziel wird dadurch erreicht, dass sämtlicher plattformspezifischer Code sauber getrennt vom restlichen Apache-Code in den Sourcen des APR und der MPMs zu finden ist. Durch diese Kapselung ist es für die Apache-Entwickler leichter geworden, plattformspezifische Änderungen und Optimierungen vorzunehmen.

Nach oben

APR (Apache Portable Runtime)

Apache benutzt nicht mehr die POSIX-Schnittstellen. Fehlerhaft und leistungsschwach implementierte POSIX-Bibliotheken hatten auf nicht-Unix-Betriebsystemen zur Folge, dass der Server dort nicht so gut lief.
Bei APR handelt es sich um eine Bibliothek, die eine Schicht zwischen den jeweiligen Betriebssytemen und Apache 2 bildet.
APR bietet durch seine API grundlegende Funktionen eines Betriebssystems an.
Dazu gehören File-I/O, Netzwerk-I/O, Speicherverwaltung, Thread- und Prozessverwaltung u.s.w.
Die APR benutzt native Aufrufe wann immer es möglich ist.
Es wird versucht die APR-Methoden den POSIX-Methoden äußerlich nachzuempfinden, damit die Programmierer schon geschriebenen Code leichter auf APR zu portieren können.
Der Apache-Kern greift jetzt also nicht mehr direkt auf das Betriebsystem zu, sondern nutzt die Funktionen, die das APR mit seiner API anbietet.

Für die Version 1.0 des APR ist das primäre Ziel, alle Funktionen, die zur Realisierung von Apache 2.0 benötigt werden, zur Verfügung zu stellen. Es ist allerdings geplant, danach das APR auch unabhängig von Apache als Basis für plattformunabhängiges Programmieren weiterzuentwickeln und interessierten Programmierern zur Verfügung zu stellen.

Nach oben

MPMs (Multi Processing Modules)

In diese spezielle Art von Modulen wurde der Code ausgelagert der, in der 1.3-Version die Prozesse und oder Threads verwaltete. Die Aufgabe eines MPM ist es also, eingehende http-Anfragen auf einfache ‚Ausführungseinheiten' abzubilden, die diese verarbeiten. Ob es sich dabei um Prozesse oder Threads handelt ist von dem jeweiligen MPM abhängig.
Die Modularisierung dieses Teils von Apache bringt neben einem klarer strukturierten Quellcode einige weitere Vorteile mit sich. Die Apache-Entwickler haben es explizit erlaubt, in den Multi-Processing-Modulen betriebssystemspezifischen Code zu verwenden. Es lässt sich demnach ein MPM schreiben, das nur auf einem Betriebssystem übersetzt werden kann und auf dieses optimiert ist.
Auf Nicht-Unix-Betriebssystemen führt das zu einer Geschwindigkeitssteigerung im Vergleich zu Apache 1.3.
Apache-Entwickler Bill Stoddard erreichte unter Windows einen Perfomancegewinn von 50% bei statischen Webseiten. http://wstoddard.com/ApacheCon2000/


Nach oben

MPMs unter Unix

Für Unix gibt es mehrere MPMs. Jedes davon implementiert eine andere Strategie, mit der der Webserver die anfallenden HTTP-Anfragen abarbeiten soll. Ein Webmaster hat somit die Möglichkeit, die für seine jeweilige Anwendung geeignetste Variante auszusuchen, indem er das entsprechende MPM in das Apache-Binary einkompiliert.

Threads sind unter den UNIXen weniger recourcen-intensiv als Prozesse. Das bedeutet, im Vergleich zu 1.3, wo nur Prozesse benutzt wurden, dass die Skalierbarkeit bei Verwendung von Threads zunimmt.
Andererseit ist die Sicherheit bei mehreren Prozessen größer, da bei fehlerhaften Modulen, die einen Prozeß zum abstürzen bringen, nur wenige Verbindungen verloren gehen.


Nach oben

Prefork

Dieses MPM implementiert, das gleiche Laufzeitverhalten, wie schon bei 1.3 unter Unix.
Ein Elternprozes ist dafür zuständig, so viele Kindprozesse zu erzeugen, dass immer ein Vorrat vorhanden ist, der neu eingehende http-Anfragen entgegennehmen kann.
Die Konfigurationsoptionen MinSpareServers und MaxSpareServers legen fest, wie viele Kindprozesse mindestens und maximal auf Vorrat bereitgehalten werden sollen. Sinkt die Anzahl der freien Prozesse unter die Anzahl MinSpareServers, werden neue erzeugt, steigt sie über die Anzahl MaxSpareServers werden Prozesse aus dem Speicher entfernt.
Da jeder Prozess nur genau eine Anfrage gleichzeitig bearbeitet, kann durch einen Fehler in einen solchen Prozesses auch nur eine Verbindung mit dem Server verloren gehen.

Vorteil bei dynamisch generierten Seiten.


Nach oben

threaded

Dieses MPM arbeitet ähnlich dem oben genannten. Der entscheidende Unterschied ist der, dass jetzt in jedem Prozess mehrere Threads laufen können. Wie viele dies sind, kann die Konfigurationsoption ThreadsPerChild festlegen. Bei Verwendung dieses MPM achtet der httpd darauf, wie viele unbeschäftigte Threads noch vorhanden sind. Die Direktiven MinSpareThreads und MaxSpareThreads geben an, wie viele Threads unbeschäftigt sein dürfen, bevor neue Prozesse erstellt oder aus dem Speicher entfernt werden. Dieses MPM arbeitet also sowohl mit mehreren Prozessen als auch mit Threads - das gab es bei Apache 1.3 nicht.
Nach oben

Dexter

Dieses MPM arbeitet ebenfalls mit einer Kombination aus Prozessen und Threads, die innerhalb der Prozesse ablaufen. Im Unterschied zum MPM "threaded" steht hier jedoch die Anzahl der Prozesse fest; lediglich die der Threads innerhalb dieser Prozesse schwankt je nach Serverlast. Die Anzahl der anfangs zu startenden Prozesse definiert die Konfigurationsanweisung NumServers, die der darin zu Beginn enthaltenen Threads StartThreads. Wie sich die Anzahl der Threads bei unterschiedlicher Last anpassen soll, legen wieder MinSpareThreads und MaxSpareThreads fest.
Nach oben

Perchild

Perchild basiert auf dem Dexter-MPM, bietet aber wichtige darüber hinausgehende Funktionen, die insbesondere für Web-Hoster interessant sein dürften. Wie bei Dexter hat man es hier mit einer festen Anzahl von Prozessen zu tun, in denen mehrere Threads ablaufen. Zusätzlich besteht die Möglichkeit, die Prozesse unter unterschiedlichen User- und Gruppen-Kennungen laufen zu lassen, sodass man verschiedene virtuelle Hosts mit unterschiedlichen Rechten laufen lassen kann. Dazu dient die Direktive ChildPerUserID, die besagt, wie viele Prozesse unter einer bestimmten Benutzerkennung laufen sollen. Mit der Anweisung AssignUserID innerhalb des <VirtualHost>-Kontextes wird den entsprechenden Prozessen die Benutzerkennung zugewiesen.
Nach oben

Module für ander Betriebsysteme

Es exitieren MPMs für Windows, OS2 und BeOS.
Unter Windows wird das gleich Laufzeitverhalten wie bei 1.3 implementiert.

Nach oben

[ Seminar Linux und Apache ] ... [ Inhaltsübersicht ] ... [ Funktionsweise ]