Tutorial zur Verarbeitung statischer Ressourcen in Tomcat

Tutorial zur Verarbeitung statischer Ressourcen in Tomcat

Vorwort

Alle Anfragen in Tomcat werden von Servlet verarbeitet, und statische Ressourcen sind keine Ausnahme. In der Standarddatei web.xml ist ein DefaultServlet zur Verarbeitung statischer Ressourcen konfiguriert, das die Zwischenspeicherung und Wiederaufnahme von Haltepunkten unterstützt.

Die grundlegende Verarbeitung von DefaultServlet ist wie folgt:

  • Überprüfen, ob eine Ressource zwischengespeichert ist
  • Überprüft, ob die im optionalen If-Headerfeld angegebene Bedingung erfüllt ist.
  • Setzen Sie Antwortheaderfelder wie Content-Type, Content-Length, ETag, Last-Modified
  • Überprüft, ob die Bedingungen von Sendfile erfüllt sind, andernfalls kopiert er den Inhalt in den Ausgabestream

Als nächstes werden wir hauptsächlich das Design und die Implementierung des Ressourcen-Cachings sowie die Verarbeitung des If-Headerfelds analysieren.

1. Ressourcen-Cache-Design

Da die Zugriffsgeschwindigkeit auf die Festplatte wesentlich geringer ist als die Zugriffsgeschwindigkeit auf den Arbeitsspeicher, kann das ordnungsgemäße Zwischenspeichern einiger statischer Ressourcen zu schnelleren Systemreaktionen führen.

Als Tomcat die Verarbeitung statischer Ressourcen in Version 6.0.53 implementierte, verwendete es einige JNDI-APIs (aber es schien, dass dies bei der Verwendung wenig mit JNDI zu tun hatte). Die relevanten Klassendiagramme und Kernmethoden und -eigenschaften lauten wie folgt:

Cache-bezogene Klassen:

  • ResourceCache: Cache-Implementierung, die Funktionen zum Suchen, Laden und Löschen von Ressourcen bereitstellt
  • CacheEntry: Ein Cache-Eintrag, einschließlich des Cache-Namens, z. B. /tomcat.gif, der Ressource und der Ressourcenattribute sowie des entsprechenden Verzeichnisses

Die mit dem Ressourcenverzeichnis in Zusammenhang stehenden Klassen sind:

  • EmptyDirContext: Wird hauptsächlich im eingebetteten Modus verwendet und verhält sich, als ob keine Ressourcen verfügbar wären
  • FileDirContext: Dateisystembasierter Ressourcenverzeichnisdienst
  • WARDirContext: Verzeichnisdienst basierend auf War-Datei
  • Ressource: kapselt Ressourceninhalte, hauptsächlich Bytedaten und Eingabestream
  • ResourceAttributes: Ressourcenattribute, hauptsächlich Inhaltslänge und letzte Änderungszeit
  • ProxyDirContext: Ein Proxy für Ressourcen-Cache und Verzeichnisdienste, der Funktionen wie das Suchen des Ressourcen-Cache und die Überprüfung, ob der Cache abgelaufen ist, bereitstellt.

Standardmäßig beträgt die maximale Cachegröße 10 MB, die maximale Größe einer einzelnen zwischengespeicherten Ressource beträgt 512 KB und die Cache-TTL beträgt 5 Sekunden.

Wenn ein Mapper einem Wrapper zugeordnet wird, der statische Ressourcen verarbeitet, führt dies im Allgemeinen zum Laden von Ressourcen. Die grundlegenden Methodenaufrufe lauten wie folgt:

Mapper.map(MessageBytes, MessageBytes, MappingData)
└─Mapper.internalMap(CharChunk, CharChunk, MappingData)
 └─Mapper.internalMapWrapper(Mapper$Context, CharChunk, MappingData)
 └─ProxyDirContext.lookup(Zeichenfolge)
 └─ProxyDirContext.cacheLookup(Zeichenfolge)
 └─ResourceCache.lookup(Zeichenfolge)
  └─ResourceCache.find(CacheEntry[], String)

Cache-Ressourcen werden der Reihe nach in das interne Array eingefügt. Die Find-Methode führt eine binäre Suche im Cache nach Ressourcennamen durch, wobei der Ressourcenname der Anforderungspfad ist. Es gibt zwei Situationen: Cache-Treffer und Cache-Fehlschlag.

Wenn der Cache fehlt, wird in der Methode cacheLookup ein neues CacheEntry-Objekt erstellt und die Methode cacheLoad aufgerufen, um es dem Cache-Array von ResourceCache hinzuzufügen. Vor dem Hinzufügen werden die folgenden Vorgänge für den Cache-Eintrag ausgeführt:

  • Abrufen und Initialisieren der Cache-Ressourceneigenschaften, hauptsächlich contentLength und lastModified der Datei
  • Wenn die Dateilänge weniger als 512 KB beträgt, laden Sie den Dateiinhalt in den Speicher
  • Markieren Sie den Cache als vorhanden und legen Sie den Cache-Zeitstempel fest

