Analysieren Sie das Arbeitsprinzip von Tomcat

Analysieren Sie das Arbeitsprinzip von Tomcat

SpringBoot ist wie eine riesige Python, die sich langsam um uns windet und uns lähmt. Ich muss zugeben, dass die Verwendung von SpringBoot tatsächlich die Arbeitseffizienz verbessert hat, gleichzeitig aber auch dazu geführt hat, dass wir viele Fähigkeiten vergessen haben. Als ich zum ersten Mal in die Gesellschaft eintrat, habe ich Java-Webprojekte noch manuell über Tomcat bereitgestellt und häufig Leistungsoptimierungen an Tomcat durchgeführt. Darüber hinaus müssen Sie auch die Beziehung zwischen den verschiedenen Jars klären, um Probleme wie Jar-Verlust und Versionskonflikte zu vermeiden, die zu Ausnahmen beim Dienststart führen können. Jetzt werden all diese langwierigen und sich wiederholenden Aufgaben von SpringBoot übernommen und wir können uns mehr auf die Geschäftslogik konzentrieren. Allerdings ist es genauso wichtig, das Arbeitsprinzip und den Anforderungsverarbeitungsablauf von Tomcat zu verstehen, wie den Quellcode des Spring-Frameworks zu analysieren. Zumindest fragen Interviewer besonders gerne nach diesen Grundprinzipien und Designideen. Ich hoffe, dieser Artikel kann Ihnen weiterhelfen.

Tomcat-Gesamtarchitektur

Tomcat ist ein kostenloser, Open Source und leichtgewichtiger Web-Anwendungsserver. Es eignet sich für den Einsatz in kleinen und mittelgroßen Unternehmensprojekten, bei denen die Parallelität nicht sehr hoch ist.

Dateiverzeichnisstruktur

Nachfolgend sehen Sie die Hauptverzeichnisstruktur von Tomcat 8

Inhaltsverzeichnis Funktionsbeschreibung
bin Speichert ausführbare Dateien, wie Start- und Herunterfahren
Konf Speichert Konfigurationsdateien, wie die Kernkonfigurationsdatei server.xml und die Standard-Bereitstellungsdeskriptordatei der Anwendung web.xml
Bibliothek Speichern Sie die für die Ausführung von Tomcat erforderlichen JAR-Pakete
Protokolle Speichert die laufenden Logdateien
Webanwendungen Speichert das Standardverzeichnis für die Bereitstellung von Webanwendungen
arbeiten Temporäres Verzeichnis zum Speichern der Codegenerierung und kompilierter Dateien für Webanwendungen

Funktionale Komponentenstruktur

Tomcat hat zwei Kernfunktionen: den Connector, der für den Empfang und die Beantwortung externer Anfragen zuständig ist, und den Container, der für die Verarbeitung der Anfragen zuständig ist. Connector und Container ergänzen sich und bilden gemeinsam den grundlegenden Webservice. Jeder Tomcat-Server kann mehrere Dienste verwalten.

Komponenten Funktion
Konnektor Verantwortlich für den Empfang externer Feedbackanfragen. Es ist der Transportknotenpunkt zwischen Tomcat und der Außenwelt. Es überwacht den Port, um externe Anforderungen zu empfangen, übergibt die verarbeiteten Anforderungen zur Geschäftsverarbeitung an den Container und gibt schließlich die Ergebnisse der Containerverarbeitung an die Außenwelt zurück.
Container Verantwortlich für die interne Verarbeitung der Geschäftslogik. Es besteht aus vier Containern: Engine, Host, Context und Wrapper, die zum Verwalten und Aufrufen der Servlet-bezogenen Logik verwendet werden.
Service Für die Außenwelt bereitgestellte Webdienste. Es umfasst im Wesentlichen zwei Kernkomponenten: Konnektor und Container sowie weitere Funktionskomponenten. Tomcat kann mehrere Dienste verwalten und jeder Dienst ist unabhängig von den anderen.

