Java Servlet Cache + Cache-Management

Sekundentakt

Bekanntes Mitglied
Hallo Gemeinde,

leider erhielt ich in einer anderen Community keine Antwort auf meine Frage, daher probiere ich es mal hier.
Nachdem ich mir ein Buch zu JavaEE besorgt habe und dort keine entsprechenden Antworten fand, frage ich noch mal hier:

Wie realisiert man einen Cache in einem Servlet?

Hintergrund:
Es gibt Dateien oder Datenbankeinträge, die vom Servlet zur Erfüllung seiner Aufgabe benötigt werden. Es ist dabei aber nicht zwingend notwendig, dass die bis auf die Millisekunde aktuell sind.
Ich habe nun die Idee eines Heartbeats: Alle x Minuten fülle ich eine HashMap mit den neuesten Daten an.
Die Methoden des Servlets greifen dabei auf diese zurück. Datenbankanfragen oder ständiges Datei-parsen fällt weg.

Meine Frage ist jetzt allerdings: Wie greife ich darauf am besten (und saubersten) zu.

Gesetz dem Fall ich habe ein komplexes Projekt mit hunderten Klassen. Ich möchte, dass ich von jeder dieser Klassen aus die theoretische Möglichkeit habe, auf den Cache zuzugreifen, der die Daten vorhält.

Wenn ich den Cache jetzt als einfache Variable meines Servlets abspeichere, kann ich darauf aber nicht mehr zugreifen.
Gut, ich könnte die HashMap als Variable des Servlets angeben und diese dem Konstruktor von bestimmten Request-Handler-Objekten mitgeben. Dann wäre das Ganze gekapselt.

Aber ist das wirklich Best Practice?

Wohlbemerkt: Wir reden hier nicht von einem HTML-Cache. Das ist zwar ein interessantes Thema, da man sich dann die Arbeit erspart, den Request überhaupt komplett durchzuarbeiten, sondern das Ergebnis sofort liefern kann - aber hier geht es wirklich um einen Cache, der Daten aus Dateien oder Datenbanken rausholt und für die eigene Arbeit vorhält.

Cache-Events
Was mich auch noch interessiert, ist, ob ich ein Objekt dazu zwingen kann, nach einer bestimmten Zeit automatisch eine Methode aufzurufen. Also das z.B. alle 30 Sekunden im Cache überprüft wird, ob die gecachten Daten nicht schon zu alt sind oder etwas Ähnliches. Bisher habe ich noch nirgends etwas zu so einem objektinternen Micromanagement finden können.

Danke!

Beste Grüße
 
Wie kommst du denn zur Zeit an die Daten aus den Files/der Datenbank?
Wenn du das über eine eigene Repository/DAO Klasse machst, wäre es wohl ideal den Cache dort einzubauen. Da alle Klassen deiner Applikation über dieses Repository/DAO gehen müssen, wäre der Cache auch für alle gültig.
 
Wie kommst du denn zur Zeit an die Daten aus den Files/der Datenbank?
Gar nicht. Bevor ich anfange ein etwas komplexeres Projekt in JavaEE zu implementieren, wollte ich mich erst mal mit der Architektur beschäftigen. Es handelt sich um das erste Projekt im JavaEE-Bereich und da hielt ich es eher für angebracht, nicht einfach drauf los zu coden.

Wenn du das über eine eigene Repository/DAO Klasse machst, wäre es wohl ideal den Cache dort einzubauen.
Das DAO müsste dann aber gemeinsam mit dem Servlet initialisiert werden und diesem als Variable zur Verfügung stehen, richtig?
 
Gar nicht. Bevor ich anfange ein etwas komplexeres Projekt in JavaEE zu implementieren, wollte ich mich erst mal mit der Architektur beschäftigen. Es handelt sich um das erste Projekt im JavaEE-Bereich und da hielt ich es eher für angebracht, nicht einfach drauf los zu coden.
Warum willst du die Daten überhaupt im RAM haben? Wegen der Geschwindigkeit? Die meisten DMBS unterstützen dies schon von Haus aus, d.h. dass sie alle Daten zur Laufzeit im RAM lassen können wenn du es ihnen sagst.

Das DAO müsste dann aber gemeinsam mit dem Servlet initialisiert werden und diesem als Variable zur Verfügung stehen, richtig?
Ein Singleton, das im Speicher bleibt, ja.
 
Singleton = Jein

Normal würde man das DAO in alle benötigten Webseiten/Controller injizieren. Wie das genau geht hängt dann wieder vom eingesetzten DI Framework bzw. Webframework ab.

