Die erste Version des Apache HTTP Servers erschien 1995. Noch heute, mehr als 20 Jahre später, regiert die Software als Häuptling unter den Web­ser­vern – doch nicht ohne Kon­kur­renz. Vor allem der russische Webserver NGINX (Aus­spra­che wie „Engine-X“), ebenfalls ein Open-Source-Projekt, macht Markt­an­tei­le gut – und das in rasender Ge­schwin­dig­keit. Besonders schmerz­lich für die Apache Foun­da­ti­on: Die meisten Websites, die im Alexa-Ranking gut ab­schnei­den, werden heute schon über NGINX aus­ge­lie­fert. Dies zeigt eine re­gel­mä­ßig ak­tua­li­sier­te Statistik von W3Techs. Nicht nur russische In­ter­net­grö­ßen wie die Such­ma­schi­nen Rambler und Yandex, der E-Mail-Service Mail.RU oder das soziale Netzwerk VK setzen auf den leicht­ge­wich­ti­gen Webserver; auch in­ter­na­tio­na­le Anbieter wie Dropbox, Netflix, WordPress und FastMail.com nutzen NGINX, um die Per­for­mance ihrer Services zu ver­bes­sern. Gehört der Apache HTTP Server damit bald zum alten Eisen?

Hinweis

Der Apache HTTP Server ist ein Software-Projekt, das unter der Schirm­herr­schaft der Apache Foun­da­ti­on vor­an­ge­trie­ben wird. Im öko­no­mi­schen Sprach­ge­brauch der In­ter­net­ge­mein­de wird der Name des Web­ser­vers in der Regel auf „Apache“ verkürzt. Auch wir folgen dieser Kon­ven­ti­on: Ist im Folgenden von „Apache“ die Rede, ist stets die Software und nicht der Her­stel­ler gemeint.    

Die Her­aus­for­de­rung des Web 2.0

Owen Garrett, Head of Products bei Nginx, Inc., be­zeich­net den Apache-Webserver in einem Blog­ar­ti­kel vom 9. Oktober 2015 als „Backbone“ („Wir­bel­säu­le“) des Web 1.0 und hebt damit dessen Bedeutung für die Ent­wick­lung des Internets um die Jahr­tau­send­wen­de hervor. Der große Erfolg des Web­ser­vers sei vor allem auf die einfache Ar­chi­tek­tur der Software zu­rück­zu­füh­ren. Diese jedoch beruhe auf Design-Ent­schei­dun­gen, die sich an einem World Wide Web ori­en­tier­ten, das mit dem von heute nicht zu ver­glei­chen ist. Vor 20 Jahren waren Webseiten we­sent­lich einfacher aufgebaut, Band­brei­te war be­schränkt und teuer, CPU-Re­chen­zeit hingegen ver­gleichs­wei­se günstig.

Heute haben wir es mit einem World Wide Web der zweiten Ge­ne­ra­ti­on zu tun, und dieses zeigt sich von einer gänzlich anderen Seite: Die Anzahl der User sowie der weltweite Webtraf­fic haben sich ver­viel­facht. Das Gleiche gilt für die durch­schnitt­li­che Größe der Webseiten im Netz und die Anzahl der Kom­po­nen­ten, die ein Web­brow­ser abfragen und rendern muss, um diese dar­stel­len zu können. Ein wach­sen­der Teil der In­ter­net­ge­mein­de ist von klein auf mit den Mög­lich­kei­ten des Web 2.0 auf­ge­wach­sen. Diese Nut­zer­grup­pe ist es nicht gewohnt, mehrere Sekunden oder gar Minuten auf den Download einer Webseite zu warten.

Diese Ent­wick­lun­gen haben den Apache HTTP Server in den ver­gan­ge­nen Jahren immer wieder vor Her­aus­for­de­run­gen gestellt. Owen Garrett macht dafür die pro­zess­ba­sier­te Ar­chi­tek­tur des Apache ver­ant­wort­lich, die an­ge­sichts des rasant stei­gen­den Traffic-Auf­kom­mens nicht gut skaliert werden könne. Dieser Schwach­punkt war eine der Haupt­mo­ti­va­tio­nen für die Ent­wick­lung von NGINX im Jahr 2002, der mit einer event­ge­steu­er­ten Ar­chi­tek­tur gänzlich andere Wege ein­schlägt. NGINX geht auf den rus­si­schen Software-Ent­wick­ler Igor Sysoev zurück, der die Software, die glei­cher­ma­ßen als Webserver, Reverse-Proxy und E-Mail-Proxy zum Einsatz kommt, speziell auf die Be­dürf­nis­se der rus­si­schen Such­ma­schi­ne Rambler zu­ge­schnit­ten hat.

Wir stellen beide Webserver in einem Vergleich gegenüber und gehen dabei auf ar­chi­tek­to­ni­sche Un­ter­schie­de, die Kon­fi­gu­ra­ti­on, Er­wei­te­rungs­mög­lich­kei­ten sowie auf Kom­pa­ti­bi­li­tät, Do­ku­men­ta­ti­on und Support ein.

Tipp

Eine all­ge­mei­ne Ein­füh­rung zu den beiden Open-Source-Web­ser­vern in unserem Vergleich sowie zu deren In­stal­la­ti­on und Kon­fi­gu­ra­ti­on finden Sie in den Grund­la­gen­ar­ti­keln zu Apache und NGINX.

Ar­chi­tek­to­ni­sche Un­ter­schie­de

Die Webserver Apache und NGINX setzen auf grund­ver­schie­de­ne Software-Ar­chi­tek­tu­ren. Un­ter­schied­li­che Konzepte finden sich in Bezug auf das Ver­bin­dungs­ma­nage­ment, die In­ter­pre­ta­ti­on von Cli­en­tan­fra­gen, den Umgang mit sta­ti­schen und dy­na­mi­schen Web­in­hal­ten sowie bei der Kon­fi­gu­ra­ti­on.

Ver­bin­dungs­ma­nage­ment

Die Open-Source-Webserver Apache und NGINX un­ter­schei­den sich im We­sent­li­chen darin, wie sie mit ein­ge­hen­den Cli­en­tan­fra­gen (Requests) umgehen. Während dem Apache eine pro­zess­ba­sier­te Ar­chi­tek­tur zugrunde liegt, erfolgt das Ver­bin­dungs­ma­nage­ment bei NGINX auf Grundlage eines event­ge­steu­er­ten Ver­ar­bei­tungs­al­go­rith­mus. Dieser er­mög­licht es, Requests res­sour­cen­spa­rend ab­zu­ar­bei­ten, selbst wenn diese aus einer Vielzahl von Ver­bin­dun­gen gleich­zei­tig eingehen. Dies wird – u. a. von den NGINX-Ent­wick­lern – als großer Vorteil gegenüber dem Apache HTTP Server angeführt. Doch auch dieser bietet ab Version 2.4 die Mög­lich­keit, Events zu im­ple­men­tie­ren. Die Un­ter­schie­de liegen somit im Detail.

Der Apache-Webserver folgt einem Ansatz, bei dem jede Cli­en­tan­fra­ge von einem separaten Prozess oder Thread be­ar­bei­tet wird. Dies ist bei Single-Threading – dem ur­sprüng­li­chen Be­triebs­mo­dus des Apache HTTP Servers – früher oder später mit I/O-Blocking-Problemen verbunden: Prozesse, die Schreib- oder Le­se­ope­ra­tio­nen erfordern, werden strikt nach­ein­an­der ab­ge­ar­bei­tet. Ein nach­fol­gen­der Request verweilt solange in der War­te­schlei­fe, bis der vor­her­ge­hen­de be­ant­wor­tet wurde. Umgehen lässt sich dies, indem mehre Single-Threading-Prozesse gleich­zei­tig gestartet werden – eine Strategie, die mit einem hohen Res­sour­cen-Verbrauch verbunden ist.

