Läuft Ihre J2EE-Anwendung langsam? Können sie dem steigenden Verkehr standhalten? In diesem Artikel wird die Leistungsoptimierungstechnologie für die Entwicklung leistungsstarker, hochelastischer JSP-Seiten und Servlets beschrieben. Die Idee besteht darin, so schnell wie möglich aufzubauen und sich an die wachsende Anzahl von Benutzern und deren Anforderungen anzupassen. In diesem Artikel führe ich Sie zum Erlernen praktischer und bewährter Techniken zur Leistungsoptimierung, die die Leistung Ihrer Servlets und JSP-Seiten erheblich verbessern und dadurch die Leistung von J2EE verbessern. Einige dieser Technologien werden in Entwicklungsphasen eingesetzt, beispielsweise in Entwurfs- und Codierungsphasen. Ein weiterer Teil der Technologie hängt mit der Konfiguration zusammen.
Technik 1: Zwischenspeichern von Daten in der HttpServletinit()-Methode
Der Server ruft die init()-Methode des Servlets auf, nachdem die Servlet-Instanz erstellt wurde und bevor das Servlet Anfragen verarbeitet. Diese Methode wird nur einmal im Lebenszyklus des Servlets aufgerufen. Um die Leistung zu verbessern, können Sie statische Daten in init() zwischenspeichern oder kostspielige Vorgänge während der Initialisierung ausführen. Eine bewährte Vorgehensweise besteht beispielsweise darin, einen JDBC-Verbindungspool zu verwenden, der die javax.sql.DataSource-Schnittstelle implementiert.
DataSource wird aus dem JNDI-Baum abgerufen. Die Verwendung von JNDI zum Auffinden der Datenquelle bei jedem SQL-Aufruf ist sehr kostspielig und beeinträchtigt die Leistung der Anwendung erheblich. Mit der init()-Methode des Servlets kann die DataSource abgerufen und zur späteren Wiederverwendung zwischengespeichert werden:
publicclassControllerServletextendsHttpServlet
{
privatejavax.sql.DataSourcetestDS=null;
publicvoidinit(ServletConfigconfig)throwsServletException
{
super.init(config);
Contextctx=null;
versuchen
{
ctx=newInitialContext();
testDS=(javax.sql.DataSource)ctx.lookup("jdbc/testDS");
}
Catch(NamingException)
{
ne.printStackTrace();
}
Catch(Ausnahme)
{
e.printStackTrace();
}
}
publicjavax.sql.DataSourcegetTestDS()
{
returntestDS;
}
...
...
}
Technik 2: Deaktivieren Sie die automatische Ladefunktion von Servlets und JSPs
. Sie müssen den Server jedes Mal neu starten, wenn Sie das Servlet/JSP ändern. Da die Funktion zum automatischen Laden die Entwicklungszeit verkürzt, wird diese Funktion während der Entwicklungsphase als sehr nützlich angesehen. Allerdings ist es in der Laufzeitphase sehr teuer; Servlet/JSP führt zu schlechter Leistung aufgrund unnötiger Belastung und erhöhter Belastung des Klassenladers. Auch dies kann zu seltsamen Konflikten in Ihrer Anwendung führen, da Klassen, die von einem bestimmten Klassenlader geladen wurden, nicht mit Klassen zusammenarbeiten können, die vom aktuellen Klassenlader geladen wurden. Um eine bessere Leistung in der laufenden Umgebung zu erzielen, deaktivieren Sie daher die automatische Ladefunktion von Servlet/JSP.
Technik 3: HttpSession steuern
Viele Anwendungen erfordern eine Reihe von Clientanfragen, damit sie miteinander verknüpft werden können. Da das HTTP-Protokoll zustandslos ist, müssen webbasierte Anwendungen für die Aufrechterhaltung eines solchen Zustands namens Sitzung verantwortlich sein. Um Anwendungen zu unterstützen, die ihren Zustand aufrechterhalten müssen, stellt die Javaservlet-Technologie APIs bereit, die Sitzungen verwalten und mehrere Mechanismen zur Implementierung von Sitzungen ermöglichen. Das HttpSession-Objekt fungiert als Sitzung, seine Verwendung ist jedoch mit Kosten verbunden. Immer wenn HttpSession verwendet und überschrieben wird, wird es vom Servlet gelesen. Sie können die Leistung verbessern, indem Sie die folgenden Techniken anwenden:
lErstellen Sie keine Standard-HttpSession auf der JSP-Seite: Standardmäßig erstellt die JSP-Seite eine HttpSession. Wenn Sie HttpSession nicht in Ihrer JSP-Seite verwenden, verwenden Sie zur Einsparung von Leistungsaufwand die folgenden Seitenanweisungen, um die automatische Erstellung von HttpSession-Objekten zu vermeiden:
< %@pagesession="false"% >
1) Speichern Sie keine großen Objektdiagramme in HttpSession: Wenn Sie Daten in HttpSession als großes Objektdiagramm speichern, muss der Anwendungsserver jedes Mal das gesamte HttpSession-Objekt verarbeiten. Dadurch wird die Java-Serialisierung erzwungen und der Rechenaufwand erhöht. Aufgrund des Overheads der Serialisierung nimmt der Durchsatz des Systems ab, wenn die im HttpSession-Objekt gespeicherten Datenobjekte zunehmen.
2) Geben Sie die HttpSession nach der Verwendung frei: Wenn die HttpSession nicht mehr verwendet wird, verwenden Sie die Methode HttpSession.invalidate(), um die Sitzung ungültig zu machen.
3) Legen Sie den Timeout-Wert fest: Eine Servlet-Engine verfügt über einen Standard-Timeout-Wert. Wenn Sie die Sitzung nicht löschen oder die Sitzung nicht weiter verwenden, bis das Zeitlimit überschritten wird, löscht die Servlet-Engine die Sitzung aus dem Speicher. Aufgrund des Overheads im Arbeitsspeicher und der Garbage Collection ist die Auswirkung auf die Ausfallsicherheit und Leistung des Systems umso größer, je höher der Wert für das Sitzungszeitlimit ist. Versuchen Sie, den Sitzungszeitüberschreitungswert so niedrig wie möglich festzulegen.
Technik 4: Verwenden Sie die gzip-Komprimierung.
Bei der Komprimierung werden redundante Informationen entfernt und Ihre Informationen auf möglichst kleinem Raum beschrieben. Durch die Verwendung von gzip (GNUzip) zum Komprimieren von Dokumenten kann die Zeit für das Herunterladen von HTML-Dateien effektiv verkürzt werden. Je kleiner Ihre Nachrichten sind, desto schneller werden sie gesendet. Wenn Sie also den von Ihrer Webanwendung generierten Inhalt komprimieren, erreicht er den Benutzer umso schneller und wird auf dem Bildschirm des Benutzers angezeigt. Nicht jeder Browser unterstützt die GZIP-Komprimierung, aber es ist einfach zu überprüfen, ob ein Browser sie unterstützt, und GZIP-komprimierte Inhalte an den Browser zu senden. Der folgende Codeausschnitt veranschaulicht, wie komprimierte Inhalte gesendet werden.
publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
throwsIOException,ServletException
{
OutputStreamout=null
//Überprüfen Sie den Header „Accepting-Encoding“ aus der HTTP-Anfrage.
//Wenn der Header gzip enthält, wählen Sie GZIP.
//Wenn der Header „compress“ enthält, wählen Sie „ZIP“.
//Otherwisechoosenocompression.
Stringencoding=request.getHeader("Accept-Encoding");
if(encoding!=null&&encoding.indexOf("gzip")!=-1)
{
Response.setHeader("Content-Encoding","gzip");
out=newGZIPOutputStream(response.getOutputStream());
}
elseif(encoding!=null&&encoding.indexOf("compress")!=-1)
{
Response.setHeader("Content-Encoding","compress");
out=newZIPOutputStream(response.getOutputStream());
}
anders
{
out=response.getOutputStream(
}
...
...
}
Technik 5: SingleThreadModel nicht verwenden
SingleThreadModel garantiert, dass das Servlet jeweils nur eine Anfrage verarbeitet. Wenn ein Servlet diese Schnittstelle implementiert, erstellt die Servlet-Engine für jede neue Anfrage eine separate Servlet-Instanz, was einen hohen Systemaufwand verursacht. Wenn Sie Thread-Sicherheitsprobleme lösen müssen, verwenden Sie bitte andere Methoden anstelle dieser Schnittstelle. Die Verwendung von SingleThreadModel wird in Servlet2.4 nicht mehr empfohlen.
Technik 6: Verwenden Sie die Thread-Pool
-Servlet-Engine, um für jede Anforderung einen separaten Thread zu erstellen, weisen Sie den Thread der service()-Methode zu und löschen Sie den Thread, nachdem die service()-Methode ausgeführt wurde. Standardmäßig erstellt die Servlet-Engine möglicherweise einen neuen Thread für jede Anfrage. Da das Erstellen und Löschen von Threads teuer ist, verringert dieses Standardverhalten die Systemleistung. Wir können den Thread-Pool verwenden, um die Leistung zu verbessern. Konfigurieren Sie entsprechend der erwarteten Anzahl gleichzeitiger Benutzer einen Thread-Pool und legen Sie die minimale und maximale Anzahl von Threads im Thread-Pool sowie die minimalen und maximalen Wachstumswerte fest. Zunächst erstellt die Servlet-Engine einen Thread-Pool mit einer Anzahl von Threads, die der Mindestanzahl von Threads in der Konfiguration entspricht. Die Servlet-Engine weist dann einer Anfrage einen Thread aus dem Pool zu, anstatt jedes Mal einen neuen Thread zu erstellen. Nach Abschluss des Vorgangs fügt die Servlet-Engine den Thread wieder in den Thread-Pool ein. Durch den Einsatz von Thread-Pools kann die Leistung deutlich verbessert werden. Bei Bedarf können basierend auf der maximalen Anzahl von Threads und der Anzahl des Wachstums weitere Threads erstellt werden.
Technik 7: Wählen Sie den richtigen Einschlussmechanismus
. In JSP-Seiten gibt es zwei Möglichkeiten, Dateien einzuschließen: Anweisungen einschließen (< %@includefile="test.jsp"% >) und Aktionen einschließen (<jsp:includepage="test.jsp " bündig="true"/>). Die Include-Direktive schließt den Inhalt einer angegebenen Datei während der Kompilierungsphase ein, beispielsweise wenn eine Seite in ein Servlet kompiliert wird. Eine Einschlussaktion umfasst das Einschließen von Dateiinhalten während der Anforderungsphase, beispielsweise wenn ein Benutzer eine Seite anfordert. Das Einbinden von Anweisungen geht schneller als das Einbinden von Aktionen. Sofern sich die eingebundenen Dateien nicht häufig ändern, erzielen Sie daher eine bessere Leistung, wenn Sie die Include-Direktive verwenden.
Technik 8: Verwenden Sie geeignete Bereiche in useBean-Aktionen.
Eine der leistungsstärksten Möglichkeiten, JSP-Seiten zu verwenden, ist die Arbeit mit JavaBean-Komponenten. JavaBeans können mithilfe des <jsp:useBean>-Tags in JSP-Seiten eingebettet werden. Die Syntax lautet wie folgt:
<jsp:useBeanid="name"scope="page|request|session|application"class=
"package.className"type="typeName">
</jsp:useBean>
Das Bereichsattribut beschreibt den sichtbaren Bereich der Bean. Der Standardwert des Bereichsattributs ist Seite. Sie sollten den richtigen Bereich basierend auf den Anforderungen Ihrer Anwendung auswählen, da dies sonst die Leistung Ihrer Anwendung beeinträchtigt.
Wenn Sie beispielsweise ein spezifisches Objekt für eine bestimmte Anforderung benötigen, den Bereich jedoch auf „Sitzung“ festlegen, verbleibt dieses Objekt im Speicher, nachdem die Anforderung beendet ist. Es bleibt im Speicher, es sei denn, Sie löschen es explizit aus dem Speicher, machen die Sitzung ungültig oder die Sitzung läuft ab. Wenn Sie nicht das richtige Bereichsattribut auswählen, wird die Leistung aufgrund des Speicher- und Garbage-Collection-Overheads beeinträchtigt. Legen Sie also einen geeigneten Bereich für Objekte fest und löschen Sie sie, sobald Sie damit fertig sind.
Verschiedene Techniken
1) Vermeiden Sie die Verkettung von Zeichenfolgen: Da Zeichenfolgenobjekte unveränderliche Objekte sind, führt die Verwendung des „+“-Operators zur Erstellung einer großen Anzahl von Nullzeitobjekten. Je mehr „+“ Sie verwenden, desto mehr Nullzeitobjekte werden generiert, was sich auf die Leistung auswirkt. Wenn Sie Zeichenfolgen verketten müssen, verwenden Sie StringBuffer anstelle der Operation „+“.
2) Vermeiden Sie die Verwendung von System.out.println: System.out.println verarbeitet die Festplatteneingabe/-ausgabe synchron, was den Systemdurchsatz erheblich verringert. Vermeiden Sie nach Möglichkeit die Verwendung von System.out.println. Obwohl viele ausgereifte Debugging-Tools verfügbar sind, ist System.out.println manchmal immer noch nützlich für Ablaufverfolgungs- oder Debugging-Zwecke. Sie sollten System.out.println so konfigurieren, dass es nur während Fehler- und Debugging-Phasen geöffnet wird. Wenn eine finalBoolean-Variable auf „false“ konfiguriert ist, werden Optimierungsprüfungen und Ausführungs-Trace-Ausgaben während der Kompilierungsphase abgeschlossen.
3) Vergleich von ServletOutputStream und PrintWriter: Aufgrund des Zeichenausgabestroms und der Kodierung von Daten in Bytes führt die Verwendung von PrintWriter zu einem geringen Leistungsaufwand. Daher sollte PrintWriter verwendet werden, nachdem alle Zeichensatzkonvertierungen korrekt durchgeführt wurden. Wenn Sie andererseits wissen, dass Ihr Servlet nur Binärdaten zurückgibt, verwenden Sie ServletOutputStream, da der Servlet-Container keine Binärdaten codiert, sodass Sie den Aufwand für die Zeichensatzkonvertierung eliminieren.
Zusammenfassung
Der Zweck dieses Artikels besteht darin, Ihnen einige praktische und bewährte Techniken zur Leistungsoptimierung zur Verbesserung der Servlet- und JSP-Leistung vorzustellen, die die Gesamtleistung Ihrer J2EE-Anwendungen verbessern. Der nächste Schritt sollte darin bestehen, die Leistungsoptimierung anderer verwandter Technologien wie EJB, JMS und JDBC zu beobachten.