Kernprinzip des Tomcat-Konnektors

Tomcat Connector Framework - Coyote

Connector-Kernfunktionen

1. Netzwerkports abhören, Netzwerkanforderungen empfangen und beantworten.

2. Netzwerk-Bytestream-Verarbeitung. Konvertieren Sie den empfangenen Netzwerk-Bytestream in eine Tomcat-Anfrage und dann in eine Standard-Servlet-Anfrage an den Container. Konvertieren Sie gleichzeitig die vom Container gesendete Servlet-Antwort in eine Tomcat-Antwort und dann in einen Netzwerk-Bytestream.

Design des Anschlussmoduls

Um die beiden Kernfunktionen des Connectors zu erfüllen, benötigen wir einen Kommunikationsendpunkt, der den Port abhört, einen Prozessor, der den Netzwerk-Bytestream verarbeitet und schließlich einen Adapter, der die verarbeiteten Ergebnisse in die vom Container benötigte Struktur konvertiert.

Komponenten Funktion
Endpunkt Endpunkt, der zum Handhaben der Logik des Socket-Empfangens und -Sendens verwendet wird. Intern wartet Acceptor auf Anfragen, Handler verarbeitet Daten und AsyncTimeout überprüft das Anfrage-Timeout. Spezifische Implementierungen umfassen NioEndPoint, AprEndpoint usw.
Prozessor Prozessor, der für das Erstellen von Tomcat-Anforderungs- und Antwortobjekten verantwortlich ist. Spezifische Implementierungen umfassen Http11Processor, StreamProcessor usw.
Adapter Adapter, der die Konvertierung zwischen Tomcat Request, Response und ServletRequest, ServletResponse realisiert. Dabei wird das klassische Adapter-Entwurfsmuster verwendet.
ProtokollHandler Der Protokollprozessor kombiniert verschiedene Protokolle und Kommunikationsmethoden in entsprechenden Protokollprozessoren. Beispielsweise kapselt Http11NioProtocol HTTP + NIO.

Der entsprechende Quellpaketpfad ist org.apache.coyote . Das entsprechende Strukturdiagramm sieht wie folgt aus

Kernprinzip des Tomcat-Containers

Tomcat-Container-Framework – Catalina

Behälterstrukturanalyse

Jeder Dienst enthält einen Container. Eine Container-Engine kann mehrere virtuelle Hosts verwalten. Jeder virtuelle Host kann mehrere Webanwendungen verwalten. Jede Webanwendung verfügt über mehrere Servlet-Wrapper. Die vier Container Engine, Host, Context und Wrapper stehen in einer Eltern-Kind-Beziehung.

Container Funktion
Motor Engine, verwaltet mehrere virtuelle Hosts.
Gastgeber Virtueller Host, verantwortlich für die Bereitstellung von Webanwendungen.
Kontext Webanwendung, einschließlich mehrerer Servlet-Wrapper.
Verpackung Hülle, die unterste Schicht des Behälters. Kapselt Servlets ein und ist für die Erstellung, Ausführung und Zerstörung von Instanzen verantwortlich.

Der entsprechende Quellpaketpfad ist org.apache.coyote . Das entsprechende Strukturdiagramm sieht wie folgt aus

Containeranforderungsverarbeitung

Der Anforderungsverarbeitungsprozess des Containers besteht darin, die vier Container Engine, Host, Context und Wrapper Schicht für Schicht aufzurufen und schließlich die entsprechende Geschäftslogik im Servlet auszuführen. Jeder Container verfügt über eine Kanalpipeline und jeder Kanal über ein Basisventil (z. B. StandardEngineValve), das einem Gate ähnelt, das zum Verarbeiten von Anforderungen und Antworten verwendet wird. Das Flussdiagramm ist wie folgt.

Ablauf der Tomcat-Anforderungsverarbeitung