Al­ter­na­tiv kommen Multi-Threading-Me­cha­nis­men zum Einsatz. Im Gegensatz zum Single-Threading, bei dem in jedem Prozess lediglich ein Thread zur Verfügung steht, um Cli­en­tan­fra­gen zu be­ant­wor­ten, bietet Multi-Threading die Mög­lich­keit, mehrere Threads in ein und demselben Prozess laufen zu lassen. Da Threads unter Linux weniger Res­sour­cen benötigen als Prozesse, bietet Multi-Threading die Mög­lich­keit, den großen Res­sour­cen­be­darf der pro­zess­ge­stütz­ten Ar­chi­tek­tur des Apache HTTP Servers zu kom­pen­sie­ren.

In­te­grie­ren lassen sich Me­cha­nis­men zur par­al­le­len Be­ar­bei­tung von Cli­en­tan­fra­gen bei Apache durch eines von drei Multi-Pro­ces­sing-Modulen (MPMs): mpm_prefork, mpm_worker, mpm_event.

  • mpm_prefork: Das Apache-Modul „Prefork“ bietet ein Multi-Prozess-Ma­nage­ment auf Basis eines Single-Threading-Me­cha­nis­mus. Das Modul erzeugt einen El­tern­pro­zess, der einen Vorrat an Kind­pro­zes­sen zur Verfügung stellt. In jedem Kind­pro­zess läuft ein Thread, der es er­mög­licht, jeweils eine Cli­en­tan­fra­ge zu be­ant­wor­ten. Solange mehr Single-Thread-Prozesse vorhanden sind, als Cli­en­tan­fra­gen eingehen, werden die Requests gleich­zei­tig ab­ge­ar­bei­tet.
    Die Anzahl der ver­füg­ba­ren Single-Threading-Prozesse wird mithilfe der Ser­ver­kon­fi­gu­ra­ti­ons­op­tio­nen „Min­S­pa­re­Ser­vers“ und „Max­Spa­re­Ser­vers“ definiert. Prefork birgt die oben erwähnten Per­for­mance-Nachteile des Single-Th­re­a­dings. Von Vorteil ist jedoch die weit­ge­hen­de Un­ab­hän­gig­keit separater Prozesse: Geht eine Ver­bin­dung aufgrund eines feh­ler­haf­ten Prozesses verloren, wirkt sich dies in der Regel nicht auf die Ver­bin­dun­gen aus, die in anderen Prozessen be­ar­bei­tet werden.
  • mpm_worker: Mit dem Modul „Worker“ stellt Apache Nutzern einen Multi-Threading-Me­cha­nis­mus zur par­al­le­len Be­ar­bei­tung von Cli­en­tan­fra­gen zur Verfügung. Wie viele Threads pro Prozess gestartet werden können, lässt sich mithilfe der Ser­ver­kon­fi­gu­ra­ti­ons­op­ti­on „Th­read­sPer­Child“ de­fi­nie­ren. Das Modul sieht einen Thread pro TCP-Ver­bin­dung vor. Solange mehr Threads zur Verfügung stehen, als Cli­en­tan­fra­gen eingehen, werden die Requests parallel ab­ge­ar­bei­tet. Über un­be­schäf­tig­te Threads wacht der El­tern­pro­zess (httpd).
    Nutzern stehen die Befehle „Min­S­pa­reTh­reads“ und „Max­Spa­reTh­reads“ zur Verfügung, um zu de­fi­nie­ren, ab welcher Anzahl un­be­schäf­tig­ter Threads neue Threads erzeugt bzw. laufende Threads aus dem Speicher entfernt werden. Das Worker-Modul hat einen we­sent­lich geringen Res­sour­cen­be­darf als das Prefork-Modul. Da Ver­bin­dun­gen nicht in separaten Prozessen ver­ar­bei­tet werden, kann sich ein feh­ler­haf­ter Thread jedoch auf den gesamten Multi-Threading-Prozess und damit auf alle Ver­bin­dun­gen, die in diesem be­ar­bei­tet werden, auswirken. Zudem ist Worker ebenso wie Prefork anfällig für Über­las­tun­gen durch so­ge­nann­te Keep-Alive-Ver­bin­dun­gen (s. u.).
  • mpm_event: Seit Version 2.4 steht dem Apache HTTP Server mit Event ein drittes Multi-Pro­ces­sing-Modul für den Pro­duk­tiv­ein­satz zur Verfügung. Dieses stellt eine Variante des Worker-Moduls dar, die für eine Last­ver­tei­lung zwischen den ge­star­te­ten Threads sorgt. Dazu kommt pro Multi-Threading-Prozess ein so­ge­nann­ter Listener-Thread zum Einsatz, der ein­ge­hen­de Cli­en­tan­fra­gen ent­ge­gen­nimmt und damit zu­sam­men­hän­gen­de Aufgaben auf Worker-Threads verteilt.
    Das Event-Modul wurde ent­wi­ckelt, um den Umgang mit so­ge­nann­ten Keep-Alive-Ver­bin­dun­gen zu op­ti­mie­ren, also TCP-Ver­bin­dun­gen, die aufrecht gehalten werden, um die Über­tra­gung weiterer Cli­en­tan­fra­gen oder Ser­ver­ant­wor­ten (Responses) zu er­mög­li­chen. Kommt das klas­si­sche Worker-Modul zum Einsatz, halten Worker-Threads einmal auf­ge­bau­te Ver­bin­dun­gen in der Regel aufrecht und werden somit blockiert – selbst dann, wenn keine weiteren Anfragen eingehen. Dies kann bei einer hohen Anzahl von Keep-Alive-Ver­bin­dun­gen zu einer Über­las­tung des Servers führen. Das Event-Modul hingegen lagert die Auf­recht­erhal­tung von Keep-Alive-Ver­bin­dun­gen an den un­ab­hän­gi­gen Listener-Thread aus. Worker-Threads werden somit nicht blockiert und stehen für die Be­ar­bei­tung weiterer Anfragen zur Verfügung.

Folgende Grafik zeigt eine sche­ma­ti­sche Dar­stel­lung der pro­zess­ba­sier­ten Ar­chi­tek­tur des Apache-Web­ser­vers unter Ver­wen­dung des Worker-Moduls:

Je nachdem, welches Modul Anwendung findet, löst Apache das Con­cur­ren­cy-Problem (auch „Ne­ben­läu­fig­keit“, die gleich­zei­ti­ge Be­ant­wor­tung mehrerer Cli­en­tan­fra­gen) entweder durch zu­sätz­li­che Prozesse oder Threads. Beide Lö­sungs­stra­te­gien gehen mit zu­sätz­li­chem Res­sour­cen­auf­wand einher. Dieser wird bei der Ska­lie­rung eines Apache Servers zum li­mi­tie­ren­den Faktor.

Der enorme Res­sour­cen­hun­ger des Ein-Prozess-pro-Ver­bin­dung-Ansatzes re­sul­tiert daraus, dass für jeden zu­sätz­li­chen Prozess eine eigene Lauf­zeit­um­ge­bung be­reit­ge­stellt werden muss. Diese erfordert die Zuweisung von CPU-Zeit und separatem Speicher. Zudem muss jedes Apache-Modul, das in einem Worker-Prozess zur Verfügung stehen soll, für jeden Prozess separat geladen werden. Threads hingegen teilen sich eine Aus­füh­rungs­um­ge­bung (das Programm) und den Adress­raum im Speicher. Der Overhead zu­sätz­li­cher Threads ist dadurch erheblich geringer als der von Prozessen. Doch auch Multi-Threading ist re­chen­in­ten­siv, wenn es zu Kon­text­wech­seln (Context Switches) kommt.

Als Kon­text­wech­sel be­zeich­net man den Vorgang, bei dem ein System von einem Prozess bzw. Thread zu einem anderen um­schal­tet. Dazu muss der Kontext des beendeten Prozesses bzw. Threads gesichert und der des neuen erzeugt bzw. wie­der­her­ge­stellt werden. Ein zeit­in­ten­si­ver ad­mi­nis­tra­ti­ver Vorgang, bei dem CPU-Register sowie diverse Tabellen und Listen geladen und gesichert werden müssen.

