Im modernen Web findet man oft den für eine Webapplikation typischen Aufbau mit Webserver und Applikation. Ein Benutzer macht dabei die Requests alle an einen Webserver (NGINX, Apache, Traefik) welche seinerseits die Requests an eine Applikation (z.B. Django) weiterleitet.
Der Webserver kümmert sich dabei typischerweise um Themen wie SSL Terminierung oder Load Balancing. Neben diesen Aufgaben kann aber der Webserver aber auch als sogenannter Proxy Cache agieren, dabei werden die Antworten bestimmter Requests im Cache gespeichert und von da aus beantwortet, die Requests gelangen nie zur Applikation.
Modell
Für die Simulation wird SimPy verwendet, ein Python Paket für diskrete Ereignissimulation. Das ganze System wird über verschiedene Klassen modelliert, welche sich an der Übersicht weiter oben orientieren:
-
Der UserGenerator erzeugt exponentialverteilt mit einer gegeben Ankunftsrate neue User.
-
Ein User erzeugt einen initialen Page-Request (z.B. HTML Seite) und anschliessend 5 gleichzeitige Asset-Requests (z.B. JavaScript, CSS, Webfonts).
-
Der Page- oder Asset-Request wartet der Reihe nach auf einen Webserver-Worker, eine Applikations-Instanz (falls ohne Cache), die Application-Antwort (falls ohne Cache) und schliesslich auf die Webserver-Antwort.
-
Der Webserver ist eine Warteschlange mit einer Kapazität von 768 Worker und einer triangular-verteilten Verarbeitungszeit von 10/15/20ms.
-
Optional werden für den Cache Page-Requests für 5s respektive Asset-Requests unendlich lange beim ersten Request gespeichert.
-
-
Die Application ist eine Warteschlange mit einer Kapazität von 4 Instanzen und triangular-verteilten Verarbeitungszeit von 0.5/5/60s für Page-Requests respektive 100/150/200ms für Asset-Requests.
Währen der Simulation werden pro Request verschiedene Zeiten gemessen:
-
waiting_time_webserver : Wie lange auf einen Webserver-Worker gewartet wird.
-
waiting_time_application : Wie lange auf eine Applikations-Instanz gewartet wird.
-
response_time_application: Wie lange die Applikation für die Antwort braucht.
-
response_time_webserver: Wie lange der Webserver für die Antwort braucht.
-
total_time: Die Gesamtzeit des Requests.
Baseline: Ohne Cache
Ohne Cache – d.h. jeder Request wird vom Webserver direkt an die Applikation weitergereicht – steigt die Drop Rate – d.h. die Anzahl Requests, welche während der Simulationszeit von einer Stunde nie eine Antwort erhalten – ab einer Rate von rund 10 Benutzern pro Minute.
Bei nur einem Benutzer pro Minute gibt es keine Wartezeiten und die Antwortzeiten bestimmen sich durch die vorgegebenen Verteilungen. Die Gesamtzeit ist praktisch nur von der langsamen Applikation bestimmt. Bei 50 Benutzern pro Minute zeigt sich hingegen ein anderes Bild: Hier sind nun die Antwortzeiten verhältnismässig irrelevant, am meisten Zeit braucht das Warten auf eine Applikations-Instanz sowie das Warten auf einen Webserver-Worker. Das Bottleneck ist wie zu erwarten die langsame Applikation.
Caching von Assets
Assets wie JavaScript-, CSS- und Webfont-Dateien verändern sich relativ selten und können daher meist problemlos für einen längeren Zeitraum im Cache des Webserver gespeichert werden. Request für solche Dateien werden dadurch bereits vom Webserver beantwortet, die Applikation wird weniger belastet. Zwar steigt auch hier die Drop Rate ab ca. 10 Benutzern pro Minute, allerdings etwas weniger steil.
Deutlich gesunken ist hingegen die durchschnittlich Gesamtzeit (aufgrund der schneller beantworteten Assets-Requests). Immer noch ist jedoch das Warten auf freie Applikationsinstanzen das Bottleneck, da jeder User einen intitialen Page-Request benötigt. Mit steigender Anzahl Benutzer werden auch diese Requests nicht mehr beantwortet und der Assets-Cache ist wirkungslos.
Wie wirkt sich eigentlich eine Erhöhung der Anzahl Instanzen und Worker aus? Mit der Erhöhung der Anzahl Instanzen sinkt die Drop Rate stark, da mehr Requests gleichzeitig abgearbeitet werden können. Aber auch die Erhöhung der Anzahl Worker wirkt sich positiv auf die Drop Rate aus, da diese die stark variierende Antwortzeit der Applikation aber auch die unterschiedlichen Ankunftszeiten der User glätten können.
Caching von Pages und Assets
HTML Seiten sind generell kritischer bezüglich Cache, da sie meist dynamisch sind. Die Anzahl möglicher Benutzer pro Minute ohne Drop Rate steigt um den Faktor 100. Bereits eine nur kurze Cache Dauer von 5s für Page-Requests kann aber bereits einen starken Einfluss haben, da damit Spitzen gebrochen werden können.
Auch die mittlere Antwortzeit sinkt mit nur wenigen Sekunden Pages Cache. Schlussendlich ist auch hier wieder die langsame Applikation das Bottleneck respektive das Warten auf freie Applikations-Instanzen.
Ressourcen
-
Repository mit Jupyter Notebook, verfügbar unter https://gitlab.ost.ch/simulation/simulations/simpy-web-cache.
-
SimPy, kostenlos verfügbar, siehe https://simpy.readthedocs.io