Die oben genannten Wissenspunkte haben Stück für Stück vorgestellt, wie ein Tomcat eine Anfrage verarbeitet. Einfach ausgedrückt: Der Verarbeitungsfluss des Connectors + der Verarbeitungsfluss des Containers = der Verarbeitungsfluss von Tomcat. Ha! Die Frage ist also, wie findet Tomcat die entsprechende virtuelle Site über den Anforderungspfad? Wie finde ich das entsprechende Servlet?

Einführung in die Mapper-Funktion

Hier müssen wir einen Komponenten-Mapper einführen, der oben nicht vorgestellt wurde. Wie der Name schon sagt, besteht seine Aufgabe darin, eine Routing-Zuordnung für den Anforderungspfad bereitzustellen. Die Anforderungs-URL wird abgeglichen, um zu bestimmen, welcher Container den Abgleich durchführt. Jeder Container hat seinen eigenen entsprechenden Mapper, beispielsweise MappedHost. Ich frage mich, ob Sie sich jemals an die Angst erinnert haben, von einer nicht gefundenen Mapper-Klasse dominiert zu werden. Früher mussten Sie jedes Mal, wenn Sie eine vollständige Funktion geschrieben haben, die Zuordnungsregeln in web.xml konfigurieren. Mit zunehmender Größe der Datei traten verschiedene Probleme auf.

HTTP-Anforderungsprozess

Öffnen Sie die Datei server.xml im Verzeichnis tomcat/conf, um eine http://localhost:8080/docs/api-Anfrage zu analysieren.

Schritt 1: Der Connector lauscht auf Port 8080. Da der angeforderte Port und der Abhörport identisch sind, akzeptiert der Connector die Anforderung.

Schritt 2: Weil der standardmäßige virtuelle Host der Engine „localhost“ ist und das Verzeichnis des virtuellen Hosts „webapps“ ist. Die Anfrage hat also das Verzeichnis tomcat/webapps gefunden.

Schritt 3: Die analysierten Dokumente sind der Anwendungsname des Webprogramms, also der Kontext. Zu diesem Zeitpunkt sucht die Anforderung weiterhin nach dem Verzeichnis „Docs“ im Verzeichnis „Webapps“. Manchmal lassen wir auch den Anwendungsnamen weg.

Schritt 4: Die analysierte API ist die spezifische Geschäftslogikadresse. Zu diesem Zeitpunkt müssen Sie die Zuordnungsbeziehung in docs/WEB-INF/web.xml finden und schließlich die spezifische Funktion aufrufen.

<?xml version="1.0" encoding="UTF-8"?>
<Server-Port="8005" shutdown="HERUNTERFAHREN">

 <Dienstname="Catalina">

	<!-- Der Abhörport des Connectors ist 8080 und das Standardkommunikationsprotokoll ist HTTP/1.1 -->
 <Anschlussport="8080" Protokoll="HTTP/1.1"
  VerbindungsTimeout="20000"
  UmleitungsPort="8443" />
			 
	<!-- Der standardmäßige virtuelle Host für die Engine mit dem Namen Catalina ist localhost -->
 <Engine-Name="Catalina" Standardhost="localhost">

	 <!-- Ein virtueller Host namens localhost, dessen Verzeichnis webapps ist-->
 <Hostname="localhost" appBase="webapps"
  unpackWARs="true" autoDeploy="true">

 </Host>
 </Engine>
 </Dienst>
</Server> 

So starten Sie den eingebetteten Tomcat in SpringBoot

Die Ein-Klick-Dienststartfunktion von SpringBoot lässt viele Freunde, die gerade erst in die Gesellschaft eingetreten sind, vergessen, was Tomcat ist. Da die Hardwareleistung immer höher wird, können gewöhnliche kleine und mittelgroße Projekte direkt mit dem integrierten Tomcat gestartet werden. Für einige größere Projekte sind jedoch möglicherweise Tomcat-Clustering und -Optimierung erforderlich, und der integrierte Tomcat kann diese Anforderungen möglicherweise nicht erfüllen.