Das Modul mpm_event hält einen Event-Me­cha­nis­mus für den Apache HTTP Server bereit, der die Be­ar­bei­tung ein­ge­hen­der Ver­bin­dun­gen an einen Listener-Thread auslagert. Dieser er­mög­licht es, nicht mehr benötigte Ver­bin­dun­gen (auch Keep-Alive-Ver­bin­dun­gen) zu beenden und so den Res­sour­cen­ver­brauch zu re­du­zie­ren. Nicht gelöst wird das Problem re­chen­in­ten­si­ver Kon­text­wech­sel, die entstehen, wenn der Listener-Thread Requests über die von ihm ge­hal­te­nen Ver­bin­dun­gen an separate Worker-Threads übergibt.

Die von Grund auf event­ba­sier­te Ar­chi­tek­tur von NGINX hingegen rea­li­siert Ne­ben­läu­fig­keit, ohne dass für jede neue Ver­bin­dung ein zu­sätz­li­cher Prozess oder Thread benötigt wird. Ein einzelner NGINX-Prozess kann Tausende von HTTP-Ver­bin­dun­gen gleich­zei­tig ver­ar­bei­ten. Rea­li­siert wird dies durch einen Schlei­fen­me­cha­nis­mus, den so­ge­nann­ten Event-Loop. Dieser er­mög­licht es, Cli­en­tan­fra­gen asynchron innerhalb eines Threads ab­zu­ar­bei­ten.

Tipp

Theo­re­tisch kommt NGINX bei der Ver­ar­bei­tung von Ver­bin­dun­gen mit nur einem Single-Threading-Prozess aus. Um die Hardware optimal aus­zu­nut­zen, wird der Webserver in der Regel jedoch mit einem Worker-Prozess pro Pro­zes­sor­kern (CPU) der zu­grun­de­lie­gen­den Maschine gestartet.

Anders als der Apache-Webserver, bei dem sich die Anzahl der aktiven Prozesse bzw. Threads lediglich durch Minimal- und Ma­xi­mal­wer­te ein­gren­zen lässt, bietet NGINX ein vor­her­sag­ba­res Pro­zess­mo­dell, das exakt auf die zu­grun­de­lie­gen­de Hardware abstimmt wird. Dieses umfasst einen Master-Prozess, die Hel­fer­pro­zes­se Cache-Loader und Cache-Manager sowie eine auf die Anzahl der Pro­zes­sor­ker­ne ab­ge­stimm­te und durch die Kon­fi­gu­ra­ti­on exakt fest­ge­leg­te Anzahl an Worker-Prozessen.

  • Master-Prozess: Beim Master-Prozess handelt es sich um einen über­ge­ord­ne­ten Prozess, der alle grund­le­gen­den Ope­ra­tio­nen ausführt. Zu diesen gehören u. a. das Einlesen der Server-Kon­fi­gu­ra­ti­on, die Port­bin­dung sowie die Er­stel­lung aller folgenden Pro­zess­ty­pen.
  • Hel­fer­pro­zes­se: NGINX nutzt zwei Hel­fer­pro­zes­se für das Cache-Ma­nage­ment: Cache-Loader und Cache-Manager.
    • Cache-Loader: Der Cache-Loader ist dafür ver­ant­wort­lich, dass der fest­plat­ten­ba­sier­te Cache in den Ar­beits­spei­cher geladen wird.

    • Cache-Manager: Aufgabe des Cache-Managers ist es, darauf zu achten, dass Einträge aus dem Fest­plat­ten-Cache die zuvor kon­fi­gu­rier­te Größe aufweisen, und diese bei Bedarf zu be­schnei­den. Dieser Prozess wird pe­ri­odisch auf­ge­ru­fen.
  • Worker-Prozess: Worker-Prozesse sind für die Be­ar­bei­tung von Ver­bin­dun­gen, für Schreib- und Le­se­zu­grif­fe auf die Fest­plat­te sowie für die Kom­mu­ni­ka­ti­on mit Upstream-Servern (Server, die anderen Servern Dienste zur Verfügung stellen) ver­ant­wort­lich. Es handelt sich somit um die einzigen Prozesse des NGINX-Prozess-Modells, die durch­gän­gig aktiv sind.

Folgende Grafik zeigt eine sche­ma­ti­sche Dar­stel­lung des NGINX-Prozess-Modells:

Alle Worker-Prozesse, die vom NGINX-Master-Prozess im Rahmen der Kon­fi­gu­ra­ti­on gestartet werden, teilen sich ein Set von Listener-Sockets (Kom­mu­ni­ka­ti­ons­end­punk­te). Statt für jede ein­ge­hen­de Ver­bin­dung einen eigenen Prozess oder Thread zu starten, wird in jedem Worker-Prozess ein Event-Loop aus­ge­führt, der die asyn­chro­ne Be­ar­bei­tung mehrerer Tausend Ver­bin­dun­gen innerhalb eines Threads er­mög­licht, ohne den Prozess zu blo­ckie­ren. Dazu lauschen die Worker-Prozesse an den Listener-Sockets kon­ti­nu­ier­lich auf Events, die durch ein­ge­hen­de Ver­bin­dun­gen ausgelöst werden, nehmen diese an und führen während der Be­ar­bei­tung von HTTP-Requests Lese- und Schreib­pro­zes­se am Socket aus.

Dabei stellt NGINX keine eigenen Me­cha­nis­men für die Ver­tei­lung von Ver­bin­dun­gen auf Worker-Prozesse zu Verfügung. Statt­des­sen kommen Kernel-Funk­tio­nen des Be­triebs­sys­tems zum Einsatz. Schemata, wie ein­ge­hen­de Anfragen zu ver­ar­bei­ten sind, werden durch separate Zu­stands­ma­schi­nen (State Machines) für HTTP, raw TCP sowie SMTP, IMAP und POP3 be­reit­ge­stellt.

Ganz allgemein kann NGINX als Event-Handler be­zeich­net werden, der vom Kernel In­for­ma­tio­nen über Events erhält und dem Be­triebs­sys­tem sagt, wie die damit zu­sam­men­hän­gen­den Aufgaben zu be­ar­bei­ten sind. Die asyn­chro­ne Be­ar­bei­tung von Aufgaben innerhalb des Event-Loops beruht auf Er­eig­nis­be­nach­rich­ti­gun­gen, Rück­ruf­funk­tio­nen (Callbacks) und Timern. Diese Me­cha­nis­men er­mög­li­chen es, dass ein Worker-Prozess eine Operation nach der anderen ans Be­triebs­sys­tem de­le­gie­ren kann, ohne untätig auf das Ergebnis einer Operation oder die Antwort von Client-Pro­gram­men warten zu müssen. NGINX fungiert somit als Or­chestra­tor für das Be­triebs­sys­tem, welches das Lesen und Schreiben von Bytes übernimmt.

Diese Art des Ver­bin­dungs­ma­nage­ments erzeugt lediglich einen minimalen Overhead für zu­sätz­li­che Ver­bin­dun­gen. Alles was benötigt wird, ist ein zu­sätz­li­cher File De­scrip­tor (FD) und ein Minimum an zu­sätz­li­chem Ar­beits­spei­cher im Worker-Prozess. Re­chen­in­ten­si­ve Kon­text­wech­sel hingegen treten lediglich dann auf, wenn innerhalb eines Event-Loops keine weiteren Events auftreten. Diese Ef­fek­ti­vi­tät bei der Be­ar­bei­tung von Anfragen über eine Vielzahl von Ver­bin­dun­gen prä­de­sti­niert NGINX als Last­ver­tei­ler für stark fre­quen­tier­te Websites wie bei­spiels­wei­se WordPress.com.

Fazit

NGINX bietet mit der event­ge­stütz­ten Ar­chi­tek­tur eine Al­ter­na­ti­ve zum pro­zess­ba­sier­ten Ver­bin­dungs­ma­nage­ment des Apache HTTP Servers. Als Erklärung, warum NGINX bei Benchmark-Tests so gut ab­schnei­det, reicht dieses Merkmal allein jedoch nicht aus. Denn auch Apache un­ter­stützt seit Version 2.4 einen event­ba­sier­ten Ver­ar­bei­tungs­me­cha­nis­mus für Cli­en­tan­fra­gen. Achten Sie bei Webserver-Ver­glei­chen wie Apache vs. NGINX daher stets darauf, mit welchen Modulen die Webserver im Test zum Einsatz kommen, wie die Webserver kon­fi­gu­riert sind und welche Aufgaben bewältigt werden müssen.