Ansonsten gibt es für das Caching auch bereits fertige Libraries wie z.B. Performance at Any Scale die man dann innerhalb des DAOs nutzen kann.
 
Warum willst du die Daten überhaupt im RAM haben? Wegen der Geschwindigkeit? Die meisten DMBS unterstützen dies schon von Haus aus, d.h. dass sie alle Daten zur Laufzeit im RAM lassen können wenn du es ihnen sagst.
Das ist wahr. Allerdings ist es so, dass ein User teilweise 2-3 Requests pro Sekunde an eine Web-Schnittstelle sendet. Ich möchte in diesem Falle einfach die ständigen Zugriffe auf die Datenbank unterbinden (Öffnen und Schließen der Verbindung etc.) und einfach in einem Cache nachschauen, ob die fragende IP mit dem gesendeten Kennwort und Usernamen bereits als authorisiert anerkannt worden ist. Falls dies nicht der Fall sein sollte, schaue ich in der Datenbank nach.

Das ist aber nur ein sehr kleiner Anwendungsbereich für den Cache.
Der Haupt-Anwendungsbereich läge darin, Entscheidungen auf Basis der hereinkommenden Requests zu speichern, um anschließend Requests an andere Teil-Programme durchzuführen.
Dadurch spare ich mir dann, die Entscheidungen jedesmal erneut zu treffen.
Die Arbeit die ich mir dabei spare ist zwar (erstmal) nur marginal, aber so weiß ich zumindest wie das Grundprinzip funktioniert und kann darauf aufbauen.

Ein Singleton, das im Speicher bleibt, ja.
Ich meine eher sowas:

Java:
public class myServlet extends HttpServlet 
{
    Map<String, String> cache;
    ...

    //irgendwo in einer Methode, ob nun init() oder woanders...
    {
           cache = new HashMap<String, String>();
    }

    //ein RequestHandler soll in einer anderen Methode auf den cache zugreifen können:
    {
          RequestHandler rh = new RequestHandler(cache, request);
    }
}

Normal würde man das DAO in alle benötigten Webseiten/Controller injizieren. Wie das genau geht hängt dann wieder vom eingesetzten DI Framework bzw. Webframework ab.
Nun, mein Servlet soll keine Webseiten füllen, sondern letzten Endes nur einen XML-Response zurückgeben. No Big Deal. Ich glaube nicht, dass ich solche Frameworks dann brauche?

Ansonsten gibt es für das Caching auch bereits fertige Libraries wie z.B. Performance at Any Scale die man dann innerhalb des DAOs nutzen kann.
Das klingt interessant. Hast Du damit selbst auch schon Erfahrungen gemacht?
 
Zuletzt bearbeitet:
Erfahrungen mit einem Cache leider noch nicht.

Bezüglich des Frameworks, auch wenn du "nur" XML-Responses zurück gibst, würde ich dir zumindest zu einem DI-Framework (Spring, Guice, EJB3) raten, da hierdurch deine Gesamtarchitektur wartbarer und besser testbar wird. Dein Servlet sähe dann z.B. so aus

Java:
public class MyServlet extends HttpServlet {
    @EJB
    private DAO dao;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ...
        List<Things> things = dao.getAllThings(); // Das DAO guckt erst in den Cache und nur dann in die Datenbank, wenn Cache nicht vorhanden oder zu alt ist
        ...
    }
}
 
Sekundentakt hat gesagt.:
Ich möchte in diesem Falle einfach die ständigen Zugriffe auf die Datenbank unterbinden (Öffnen und Schließen der Verbindung etc.)
Die Verbindungen zur DB bleiben auf, du kannst sie in einem Connection-Pool halten. Und an den Datenzugriffen über das DBMS wird eine hohe Antwortgeschwindigkeit sicherlich nicht scheitern.

Für alle zu cachende Daten brauchst du ein Singleton bzw. einen statischen Codeblock, der dir die Referenzen auf die Daten hält, da diese sonst vom GC wieder gekillt werden.

Die Frage ist eher wie viele Daten du speichern möchtest bzw. was du alles mit ihnen machen willst. Werden die Operationen zu umfangreich machen eigene Datenstrukturen oft wenig Sinn, da sie in großen Mengen schwer zu verwalten sind. Da würde ich dann ein DBMS oder eine sonst eine Lib, die dafür geeignet ist, benutzen.

Ein Framework würde ich nicht verwenden, schon gar nicht wenn man Anfänger ist. Aber das ist jetzt natürlich nur meine persönliche Meinung...
 