Cache-Treffer verifizieren den Cache-Eintrag:

  • Überprüfen Sie, ob es abgelaufen ist und die aktuelle Zeit größer ist als der für den Cache-Eintrag festgelegte Zeitstempel
  • Wenn es abgelaufen ist, prüfen Sie, ob der Ressourceninhalt geändert wurde
  • Wenn geändert, diesen Cache leeren und den neuesten Inhalt lesen

Das Obige ist ein einfacher Verarbeitungsprozess der Ressourcen-Zwischenspeicherung.

2. Verarbeitung des If-Headerfeldes

Der Client empfängt und speichert die angeforderte Ressource im Cache. Wenn die Ressource erneut angefordert wird, überprüft der Server anhand des spezifischen Anforderungsheaderfelds, ob die Ressource geändert wurde. Wenn keine Änderung vorliegt, wird nur die Antwort „304 Not Modified“ zurückgegeben. Andernfalls wird der Inhalt der Ressource zurückgegeben, wodurch Bandbreite gespart wird.

Zur Ressourcenüberprüfung werden zwei Headerfelder verwendet: Last-Modified+If-Modified-Since und ETag+If-None-Match.

Last-Modified+If-Modified-Since, die Einheit ist Sekunden. Das ist leicht zu verstehen. Wenn die letzte Änderungszeit der Serverressource kleiner als der Wert von If-Modified-Since ist, bedeutet dies, dass sich die Ressource nicht geändert hat. If-Modified-Since entspricht If-Unmodified-Since, was einer Assertion ähnelt. Es werden nur Ressourcen mit einem Zeitstempel zurückgegeben, der kleiner als dieser ist. Wenn der Zeitstempel größer oder gleich diesem ist, wird ein Fehler 412 Precondition Failed zurückgegeben.

Die Verwendung der Zeitstempelvalidierung bringt mehrere Nachteile mit sich:

  • Die Datei kann nur den Änderungszeitpunkt ändern, der Inhalt bleibt jedoch unverändert
  • Dateien, die in weniger als einer Sekunde geändert wurden, können nicht beurteilt werden
  • Der Server kann den letzten Änderungszeitpunkt der Datei möglicherweise nicht genau ermitteln.

Aus diesem Grund hat HTTP ETag eingeführt. ETag (Entity Tags) ist eine eindeutige Kennung für eine Ressource, die als vom Server für die Ressource generiertes Token betrachtet und verwendet werden kann, um zu überprüfen, ob die Ressource geändert wurde. HTTP legt nur fest, dass ETag in Anführungszeichen gesetzt werden soll, schreibt aber nicht vor, was der Inhalt ist oder wie er implementiert werden soll. Tomcats Logik zum Generieren von ETag ist "W/\"" + contentLength + "-" + lastModified + "\"" , wobei "W/" Groß- und Kleinschreibung angibt.

ETag+If-None-Match. Der Wert von If-None-Match besteht aus einem oder mehreren durch Kommas getrennten ETags. Wenn der ETag der Serverressource keinem davon entspricht, bedeutet dies, dass die angeforderte Ressource geändert wurde; andernfalls gibt es keine Änderung. Es hat auch einen speziellen Wert – ein Sternchen (*), das nur beim Hochladen von Ressourcen verwendet wird, normalerweise bei der PUT-Methode, um zu überprüfen, ob sie hochgeladen wurden.

Darüber hinaus hat If-None-Match eine höhere Priorität als If-Modified-Since, d. h. wenn If-None-Match vorliegt, wird der letzte Änderungszeitpunkt nicht geprüft. Das Gegenteil von If-None-Match ist If-Match, das ebenfalls einer Assertion ähnelt. Es gilt nur dann als unverändert, wenn das ETag der Ressource übereinstimmt. Es wird normalerweise zum Fortsetzen von Haltepunkten verwendet.

Der Kerncode von Tomcat zur Implementierung dieses Teils lautet wie folgt:

//Gibt nur dann „true“ zurück, wenn die Ressource als geändert gilt protected boolean checkIfHeaders(HttpServletRequest request,
  HttpServletResponse-Antwort, ResourceAttributes resourceAttributes)
  wirft IOException {
 returniere checkIfMatch(Anfrage, Antwort, Ressourcenattribute)
  && checkIfModifiedSince(Anfrage, Antwort, Ressourcenattribute)
  && checkIfNoneMatch(Anfrage, Antwort, Ressourcenattribute)
  && checkIfUnmodifiedSince(Anfrage, Antwort, Ressourcenattribute);
}

2.1 Einmaliger Antragsprozess

Am Beispiel der Anforderung für die statische Ressource /main.css lauten die Header-Informationen der ersten Anforderungsantwort wie folgt:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Akzeptierte Bereiche: Bytes
ETag: W/"72259-1557127244000"
Letzte Änderung: Montag, 6. Mai 2019, 7:20:44 Uhr GMT
Inhaltstyp: Text/CSS
Inhaltslänge: 72259
Datum: Montag, 6. Mai 2019, 07:20:57 GMT