Umgang mit sta­ti­schen und dy­na­mi­schen Web­in­hal­ten

Auch im Umgang mit dy­na­mi­schen Web­in­hal­ten folgt NGINX einer anderen Strategie als der Apache HTTP Server.

Prin­zi­pi­ell gilt: Um dy­na­mi­sche Web­in­hal­te aus­lie­fern zu können, muss ein Webserver auf einen In­ter­pre­ter zu­rück­grei­fen, der in der Lage ist, eine dazu benötigte Pro­gram­mier­spra­chen wie PHP, Perl, Python oder Ruby zu ver­ar­bei­ten. Apache stellt dazu diverse Module wie mod_php, mod_perl, mod_python oder mod_ruby zur Verfügung, die es er­mög­li­chen, den ent­spre­chen­den In­ter­pre­ter direkt in den Webserver zu laden. Somit wird Apache selbst mit der Fähigkeit aus­ge­stat­tet, dy­na­mi­sche Web­in­hal­te, die mit der ent­spre­chen­den Pro­gram­mier­spra­che erstellt wurden, zu ver­ar­bei­ten. Funk­tio­nen für die Be­reit­stel­lung sta­ti­scher Inhalte werden bereits durch die oben an­ge­spro­che­nen MPM-Module im­ple­men­tiert.

NGINX hingegen bietet lediglich Me­cha­nis­men, um statische Web­in­hal­te aus­zu­lie­fern. Die Be­reit­stel­lung dy­na­mi­scher Inhalte wird an darauf spe­zia­li­sier­te An­wen­dungs­ser­ver aus­ge­la­gert. NGINX fungiert in diesem Fall lediglich als Proxy zwischen Client-Programm und Upsteam-Server. Die Kom­mu­ni­ka­ti­on erfolgt über Pro­to­kol­le wie HTTP, FastCGI, SCGI, uWSGI und Memcached. Als mögliche An­wen­dungs­ser­ver für die Aus­lie­fe­rung dy­na­mi­scher Inhalte bieten sich WebSphere, JBoss oder Tomcat an. Doch auch der Apache HTTP Server kann zu diesem Zweck zum Einsatz kommen.

Beide Stra­te­gien beim Umgang mit sta­ti­schen und dy­na­mi­schen Inhalten sind mit Vor- und Nach­tei­len verbunden. Ein Modul wie mod_php er­mög­licht dem Webserver, PHP-Code selbst aus­zu­füh­ren. Ein separater An­wen­dungs­ser­ver wird nicht benötigt. Das macht die Ad­mi­nis­tra­ti­on dy­na­mi­scher Webseiten sehr bequem. Die In­ter­pre­ter-Module für dy­na­mi­sche Pro­gram­mier­spra­chen jedoch müssen separat in jeden Worker-Prozess geladen werden, der mit der Aus­lie­fe­rung des Contents betraut ist. Bei einer großen Anzahl von Worker-Prozessen geht dies mit einem deut­li­chen Overhead einher. Diesen Overhead reduziert NGINX, da der aus­ge­la­ger­te In­ter­pre­ter nur bei Bedarf hin­zu­ge­zo­gen wird.

Während NGINX auf die In­ter­ak­ti­on mit einem aus­ge­la­ger­ten In­ter­pre­ter fest­ge­legt ist, stehen Apache-Nutzern prin­zi­pi­ell beide Stra­te­gien offen. Auch Apache kann einem An­wen­dungs­ser­ver vor­ge­la­gert werden, der die In­ter­pre­ta­ti­on dy­na­mi­scher Web­in­hal­te übernimmt. In der Regel wird dazu das Protokoll FastCGI verwende. Eine ent­spre­chen­de Schnitt­stel­le lässt sich mit dem Modul mod_proxy_fcgi laden.

Fazit

Mit beiden Web­ser­vern in unserem Vergleich lassen sich dy­na­mi­sche Webseiten aus­lie­fern. Doch während Apache Pro­gramm­code, der dabei zum Einsatz kommt, mithilfe von Modulen selbst in­ter­pre­tiert und ausführt, lagert NGINX diesen Ar­beits­schritt an einen externen An­wen­dungs­ser­ver aus.

In­ter­pre­ta­ti­on von Cli­en­tan­fra­gen

Um Anfragen von Client-Pro­gram­men (bei­spiels­wei­se Web­brow­sern oder E-Mail-Pro­gram­men) zu­frie­den­stel­lend be­ant­wor­ten zu können, muss ein Server auf Grundlage des Requests ermitteln, welche Ressource an­ge­for­dert wird und wo sich diese befindet.

Der Apache HTTP Server wurde als Webserver kon­zi­piert. NGINX hingegen bietet sowohl Web- als auch Proxy-Server-Funk­tio­nen. Dieser Un­ter­schied im Fokus spiegelt sich u. a. in der Art wieder, wie die jeweilige Software Cli­en­tan­fra­gen in­ter­pre­tiert und Res­sour­cen auf dem Server zuordnet.

Hinweis

Auch der Apache HTTP Server lässt sich mithilfe des Moduls mod_proxy als Pro­xy­ser­ver einsetzen.

Apache HTTP Server und NGINX verfügen beide über Me­cha­nis­men, die es er­mög­li­chen, ein­ge­hen­de Requests entweder als physische Res­sour­cen im Da­tei­sys­tem oder als URIs (Uniform Resource Iden­ti­fier) zu in­ter­pre­tie­ren. Doch während der Apache stan­dard­mä­ßig da­tei­ba­siert arbeitet, steht bei NGINX die URI-basierte Ver­ar­bei­tung von Anfragen im Vor­der­grund.

Geht beim Apache HTTP Server eine Client-Anfrage ein, geht dieser stan­dard­mä­ßig davon aus, dass eine bestimmte Ressource aus dem Da­tei­sys­tem des Servers abgerufen werden soll. Da Apache mittels Vir­tu­al­Hosts die Mög­lich­keit bietet, un­ter­schied­li­che Web­in­hal­te auf ein und demselben Server unter un­ter­schied­li­chen Host-Namen, IP-Adressen oder Port-Nummern be­reit­zu­stel­len, muss zunächst ermittelt werden, auf welchen Vir­tu­al­Host sich der Request bezieht. Dazu gleicht der Webserver Host-Name, IP-Adresse und Port-Nummer am Anfang der Request-URI mit den in der Haupt­kon­fi­gu­ra­ti­ons­da­tei httpd.conf de­fi­nier­ten Vir­tu­al­Hosts ab.

Folgendes Code­bei­spiel zeigt eine Apache-Kon­fi­gu­ra­ti­on, bei der die beiden Domains www.example.com und www.other-example.com unter derselben IP-Adresse betrieben werden:

NameVirtualHost *:80
<VirtualHost *:80>
ServerName www.example.com
ServerAlias example.com *.example.com
DocumentRoot /data/www/example
</VirtualHost>
<VirtualHost *:80>
ServerName www.other-example.com
DocumentRoot /data/www/other-example
</VirtualHost>
Tipp

Möchten Sie mehr über Apache erfahren? Mehr In­for­ma­tio­nen finden Sie in unserem Beitrag zum Thema "Was ist Apache?".

Der Asterisk (*) dient als Platz­hal­ter für eine beliebige IP-Adresse. In welcher Do­cu­men­tRoot (dem Start­ver­zeich­nis eines Web­pro­jekts) die an­ge­frag­te Ressource gesucht wird, ent­schei­det Apache durch einen Abgleich des im Request ent­hal­te­nen Host-Namen mit der Ser­ver­Na­me-Direktive.

Hat Apache den ge­wünsch­ten Server gefunden, wird der Request-URI stan­dard­mä­ßig auf das Da­tei­sys­tem des Servers ab­ge­bil­det (Mapping). Apache nutzt dazu die im URI ent­hal­te­ne Pfad­an­ga­be. In Kom­bi­na­ti­on mit der Do­cu­men­tRoot ergibt sich der Pfad zur Ressource.

Bei einer Anfrage mit einem Request-URI 'http://www.example.org:80/public_html/images/logo.gif' würde Apache (ausgehend von dem oben dar­ge­stell­ten Beispiel) unter folgendem Dateipfad nach der ge­wünsch­ten Ressource suchen:

/data/www/example/public_html/images/logo.gif
Hinweis

Da 80 der Standard-Port für HTTP ist, wird diese Angabe in der Praxis meist weg­ge­las­sen.

Darüber hinaus gleicht Apache den Request-URI mit op­tio­na­len File- und Directory-Blöcken in der Kon­fi­gu­ra­ti­on ab. Diese er­mög­li­chen es, spezielle An­wei­sun­gen für Requests zu de­fi­nie­ren, die sich auf die aus­ge­wähl­ten Dateien oder Ver­zeich­nis­se (inklusive Un­ter­ver­zeich­nis­se) beziehen.

In folgendem Beispiel wurden spezielle An­wei­sun­gen für das Ver­zeich­nis public_html/images und die Datei private.html definiert:

<VirtualHost *:80>
    ServerName www.example.com
    ServerAlias example.com *.example.com
    DocumentRoot /data/www/example
      <Directory var/www/example.com/public_html/images>
          Order Allow,Deny
          Allow from all
     </Directory> 
      <Files public.html>
          Order Allow,Deny
          Deny from all
      </Files>
</VirtualHost>

Neben diesem Stan­dard­vor­ge­hen bei der In­ter­pre­ta­ti­on von Cli­en­tan­fra­gen bietet Apache mit der Alias-Direktive die Mög­lich­keit, ein Al­ter­na­tiv-Ver­zeich­nis anzugeben, das anstelle der Do­cu­men­tRoot nach der an­ge­frag­ten Ressource durch­sucht werden soll. Darüber hinaus hält der Apache HTTP Server mit mod_rewrite ein Modul bereit, das es Nutzern erlaubt, URLs um­zu­schrei­ben oder wei­ter­zu­lei­ten.

Tipp

Mehr zum Server-Modul mod_rewrite finden Sie im Grund­la­gen­ar­ti­kel zum Thema Rewrite-Engine

Soll Apache Res­sour­cen abrufen, die Außerhalb des Da­tei­sys­tems des Servers abgelegt wurden, kommt die Direktive Location zu Einsatz. Diese er­mög­licht es, An­wei­sun­gen für bestimmte URIs zu de­fi­nie­ren.

Was bei Apache eine Ausnahme darstellt, ist bei NGINX der Stan­dard­fall. NGINX parst zunächst den Request-URI und gleicht diesen mit Server- und Location-Blöcken in der Webserver-Kon­fi­gu­ra­ti­on ab. Erst danach findet (bei Bedarf) ein Mapping auf das Da­tei­sys­tem und die Kom­bi­na­ti­on mit der root (ent­spricht der Do­cu­men­tRoot des Apache-Servers) statt.

Mithilfe der Direktive Server ermittelt NGINX, welcher Host für die Be­ant­wor­tung der Client-Anfrage zuständig ist. Der Server-Block ent­spricht somit einem Vir­tu­al­Host in der Apache-Kon­fi­gu­ra­ti­on. Dazu werden der Host-Name, die IP-Adresse und die Port-Nummer des Request-URI mit allen in der Webserver-Kon­fi­gu­ra­ti­on de­fi­nier­ten Server-Blöcken ab­ge­gli­chen. Folgendes Code­bei­spiel zeigt drei Server-Blöcke innerhalb der NGINX-Kon­fi­gu­ra­ti­ons­da­tei nginx.conf:

server {
    listen 80;
    server_name example.org www.example.org;
    ...
}
server {
    listen 80;
    server_name example.net www.example.net;
    ...
}
server {
    listen 80;
    server_name example.com www.example.com;
    ...
}
Hinweis

Jeder Server-Block be­inhal­tet in der Regel eine Reihe von Location-Blöcken. Im aktuellen Beispiel wurden diese durch Platz­hal­ter () ersetzt.

Ein Abgleich des Request-URI mit den Location-Blöcken innerhalb eines Server-Blocks erfolgt erst, wenn der an­ge­frag­te Server gefunden wurde. Dazu liest NGINX die auf­ge­führ­ten Location-Blöcke ein und sucht nach der Location, die mit dem Request-URI am besten über­ein­stimmt. Jeder Location-Block be­inhal­tet spe­zi­fi­sche An­wei­sun­gen, die NGINX anzeigen, wie der ent­spre­chen­de Request zu be­ar­bei­ten ist.

Dabei können Locations so definiert werden, dass sie als Präfix für einen Pfad, als exakte Über­ein­stim­mung oder als Regulärer Ausdruck (Regular Ex­pres­si­on, RegEx) in­ter­pre­tiert werden. In der Syntax der Ser­ver­kon­fi­gu­ra­ti­on kommen dazu u. a. folgende Mo­di­fi­ka­to­ren zum Einsatz:

kein Mo­di­fi­ka­tor Die Location wird als Präfix in­ter­pre­tiert. Alle Requests, deren URI das in der Location-Direktive de­fi­nier­te Präfix aufweisen, gelten als mit der Location über­ein­stim­mend. Findet sich keine spe­zi­fi­sche­re Location, wird der Request gemäß den Angaben in diesem Location-Block ver­ar­bei­tet.
= Die Location wird als exakte Über­ein­stim­mung in­ter­pre­tiert. Alle Requests, deren URI mit der in der Location-Direktive auf­ge­führ­ten Zei­chen­fol­ge exakt über­ein­stimmt, werden gemäß den Angaben in diesem Location-Block ver­ar­bei­tet.
 ~ Die Location wird als Regulärer Ausdruck in­ter­pre­tiert. Alle Requests, deren URI mit dem Regulären Ausdruck über­ein­stimmt, werden gemäß den Angaben in diesem Location-Block ver­ar­bei­tet. Groß- und Klein­schrei­bung werden beim Abgleich aus­ge­wer­tet (case-sensitive).
~* Die Location wird als Regulärer Ausdruck in­ter­pre­tiert. Alle Requests, deren URI mit dem Regulären Ausdruck über­ein­stimmt, werden gemäß den Angaben in diesem Location-Block ver­ar­bei­tet. Groß- und Klein­schrei­bung werden beim Abgleich nicht aus­ge­wer­tet (case-in­sen­si­ti­ve).

Folgendes Beispiel zeigt drei Location-Blöcke, die anzeigen, wie ein­ge­hen­de Anfragen für die Domains example.org und www.example.org zu be­ar­bei­ten sind:

server {
    listen 80;
    server_name example.org www.example.org;
    root /data/www;
    location / {
        index index.html index.php;
    }
    location ~* \.(gif|jpg|png)$ {
        expires 30d;
    }
location ~ \.php$ {
        fastcgi_pass localhost:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

Ausgehend von einer Client-Anfrage mit der Request-URI www.example.org:80/logo.gifwürde NGINX fol­gen­der­ma­ßen vorgehen, um folgende Anfragen zu in­ter­pre­tie­ren und die ge­wünsch­te Ressource aus­zu­lie­fern:

http://www.example.org:80/logo.gif
http://www.example.org:80/index.php

Zunächst ermittelt NGINX die spe­zi­fischs­te Präfix-Location. Dazu liest der Webserver alle Locations ohne Mo­di­fi­ka­tor der Reihe nach ein und stoppt bei der ersten Location, die mit der Anfrage über­ein­stimmt. An­schlie­ßend werden alle Locations ein­ge­le­sen, die mit dem RegEx-Mo­di­fi­ka­tor (~­) markiert sind. Auch hier kommt der erste Treffer zur Anwendung. Findet sich keine passende RegEx-Location, greift der Webserver auf die zuvor er­mit­tel­te Präfix-Location als Fallback zurück.

Der Request-URI www.example.org:80/logo.gif stimmt bei­spiel­wei­se sowohl mit der Präfix-Location / als auch dem Regulären Ausdruck \.(gif|jpg|png)$ überein. NGINX würde die Anfrage daher in Kom­bi­na­ti­on mit der root auf den Dateipfad /data/www/logo.gif abbilden und die ent­spre­chen­de Ressource an den Client aus­lie­fern. Der Expires-Head gibt an, ab wann eine Antwort als veraltet gilt – im aktuellen Beispiel nach 30 Tagen: expires 30d.

Die Anfrage nach der PHP-Seite mit dem URI www.example.org:80/index.php stimmt ebenfalls mit der Prefix-Location / überein sowie mit der RegEx-Location ~ \.php$, welche bevorzugt behandelt wird. NGINX übergibt die Anfrage daher einem FastCGI-Server, der auf localhost:9000 lauscht und für die Be­ar­bei­tung dy­na­mi­scher Web­in­hal­te zuständig ist. Dabei setzt die Direktive fastcgi_param den FastCGI-Parameter SCRIPT_FILENAME auf /data/www/index.php. An­schlie­ßend wird die Datei auf dem Uptream-Server aus­ge­führt. Die Variable $document_root ent­spricht dabei der root-Direktive, die Variable $fastcgi_script_name dem Teil der URI, der auf Host-Name und Port-Nummer folgt: /index.php.

Dieses auf den ersten Blick etwas kom­pli­ziert er­schei­nen­de Vorgehen bei der In­ter­pre­ta­ti­on von Cli­en­tan­fra­gen ist den ver­schie­de­nen An­wen­dungs­fel­dern ge­schul­det, in denen NGINX zum Einsatz kommt. Im Vergleich zum primär da­tei­ba­sier­ten Vorgehen des Apache HTTP Servers er­mög­licht die URI-basierte In­ter­pre­ta­ti­on von Requests eine größere Fle­xi­bi­li­tät bei der Be­ar­bei­tung un­ter­schied­li­cher An­fra­ge­mus­ter. Benötigt wird dies bei­spiels­wei­se dann, wenn NGINX nicht als Web- sondern als Proxy- oder Mail-Proxy-Server fungiert.

Fazit

Apache wird in erster Linie als Webserver ein­ge­setzt und in­ter­pre­tiert Cli­en­tan­fra­gen primär da­tei­ba­siert. NGINX hingegen arbeitet stan­dard­mä­ßig mit URIs und wird so auch anderen An­fra­ge­mus­tern gerecht.

Kon­fi­gu­ra­ti­on

NGINX wird gegenüber dem Apache HTTP Server ein enormer Ge­schwin­dig­keits­vor­teil bei der Aus­lie­fe­rung von sta­ti­schen Web­in­hal­ten nach­ge­sagt. Dieser ist u. a. auf Un­ter­schie­de bei der Kon­fi­gu­ra­ti­on zu­rück­zu­füh­ren. Der Apache-Webserver bietet Ad­mi­nis­tra­to­ren neben der Haupt­kon­fi­gu­ra­ti­ons­da­tei httpd.conf die Mög­lich­keit einer Ver­wal­tung auf Ver­zeich­nis­ebe­ne. Dazu kommen so­ge­nann­te .htaccess-Dateien zum Einsatz. Diese de­zen­tra­len Kon­fi­gu­ra­ti­ons­da­tei­en lassen sich prin­zi­pi­ell in jedem be­lie­bi­gen Server-Ver­zeich­nis im­ple­men­tie­ren. An­wei­sun­gen, die in einer .htaccess definiert wurden, beziehen sich sowohl auf das Ver­zeich­nis, das die Kon­fi­gu­ra­ti­ons­da­tei enthält, als auch auf dessen Un­ter­ver­zeich­nis­se. In der Praxis kommen .htaccess-Dateien zum Einsatz, um den Ver­zeich­nis­zu­griff auf bestimmte Nut­zer­krei­se zu be­schrän­ken, einen Pass­wort­schutz ein­zu­rich­ten sowie Re­ge­lun­gen für das Ver­zeich­nis-Browsing, Feh­ler­mel­dun­gen, Wei­ter­lei­tun­gen oder al­ter­na­ti­ve Inhalte zu de­fi­nie­ren. Zu beachten ist, dass sich all dies auch zentral in der httpd.conf-Datei kon­fi­gu­rie­ren ließe. Relevant wird die .htaccess jedoch bei Web­hos­ting-Modellen wie dem Shared Hosting, bei dem der Zugriff auf die Haupt­kon­fi­gu­ra­ti­ons­da­tei dem Hosting-Dienst­leis­ter vor­be­hal­ten ist. Die de­zen­tra­le Kon­fi­gu­ra­ti­on via .htaccess er­mög­licht es, Nutzern die Ad­mi­nis­tra­ti­on für bestimmte Bereiche des Server-Da­tei­sys­tems – bei­spiels­wei­se für aus­ge­wähl­te Pro­jekt­ver­zeich­nis­se – zu erlauben, ohne ihnen Zugriff auf die Haupt­kon­fi­gu­ra­ti­on zu gewähren. Außerdem treten Än­de­run­gen sofort und ohne Neustart in Kraft. NGINX hingegen bietet lediglich zentrale Kon­fi­gu­ra­ti­ons­mög­lich­kei­ten. Sämtliche An­wei­sun­gen werden in der Datei nginx.conf definiert. Mit dem Zugriff auf diese Datei erhält ein Nutzer die Kontrolle über den gesamten Server. Anders als bei Apache lässt sich der ad­mi­nis­tra­ti­ve Zugang somit nicht auf aus­ge­wähl­te Ver­zeich­nis­se be­schrän­ken. Dies hat sowohl Vor- als auch Nachteile. Die zentrale Kon­fi­gu­ra­ti­on von NGINX ist weniger flexibel als das Konzept des Apache HTTP Servers, bietet jedoch einen deut­li­chen Si­cher­heits­vor­teil: Än­de­run­gen an der Kon­fi­gu­ra­ti­on des Web­ser­vers können nur von Nutzern vor­ge­nom­men werden, die über Root-Rechte verfügen. Wichtiger jedoch als das Si­cher­heits­ar­gu­ment ist der Per­for­mance-Nachteil einer de­zen­tra­len Kon­fi­gu­ra­ti­on via .htaccess. Bereits in der Do­ku­men­ta­ti­on des Apache HTTP Servers empfehlen die Ent­wick­ler, auf den Gebrauch der .htaccess zu ver­zich­ten, sofern ein Zugriff die httpd.conf möglich ist. Grund dafür ist die Prozedur, in der Apache Kon­fi­gu­ra­ti­ons­da­tei­en einliest und in­ter­pre­tiert. Wie bereits an­ge­spro­chen folgt Apache stan­dard­mä­ßig einem da­tei­ba­sier­ten Schema, um Cli­en­tan­fra­gen zu be­ant­wor­ten. Da die Apache-Ar­chi­tek­tur eine de­zen­tra­le Kon­fi­gu­ra­ti­on er­mög­licht, durch­sucht der Webserver auf dem Weg zur an­ge­frag­ten Ressource jedes Ver­zeich­nis entlang des Da­tei­pfa­des nach einer .htaccess-Datei. Alle Kon­fi­gu­ra­ti­ons­da­tei­en, die er dabei passiert, werden ein­ge­le­sen und in­ter­pre­tiert – ein Schema, das den Webserver deutlich ausbremst.

Hinweis

Prin­zi­pi­ell ist es Apache-Ad­mi­nis­tra­to­ren frei­ge­stellt, ob sie auf die de­zen­tra­len Kon­fi­gu­ra­ti­ons­mög­lich­kei­ten des Web­ser­vers zu­rück­grei­fen und die damit zu­sam­men­hän­gen­den Vor- und Nachteile in Kauf nehmen möchten. In der Do­ku­men­ta­ti­on betonen die Ent­wick­ler, dass alle .htaccess-Kon­fi­gu­ra­tio­nen mittels Directory-Blöcken auch in der Haupt­kon­fi­gu­ra­ti­on httpd.conf vor­ge­nom­men werden können.

Anwender, die die de­zen­tra­le Kon­fi­gu­ra­ti­on unter Apache de­ak­ti­vie­ren oder ein­schrän­ken möchten, nutzen dafür die Direktive Al­lo­wO­ver­ri­de in Directory-Blöcken der Haupt­kon­fi­gu­ra­ti­ons­da­tei httpd.conf und setzten setzen diese auf None. Dies weist den Webserver an, alle .htaccess-Dateien in ent­spre­chend kon­fi­gu­rier­ten Ver­zeich­nis­sen zu igno­rie­ren.

<VirtualHost *:80>
    ServerName example.com;
    ...
    DocumentRoot /data/www/example
      <Directory /data/www/example>
        AllowOverride None
        ...
      </Directory>
    ...
</VirtualHost>

Die Bei­spiel­kon­fi­gu­ra­ti­on weist den Webserver an, alle .htaccess-Dateien für den Host example.com zu igno­rie­ren.

Fazit

Anders als NGINX, der lediglich zentral kon­fi­gu­riert wird, bietet der Apache mit .htaccess die Mög­lich­keit der de­zen­tra­len, ver­zeich­nis­ba­sier­ten Kon­fi­gu­ra­ti­on. Kommen .htaccess-Dateien zum Einsatz, büßt der Webserver jedoch Ge­schwin­dig­keit ein.

Er­wei­te­rungs­mög­lich­kei­ten

Beide Webserver in unserem Vergleich setzen auf ein modulares System, bei dem die Kern-Software bei Bedarf um zu­sätz­li­che Kom­po­nen­ten erweitert werden kann. Doch bis Version 1.9.10 verfolgte NGINX beim Umgang mit Modulen eine grund­sätz­lich andere Strategie als das Kon­kur­renz­pro­dukt. Der Apache HTTP Server stellt zwei Mög­lich­kei­ten zur Verfügung, die Kern-Software zu erweitern. Module lassen sich entweder während der Ent­wick­lung in die Apache-Bi­när­da­tei­en kom­pi­lie­ren oder dynamisch und somit während der Laufzeit laden. Es lassen sich drei Ka­te­go­rien von Apache-Modulen un­ter­schei­den:

  • Ba­sis­mo­du­le: Die Apache-Ba­sis­mo­du­le umfassen alle Kom­po­nen­ten, die die Kern­funk­tio­na­li­tä­ten des Web­ser­vers zur Verfügung stellen.
  • Er­wei­te­rungs­mo­du­le: Bei diesen Er­wei­te­run­gen handelt es sich um Module der Apache Foun­da­ti­on, die als Be­stand­teil der Apache Dis­tri­bu­ti­on mit­ge­lie­fert werden. Einen Überblick über alle in der Apache-2.4-Stan­dard­in­stal­la­ti­on ent­hal­te­nen Module bietet die Apache-Do­ku­men­ta­ti­on.
  • Dritt­an­bie­ter­mo­du­le: Diese Module werden nicht von der Apache-Foun­da­ti­on, sondern von externen Dienst­leis­tern oder selbst­stän­di­gen Pro­gram­mie­rern zur Verfügung gestellt.

Bei NGINX hingegen be­schränk­te sich die Mo­du­la­ri­tät lange auf statische Er­wei­te­rungs­kom­po­nen­ten, die in die Bi­när­da­tei des Software-Kerns kom­pi­liert werden mussten. Gerade für Anwender, die es nicht gewohnt waren, eigene Software-Kom­po­nen­ten ohne den Pa­ket­ma­na­ger der je­wei­li­gen Dis­tri­bu­ti­on zu verwalten, schränkte diese Art der Software-Er­wei­te­rung die Fle­xi­bi­li­tät des Web­ser­vers deutlich ein. Das Ent­wick­ler-Team hat in diesem Punkt nach­ge­bes­sert: Seit Version 1.9.11 (Release 09.02.2016) un­ter­stützt NGINX Me­cha­nis­men, die es er­mög­li­chen, statische Module in dy­na­mi­sche zu kon­ver­tie­ren, sodass diese während der Laufzeit über Kon­fi­gu­ra­ti­ons­da­tei­en geladen werden können. In beiden Fällen kommt die Modul-API des Servers zum Einsatz. Dabei ist zu beachten, dass sich nicht alle NGINX-Module in dy­na­mi­sche Module kon­ver­tie­ren lassen. Module, die den Quellcode der Server-Software patchen, sollten nicht dynamisch geladen werden. Zudem limitiert NGINX die Anzahl dy­na­mi­scher Module, die gleich­zei­tig geladen werden können, in der Stan­dard­ein­stel­lung auf 128. Um diesen Grenzwert zu erhöhen, setzen Sie die Konstante bei NGX_MAX_DYNAMIC_MODULES im NGINX-Quellcode auf den ge­wünsch­ten Wert. Zu­sätz­lich zu den of­fi­zi­el­len Modulen der NGINX-Do­ku­men­ta­ti­on stehen Anwendern diverse Dritt­an­bie­ter­mo­du­le bereit.

Fazit

Beide Webserver lassen sich modular erweitern. Neben sta­ti­schen Modulen stehen dy­na­mi­sche Module zur Verfügung, die bei Bedarf in das laufende Programm geladen werden können.

Do­ku­men­ta­ti­on und Support

Beide Software-Projekte sind gut do­ku­men­tiert und stellen Anwendern über Wikis und Blogs In­for­ma­tio­nen aus erster Hand zur Verfügung.

Während sich die NGINX-Do­ku­men­ta­ti­on nur auf Englisch und Russisch abrufen lässt, zeichnet sich das Apache-Projekt durch In­for­ma­ti­ons­ma­te­ria­li­en in zahl­rei­chen Sprach­ver­sio­nen aus. Diese sind jedoch teilweise veraltet, sodass ein Blick in die englische Do­ku­men­ta­ti­on auch hier un­er­läss­lich ist. Hilfe bei Problemen erhalten Nutzer bei beiden Open-Source-Projekten über die Community. Dabei fungieren Mai­ling­lis­ten als Dis­kus­si­ons­fo­ren.

Trans­pa­ren­te Release-Pläne und Roadmaps geben Nutzern die Mög­lich­keit, sich auf zu­künf­ti­ge Ent­wick­lun­gen ein­zu­stel­len. Software-Fehler und Si­cher­heits­lü­cken werden bei beiden Projekten in einem öf­fent­li­chen Bug-Report erfasst und auf­ge­ar­bei­tet.

Zu­sätz­lich zum Open-Source-Projekt NGINX bietet die Nginx, Inc. das kom­mer­zi­el­le Produkt NGINX Plus an. Gegen eine jährliche Nut­zungs­ge­bühr sichern sich Anwender zu­sätz­li­che Funk­tio­nen sowie eine pro­fes­sio­nel­len Support durch den Her­stel­ler. Eine Ver­gleichs­ma­trix beider Produkte finden Sie auf der NGINX-Website. Eine kom­mer­zi­el­le Edition des Apache HTTP Servers existiert nicht. Kos­ten­pflich­ti­ge Support-Dienst­leis­tun­gen werden jedoch durch diverse Dritt­an­bie­ter angeboten.

Fazit

Sowohl der Apache HTTP Server als auch NGINX sind für einen pro­fes­sio­nel­len Einsatz auf Pro­duk­tiv­sys­te­men aus­rei­chend do­ku­men­tiert.

Kom­pa­ti­bi­li­tät und Ökosystem

Der Apache HTTP Server prägt das World Wide Web seit mehr als zwei Dekaden und gilt aufgrund des Markt­an­teils nach wie vor als De-facto-Standard für die Be­reit­stel­lung von Web­in­hal­ten. Auch NGINX kann auf eine 15-jährige Er­folgs­ge­schich­te zu­rück­bli­cken. Beide Webserver zeichnen sich durch eine breite Platt­form­un­ter­stüt­zung aus. Während der Apache für alle unixoiden Be­triebs­sys­te­me sowie für Windows empfohlen wird, führt die NGINX-Do­ku­men­ta­ti­on folgende Systeme als getestet an: FreeBSD, Linux, Solaris, IBM AIX, HP-UX, macOS und Windows. Als Standard-Server zeichnet sich der Apache durch eine weit­ge­hen­de Kom­pa­ti­bi­li­tät zu Dritt­an­bie­ter-Projekten aus. Alle re­le­van­ten Web­stan­dards lassen sich über Module in­te­grie­ren. Hinzu kommt, dass ein Großteil der Akteure im Netz mit den Konzepten des Apache vertraut sind. Ad­mi­nis­tra­to­ren und Web­ent­wick­ler setzen ihre ersten Projekte in der Regel auf kos­ten­güns­ti­gen Shared-Hosting-Platt­for­men um. Diese wiederum basieren mehr­heit­lich auf Apache und der Mög­lich­keit einer de­zen­tra­len Kon­fi­gu­ra­ti­on via .htaccess. Darüber hinaus ist der Apache HTTP Server Teil diverser quell­of­fe­ner Pro­gramm­pa­ke­te für Ent­wick­lung und Software-Tests wie XAMPP oder AMPPS. Auch NGINX stellt Anwendern ein großes Ökosystem an Modulen zur Verfügung. Darüber hinaus pflegt das Ent­wick­ler-Team Part­ner­schaf­ten zu diversen quell­of­fe­nen und pro­prie­tä­ren Software-Projekten sowie zu In­fra­struk­tur-Dienst­leis­tern wie Amazon Web Services, Windows Azure und HP.

Fazit

Beide Webserver sind etabliert. Anwender können auf ein großes Ökosystem zu­rück­grei­fen. Apache hat im Vergleich zu NGINX den Vorteil, dass sich im Laufe der Jahre eine große Nut­zer­ge­mein­de in die Grund­la­gen des Web­ser­vers ein­ge­le­sen hat. Dass Tausende von Ad­mi­nis­tra­to­ren den Quellcode der Software geprüft und ver­bes­sert haben, spricht nicht nur für die Si­cher­heit des Web­ser­vers. Auch neue Nutzer pro­fi­tie­ren von der großen Anzahl er­fah­re­ner Apache-Ad­mi­nis­tra­to­ren, die der Community bei Problemen in Foren oder über Mai­ling­lis­ten zur Seite stehen.

NGINX vs. Apache: Die Un­ter­schie­de im Überblick

Trotz der großen Un­ter­schie­de in der Software-Ar­chi­tek­tur bieten beide Webserver ähnliche Funk­tio­nen. Apache und NGINX kommen in ver­gleich­ba­ren Szenarios zum Einsatz, greifen dabei jedoch auf jeweils eigene Stra­te­gien und Konzepte zurück, um den An­for­de­run­gen gerecht zu werden. Die nach­fol­gen­de Tabelle stellt beide Software-Projekte anhand zentraler Merkmale gegenüber und zeigt Schnitt­punk­te und Ab­wei­chun­gen auf.

Merkmal Apache NGINX
Funktion Webserver Proxy-Server Webserver Proxy-Server E-Mail-Proxy Load-Balancer
Pro­gram­mier­spra­che C C
Be­triebs­sys­tem Alle unixoiden Platt­for­men Windows FreeBSD Linux Solaris IBM AIX HP-UX macOS Windows
Ver­öf­fent­li­chung 1995 2002
Lizenz Apache License v2.0 BSD-Lizenz (Berkeley Software Dis­tri­bu­ti­on)
Ent­wick­ler Apache Software Foun­da­ti­on Nginx, Inc.
Software-Ar­chi­tek­tur Prozess-/th­re­ad­ba­siert Event­ge­steu­ert
Ne­ben­läu­fig­keit Multi-Pro­ces­sing Multi-Threading Event-Loop
Statische Web­in­hal­te Ja Ja
Dy­na­mi­sche Web­in­hal­te Ja Nein
In­ter­pre­ta­ti­on von Cli­en­tan­fra­gen Primär da­tei­ba­siert URI-basiert
Kon­fi­gu­ra­ti­on Zentrale Kon­fi­gu­ra­ti­on via httpd.conf De­zen­tra­le Kon­fi­gu­ra­ti­on via .htaccess Zentrale Kon­fi­gu­ra­ti­on via nginx.conf
Er­wei­te­rungs­mög­lich­kei­ten Statische Module Dy­na­mi­sche Module Statische Module Dy­na­mi­sche Module
Do­ku­men­ta­ti­on Deutsch Englisch Dänisch Spanisch Fran­zö­sisch Japanisch Ko­rea­nisch Por­tu­gie­sisch Türkisch Chi­ne­sisch Deutsch Englisch
Support durch Ent­wick­ler Nein Ja (kos­ten­pflich­tig über Nginx, Inc.)
Community-Support Mai­ling­lis­ten Wiki Mai­ling­lis­ten Wiki

Fazit

Mit Apache und NGINX stehen Anwendern zwei stabile, sichere Open-Source-Projekte zur Verfügung. Als klarer Gewinner geht jedoch keiner der beiden Webserver aus diesem Vergleich hervor. Beiden Projekten liegen grund­ver­schie­de­ne Design-Ent­schei­dun­gen zugrunde, die je nachdem, wie die Software zum Einsatz kommt, Vorteile oder Nachteile mit sich bringen.

Der Apache HTTP Server bietet ein immenses Re­per­toire an Modulen, das der Software zusammen mit den flexiblen Kon­fi­gu­ra­ti­ons­mög­lich­kei­ten zahl­rei­che An­wen­dungs­fel­der eröffnet. Der Webserver gilt als Standard-Software für Shared-Hosting-Szenarien und wird sich in diesem Ge­schäfts­feld auch zukünftig gegen leicht­ge­wich­ti­ge Webserver wie NGINX behaupten. Die Mög­lich­keit, In­ter­pre­ter für Pro­gram­mier­spra­chen wie PHP, Perl, Python oder Ruby über Module direkt in den Webserver zu in­te­grie­ren, erlaubt die Aus­lie­fe­rung dy­na­mi­scher Web­in­hal­te ohne einen separaten An­wen­dungs­ser­ver. Dies macht den Apache HTTP Server zu einer bequemen Lösung für kleine und mit­tel­gro­ße Websites, bei denen Inhalte während des Abrufs dynamisch erzeugt werden.

NGINX hingegen bietet keine Mög­lich­keit, dy­na­mi­sche Web­in­hal­te nativ zu ver­ar­bei­ten oder ent­spre­chen­de In­ter­pre­ter durch Module ein­zu­bin­den. Es wird somit in jedem Fall ein separater An­wen­dungs­ser­ver benötigt. Dies mag bei kleinen bis mit­tel­gro­ßen Websites als ein unnötiger Mehr­auf­wand er­schei­nen. Seine Stärken zeigt ein solcher Aufbau jedoch bei großen Web­pro­jek­ten und stei­gen­dem Traffic-Aufkommen.

In der Regel kommt NGINX als Load-Balancer vor einer Gruppe von An­wen­dungs­ser­vern zum Einsatz. Dabei nimmt der Load-Balancer ein­ge­hen­de Anfragen entgegen und ent­schei­det je nach Art des Requests, ob dieser an einen spe­zia­li­sier­ten Server im Hin­ter­grund wei­ter­ge­lei­tet werden muss. Statische Web­in­hal­te werden direkt von NGINX aus­ge­lie­fert. Fordert ein Client hingegen dy­na­mi­sche Inhalte an, gibt der Load-Balancer den Request an einen dafür vor­ge­se­he­nen An­wen­dungs­ser­ver weiter. Dieser in­ter­pre­tiert die Pro­gram­mier­spra­che, setzt die an­ge­for­der­ten Inhalte zu einer Webpage zusammen und gibt diese an den Load-Balancer zurück, der wiederum die Aus­lie­fe­rung an den Client übernimmt. Auf diese Weise lassen sich hohe Traffic-Aufkommen effektiv be­wäl­ti­gen.

Hinzu kommt, dass NGINX bereits aus­ge­lie­fer­te Inhalte für eine gewisse Zeit im Cache vorhält, sodass erneut an­ge­frag­te dy­na­mi­sche Inhalte direkt vom Load-Balancer aus­ge­lie­fert werden können, ohne dass NGINX erneut auf einen An­wen­dungs­ser­ver zu­rück­grei­fen muss.

Die Aus­la­ge­rung des In­ter­pre­ters auf einen oder mehrere separate Backend-Server hat den Vorteil, dass sich der Ser­ver­ver­bund bequem skalieren lässt, indem bei Bedarf zu­sätz­li­che Backend-Server hin­zu­ge­zo­gen oder nicht benötigte Systeme ab­ge­schal­tet werden können. In der Praxis setzen viele Anwender bei einem solchen Aufbau auf die Kom­bi­na­ti­on von NGINX und Apache und nutzen somit die Stärken beider Webserver.

Zum Hauptmenü