Lassen Sie uns zunächst analysieren, wie SpringBoot Tomcat aus dem Quellcode startet. Nachfolgend sehen Sie den Code für SpringBoot 2.x.

Der Code beginnt mit der Hauptmethode und führt die Run-Methode aus, um das Projekt zu starten.

SpringApplication.run

Klicken Sie auf die Ausführungsmethode und suchen Sie die Methode zum Aktualisieren des Anwendungskontexts.

this.prepareContext(Kontext, Umgebung, Listener, Anwendungsargumente, gedrucktes Banner);
dies.refreshContext(Kontext);
dies.afterRefresh(Kontext, Anwendungsargumente);

Klicken Sie auf die Methode „refreshContext“ und suchen Sie die Aktualisierungsmethode. Und suchen Sie Schicht für Schicht nach oben, um die Methode der übergeordneten Klasse zu finden.

dies.aktualisieren(Kontext);

In der Aktualisierungsmethode der Klasse AbstractApplicationContext gibt es eine Logikzeile, die den untergeordneten Container zum Aktualisieren aufruft.

dies.postProcessBeanFactory(beanFactory);
dies.invokeBeanFactoryPostProcessors(beanFactory);
dies.registerBeanPostProcessors(beanFactory);
dies.initMessageSource();
this.initApplicationEventMulticaster();
dies.onRefresh();
dies.registerListeners();
Dies.finishBeanFactoryInitialization(beanFactory);
dies.finishRefresh();

Klicken Sie auf die Methode onRefresh und suchen Sie die Implementierungsmethode von ServletWebServerApplicationContext. Hier sehe ich endlich Hoffnung.

geschützt void onRefresh() {
 super.onRefresh();

 versuchen {
 dies.createWebServer();
 } Fang (Throwable var2) {
 throw new ApplicationContextException("Webserver konnte nicht gestartet werden", var2);
 }
}

Klicken Sie auf die Methode „createWebServer“ und suchen Sie den Code zum Abrufen des WebServers aus der Factory-Klasse.

wenn (webServer == null und servletContext == null) {
 ServletWebServerFactory-Fabrik = this.getWebServerFactory();
 // Den Webserver abrufen 
 this.webServer = factory.getWebServer(neuer ServletContextInitializer[]{this.getSelfInitializer()});
} sonst wenn (ServletContext != null) {
 versuchen {
 // Starten Sie den Webserver
 this.getSelfInitializer().onStartup(servletContext);
 } Fang (ServletException var4) {
 throw new ApplicationContextException("Servlet-Kontext kann nicht initialisiert werden", var4);
 }
}

Klicken Sie auf die Methode getWebServer und suchen Sie die Implementierungsmethode von TomcatServletWebServerFactory, die auch Jetty und Undertow enthält. Hier werden grundlegende Konnektoren, Engines, virtuelle Sites usw. konfiguriert.

öffentlicher WebServer getWebServer(ServletContextInitializer... Initialisierer) {
 Tomcat Tomcat = neuer Tomcat();
 Datei baseDir = this.baseDirectory != null ? this.baseDirectory : this.createTempDir("tomcat");
 tomcat.setBaseDir(baseDir.getAbsolutePath());
 Connector-Connector = neuer Connector (dieses Protokoll);
 tomcat.getService().addConnector(Anschluss);
 this.customizeConnector(Anschluss);
 tomcat.setConnector(Anschluss);
 tomcat.getHost().setAutoDeploy(false);
 dies.configureEngine(tomcat.getEngine());
 Iterator var5 = this.additionalTomcatConnectors.iterator();

 während(var5.hasNext()) {
 Konnektor zusätzlicherKonnektor = (Konnektor)var5.next();
 tomcat.getService().addConnector(zusätzlicherConnector);
 }

 this.prepareContext(tomcat.getHost(), Initialisierer);
 gib dies zurück.getTomcatWebServer(tomcat);
} 