Für alle zu cachende Daten brauchst du ein Singleton bzw. einen statischen Codeblock, der dir die Referenzen auf die Daten hält, da diese sonst vom GC wieder gekillt werden.
Hast Du dafür ggf. mal einen Codeschnipsel? Ich kann mir dadrunter gerade nicht allzuviel vorstellen. . .

Danke!
 
Was verstehst du jetzt nicht? Code zu Singletons gibt es im Netz zu genüge. Ansonsten ist der Ablauf der Gleiche wie beim geposteten von mvitz. Nur eben ohne Framework:

Java:
class DAO { // Singleton-Klasse
  Cache c; // Alle Daten, die gespeichert werden sollen
  DBManager db; // Verwaltet das DMBS
  List<CacheValue> getSomething(Object o) {
    return c.getValues(o);
  }
}

class Servlet extends HttpServlet {
  DAO dao = DAO.getInstance();
  void doGet(...) {
    Object o = //  irgendwas was du aus der DB haben willst
    List<CacheValue> l = dao.getSomething(o);
  }
}
 
Vielen Dank für den Code-Schnipsel.
Ich konnte mit der Klasse "Singleton" in der JavaEE-Dokumentation nicht wirklich etwas anfangen.
Da Du mit der DAO-Klasse nicht von Singleton erbst, scheint die nichts damit zu tun zu haben?

Ich schaue mir mal ein paar Tutorials an.

Gruß
 
Danke!

Das ist jetzt etwas Off-Topic, hat aber trotzdem etwas mit dem hier genannten Thema zu tun.

Mal angenommen ich will eine Anwendung schreiben, die zwar regulär über HTTP-Requests kommuniziert, die ich aber leicht auch über andere Wege erreichen möchte. Denkbar wäre es z.B. das die Anwendung auch über Sockets kommuniziert oder über direkte Zugriffe (weil Embedded). Im Augenblick denke ich in den Dimensionen eines HTTPServlets in einer JavaEE-Umgebung.
Rein vom Nutzen her, könnte das was ich machen möchte, aber auch in einer Desktop-Anwendung untergebracht werden.
Vielleicht sage ich auch eines Tages, dass HTTP-Requests prinzipiell nicht erlaubt sind, dafür aber Anfragen via Sockets.

Im Augenblick bin ich bei so einer Flexibilität aber mit dem Design etwas überfordert,...
Wie setzt man sowas um?

Falls das zu stark OT ist, eröffne ich dafür einen eigenen Thread. Da es hier aber auch irgendwo um eine Architektur-Frage geht, wollte ich das dennoch hier unterbringen.

Danke!
Gruß
 
HTTP ist bloß ein Protokoll. Es kommuniziert genauso über Sockets. Das Prinzip ist das Gleiche, egal ob du einen Server oder einen Client hast.
Google mal nach "server client" oder "socket" in Verbindung mit Java. Schreib ein paar Beispielprogramme, ließ ein bisschen Theorie durch und sobald du das verstanden hast hat sich deine Frage vllt. schon gelöst.
 
HTTP ist bloß ein Protokoll. Es kommuniziert genauso über Sockets. Das Prinzip ist das Gleiche, egal ob du einen Server oder einen Client hast.
Google mal nach "server client" oder "socket" in Verbindung mit Java. Schreib ein paar Beispielprogramme, ließ ein bisschen Theorie durch und sobald du das verstanden hast hat sich deine Frage vllt. schon gelöst.
Ich glaube, dass sie das so schon hat.

Eigentlich kann ich alles in ein Projekt hauen: Ne Server-Klasse die über Sockets arbeitet, ne Servlet-Klasse - eigentlich ist das doch alles nur die Kommunkation nach Außen.
Schlussendlich könnten Server-, wie auch Servlet-Klassen das Programm als eigenständiges Objekt an sich binden, so wie wir es hier gerade mit dem Cache taten. Es ist lediglich eine neue Schicht in der Architektur.

Danke aber dennoch für den Denkanstoß. Ich habe mir gerade dieses Tutorial durchgelesen. Mir ist noch nicht klar, wie ich dafür sorgen kann, dass der Server so lange läuft, bis er das Kommando "runterfahren" erhält, aber das ist auch erst mal zweitrangig.
Es wäre einfach nur ärgerlich gewesen, wenn ich von vornherein alles auf Servlets abstimme und später dann die Hälfte neuschreiben muss.
 

Zurück
Oben