Wenn Sie die zweite Anfrage stellen, sehen Sie sich zunächst die Schlüsselinformationen im Header-Feld der Anfrage an:

Cache-Steuerung:max-age=0
Verbindung: Keep-Alive
Gastgeber:localhost:8080
Wenn geändert seit: Montag, 6. Mai 2019, 07:20:44 GMT
Wenn keine Übereinstimmung: Mit „72259-1557127244000“

Nach Erhalt der Anfrage vergleicht der Server das ETag. Wenn die Übereinstimmung erfolgreich ist, bedeutet dies, dass die Ressource nicht geändert wurde. Die Antwort lautet wie folgt:

HTTP/1.1 304 Nicht geändert
Server: Apache-Coyote/1.1
ETag: W/"72259-1557127244000"
Datum: Montag, 6. Mai 2019, 07:21:46 GMT

Hinweis: Verwenden Sie beim Reproduzieren den Texttyp. Wenn Sie den Chrome-Browser verwenden, denken Sie daran, den Cache zu aktivieren.

2.2 Akzeptanzbereiche

In der obigen Antwort setzt der Server einen Accept-Ranges: bytes-Header, was wörtlich bedeutet, dass ein Teil der Bytes der Ressource angefordert werden kann. Wenn der Client diesen Header findet, kann er versuchen, die Übertragung fortzusetzen.

Der Parsing-Prozess ist die Implementierung der HTTP-Spezifikation. Wir werden ihn hier nicht im Detail analysieren. Detaillierte Informationen zur Spezifikation finden Sie in RFC7233#section-2.3.

3. SendFile-Verarbeitung

Überprüfen Sie, ob SendFile unterstützt wird. Dieser Vorgang wird im NIO-Modus unterstützt, d. h. Zero Copy. Dieser Vorgang reduziert eine Kopie in den Anwendungsspeicher und schreibt Daten direkt vom Kernel in den Kanal. Tomcat versucht, mit dieser Methode Dateien zu senden, die größer als 48 KB sind.

4. Zusammenfassung

Die Implementierung der Verarbeitung statischer Ressourcen durch Tomcat ist relativ vollständig, steht jedoch Webservern wie Nginx immer noch etwas nach, da diese statische Ressourcen direkt verarbeiten können, während Tomcat eine zusätzliche Zuordnung vornehmen muss. Im Allgemeinen wird eine dynamische und statische Trennung vorgenommen, damit sich Tomcat auf die Verarbeitung dynamischer Anforderungen konzentrieren kann.

Zusammenfassen

Das Obige ist der vollständige Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels einen gewissen Lernwert für Ihr Studium oder Ihre Arbeit hat. Vielen Dank für Ihre Unterstützung von 123WORDPRESS.COM.

Das könnte Sie auch interessieren:
  • Lösung für Tomcats Fehler beim Laden statischer Ressourcendateien wie CSS und JS
  • Detaillierte Erläuterung von Nginx + Tomcat zum Trennen von Anforderungen für dynamische Daten und statische Ressourcen

<<:  Installationstutorial für MySQL 5.1 und 5.7 unter Linux

>>:  Detaillierte Erklärung der Hook-Funktion und -Nutzung im Lebenszyklus der neuen Version von React

Artikel empfehlen

Eine kurze Erläuterung des Lazy-Loading-Attributmusters in JavaScript

Inhaltsverzeichnis 1. Einleitung 2. On-Demand-Att...

So fügen Sie einer großen Datentabelle in MySQL Felder hinzu

Vorwort Ich glaube, jeder ist mit dem Hinzufügen ...

Detaillierte Einführung in den DOCTYPE-Typ

<br />Wir deklarieren DOCTYPE in HTML normal...

JavaScript-Lösung für die Setinterval-Verzögerung um eine Sekunde

Bei Verwendung von setinterval wird festgestellt,...

Realisieren Sie einen super coolen Wasserlichteffekt auf Leinwandbasis

In diesem Artikelbeispiel erfahren Sie den spezif...

Zusammenfassung der Berechtigungsprobleme bei gespeicherten MySQL-Prozeduren

Ja, gespeicherte MySQL-Prozeduren scheinen sehr s...

Beispiel, wie nginx dynamische und statische Trennung implementiert

Inhaltsverzeichnis Stellen Sie nginx auf Server1 ...

Erste Schritte mit Mysql - SQL-Ausführungsprozess

Inhaltsverzeichnis 1. Prozess 2. Kernarchitektur ...

Implementierung der ELK-Bereitstellungsmethode mit einem Klick in Docker Compose

Installieren Filebeat hat Logstash-Forwarder voll...

So löschen und deinstallieren Sie MySQL in Windows 10 vollständig

Vorwort Dieser Artikel enthält eine Anleitung zum...

Zusammenfassung der grundlegenden Wissenspunkte der Linux-Gruppe

1. Grundlegende Einführung in die Linux-Gruppe Un...

So ändern Sie die Standardübermittlungsmethode des Formulars

Die Standard-Übermittlungsmethode von HTML ist get...