Nach dem Start des Dienstes wird das Protokoll ausgedruckt

osbwembedded.tomcat.TomcatWebServer: Tomcat initialisiert mit Port(s): 8900 (http)
o.apache.catalina.core.StandardService: Dienst wird gestartet [Tomcat]
org.apache.catalina.core.StandardEngine: Servlet-Engine wird gestartet: Apache Tomcat/8.5.34
oacatalina.core.AprLifecycleListener: Die auf APR basierende Apache Tomcat Native-Bibliothek, die optimale ... ermöglicht.
oaccC[Tomcat].[localhost].[/] : Initialisierung des in Spring eingebetteten WebApplicationContext
osweb.context.ContextLoader: Root WebApplicationContext: Initialisierung in 16858 ms abgeschlossen

ENDE

Der Artikel endet hier. Ich kann es wirklich nicht länger zurückhalten. Ich habe das ganze Wochenende lang geschrieben und bin immer noch nicht zum Quellcodeteil gekommen. Ich kann ihn nur in das nächste Kapitel schreiben. Wenn ich es noch einmal schreibe, ist es nutzlos. Bitte weisen Sie mich darauf hin, wenn etwas falsch ist.

Oben finden Sie detaillierte Informationen zur Funktionsweise von Tomcat. Weitere Informationen zum Funktionsprinzip von Tomcat finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • Detaillierte Erläuterung der Tomcat-Kernkomponenten und der Anwendungsarchitektur
  • Detaillierte Erläuterung des Startprinzips des in SpringBoot integrierten Tomcat
  • Tomcat analysiert XML und erstellt Objekte durch Reflektion
  • Detaillierte Analyse des Startup.bat-Prinzips in Tomcat
  • Detaillierte Analyse des catalina.bat-Prinzips in Tomcat
  • Einführung in die Prinzipien, Konfiguration und Verwendung von Tomcat-Datenquellen
  • Detaillierte Erläuterung des Implementierungsprinzips der Tomcat-Hot-Bereitstellung
  • Analysieren Sie die Prinzipien der Tomcat-Architektur für den Architekturentwurf

<<:  Der Unterschied und die Verwendung des Kommunikationsbusses der Bruderkomponenten von Vue2 und Vue3

>>:  Warum die Tabellendateigröße nach dem Löschen von Daten in MySQL unverändert bleibt

Artikel empfehlen

Vertieftes Verständnis davon in JavaScript

Vertieftes Verständnis davon in Js JavaScript Ber...

Beispielcode zum Erzielen eines Aushöhlungseffekts mit reinem CSS

Ich habe kürzlich den Aushöhlungseffekt untersuch...

border-radius ist eine Methode zum Hinzufügen abgerundeter Ränder zu Elementen

border-radius:10px; /* Alle Ecken sind mit einem ...

Implementierungscode zum Betreiben einer MySQL-Datenbank in Golang

Vorwort Golang stellt das Datenbank-/SQL-Paket fü...

Installieren Sie MySQL 5.7.18 mit dem RPM-Paket unter CentOS 7

Ich habe kürzlich MySQL verwendet. Im Artikel „My...

Detaillierte Erläuterung der Verwendung der Vue3-Statusverwaltung

Inhaltsverzeichnis Hintergrund Bereitstellen / In...

So ändern Sie die inländische Quelle von Ubuntu 20.04 apt

UPD 2020.2.26 Derzeit ist Ubuntu 20.04 LTS noch n...

So erhalten Sie Datums-/Uhrzeitdaten in MySQL, gefolgt von .0

Der Datentyp von MySQL ist datetime. Die in der D...

Detaillierte Erklärung des MySQL-Covering-Index

Konzept Wenn der Index alle Daten enthält, die di...