Entdecken Sie eBooks
Kategorien
Entdecken Sie Hörbücher
Kategorien
Entdecken Sie Zeitschriften
Kategorien
Entdecken Sie Dokumente
Kategorien
Hchste Sicherheit
Verschlsselung
Ihrer Firmendaten
(SSH, SCP, SFTP)
Groe Datenmengen
d
Einfacher Transfer un
en
tei
Da
von
h
usc
Austa
(alle Formate)
Preisnachlass
1.000
STRATO HiDrive Pro *
mtl.
6 Monate nur 19,95
Schneller Zugang
Wie bei einer lokalen
,
Festplatte ber (S)FTP
.
.m
u.v
,
IFS
rsync, SMB/C
Daten-Backups
Wiederherstellung von
n
Dokumentenversione
l
tro
on
pC
cku
Ba
mit
5
gt: 0 18 05 - 055 05
en
g
f
ru
n
A
?
en
ag
Noch Fr
. 0,42 /Min.)
net z, Mobilfunk max
dt.
(0,14 /Min. aus dem
Fest
strato.de/hidrive
* Einmalige Einrichtungsgebhr 9,90 . Rabatt-Aktion fr die erste Mindestvertragslaufzeit von 6 Monaten, danach 39,90 /Monat. Preise inkl. MwSt.
ff
Gemeinsamer Zugri
l.
ink
g
un
alt
erw
r-V
Use
Admin-Accounts fr
bis zu 120 Konten
50
Deutschland 8,50
11.2010
magazin
CD-INHALT
42 fr Softwarearchitekten
Video von der W-JAX
2009 in voller Lnge
HIGHLIGHTS
www.javamagazin.de
Apache Wicket
Hazelcast
Was Java-Entwickler
wissen sollten 48
Activiti 5.0
Beta
WEITERE INHALTE
Apache libcloud
Apache Commons Lang
Apache MyFaces
Orchestra Core
uvm.
Alle CD-Infos ab Seite 3
10
Alle Infos im Heft ab Seite 51
Social Media
API
Hazelcast 1.9
Bean Validation
latz
1.000 GB Speicherp
Maven-Dependency-Management
Der ge
Liferay Portal
e
v
i
r
D
i
H
STRniaAleTOO
nline-Speicher!
JAVA Mag
CD
Apache Maven
Dependency-Magie
100
Java EE 6 ausgepackt
Bean Validation 74
Liferay Portal
Grundlagen 56
Hazelcast
Die Skalierbarkeit und Ausfallsicherheit von Anwendungen ist mit steigendem Daten- und Benutzeraufkommen in den letzten Jahren immer relevanter geworden. In diesem Zusammenhang tauchen hufig
Begriffe wie Data Grid und Grid Computing auf. Diese stehen im Wesentlichen fr die Verteilung
von Daten und Verarbeitungsprozessen in einem Cluster. Das leichtgewichtige Open-Source-Framework Hazelcast positioniert sich genau in diesem Problemfeld.
80 javamagazin 11 | 2010
Start
Hazelcast kann in seiner aktuellen Version 1.8.5 von [1]
heruntergeladen werden. Die Sourcen sind unter [2] zu
finden. Das Deployment ist denkbar einfach: Das hazelcast.jar muss dem Classpath hinzugefgt werden, weitere Abhngigkeiten zu anderen Bibliotheken bestehen
nicht. Somit kann das Framework in jedem Java-Umfeld
(Standalone, Spring, JEE etc.) eingesetzt werden. Um einen ersten Eindruck von den Funktionen zu bekommen,
empfiehlt es sich, die Beispielanwendung auszuprobieren (run.bat bzw. run.sh). Das Programm besitzt ein
Command-Line-Interface, wobei eine bersicht ber
alle Kommandos mit help angezeigt wird.
Wenn die Beispielanwendung nun parallel in mehreren
Shells ausgefhrt wird, ist zu erkennen, dass die einzelnen
JVM-Instanzen automatisch einen Cluster bilden. Eine
besondere Konfiguration ist hierfr nicht notwendig.
Standardmig erfolgt der Discovery-Prozess mithilfe
von Multicast (falls das nicht zur Verfgung steht, kann
auch TCP/IP konfiguriert werden). Dabei hat ein Cluster
einen Namen und ist durch ein Passwort geschtzt.
Distributed Map
Als einfaches Beispiel soll in unserer Anwendung pro
User ein UserState-Objekt (Listing 1) in einer Map abgelegt werden. Um diese von Hazelcast im Cluster verwalten zu lassen, reicht der folgende Aufruf:
java.util.Map<String, UserState> map =
com.hazelcast.core.Hazelcast.getMap("userStateMap");
www.JAXenter.de
map.put("user007", userState);
UserState userState = map.get("user007");
Datenpartitionierung im Cluster
Dabei mssen folgende Aspekte beachtet werden:
Gleichmige Verteilung der Daten auf die ClusterKnoten
Schneller Zugriff auf die verteilten Daten
Kein Datenverlust bei Ausfall von Knoten
Datenumverteilung bei Vernderungen des Clusters
Wie adressiert Hazelcast diese Anforderungen? Die Daten werden anhand ihres Hash-Werts beziehungsweise
bei einer Map anhand des Hash-Werts des jeweiligen
Schlssels, gleichmig ber die Cluster-Knoten verteilt.
Die Implementierung einer sinnvollen Hash-Funktion
fr Objekte, die man in eine verteilte Datenstruktur einfgen will, ist dementsprechend besonders wichtig. Der
schnelle Zugriff auf die Daten ist dadurch gewhrleistet,
dass Hazelcast fr jeden Hash-Wert wei, auf welchem
Cluster-Knoten sich das zugehrige Objekt befindet.
Somit ist von jedem Cluster-Knoten ausgehend maximal ein Remote-Zugriff notwendig, um ein gewnschtes
Objekt zu erhalten.
Die Datensicherheit wird dadurch gewhrleistet, dass
im Standardfall fr jeden Knoten der jeweils nchste
Cluster-Knoten ein vollstndiges Backup der Daten hlt.
Falls ein Knoten ausfllt, werden die Daten der brigen
Knoten neu verteilt und gespiegelt. Zu Datenverlusten
kann es also nur kommen, wenn zwei aufeinander folgende Knoten gleichzeitig ausfallen. Bei hheren Anforderungen an die Ausfallsicherheit kann eine hhere
Anzahl an Backup-Knoten eingestellt werden. Dies hat
dann natrlich entsprechende Auswirkungen auf die
Performance von Datennderungen und den Speicherverbrauch. Fllt ein Cluster-Knoten aus oder wird ein
neuer Knoten dem Cluster hinzugefgt, dann erfolgt
automatisch eine Datenumverteilung, sodass am Ende
wieder eine Gleichverteilung der Daten und Datenbackups erreicht wird.
Beispiel: Wenn ein aus 10 Knoten bestehender Cluster
10 Millionen Objekte enthlt, dann hlt jeder Knoten
2 Millionen Objekte: 1 Million eigene und 1 Million
als Backup fr den Vorgngerknoten. Wenn 10 Knoten dazu geschaltet werden, was zur Laufzeit geschehen
kann, werden die Daten ad hoc neu verteilt und jeder
Knoten enthlt schlielich 1 Million Objekte: 500000
eigene und 500000 als Backup.
www.JAXenter.de
Query
Gerade bei groen Datenmengen werden effektive Mglichkeiten bentigt, Elemente nach beliebigen Selektionskriterien zu ermitteln. Angenommen, man mchte alle
UserStates finden, deren zugehrige User einen Namen
haben, der mit M anfngt und die lter als 18 Jahre sind.
Bei einem naiven Ansatz wrde der ausfhrende Thread
ber alle Eintrge in der Map iterieren und fr den als
Value gespeicherten UserState berprfen, ob die Bedingungen erfllt sind. Dieses Vorgehen htte aber zur
Folge, dass alle entfernt gespeicherten Eintrge bertragen werden mssten, was uerst ineffizient wre. Fr
Listing 1
public class UserState implements Serializable {
private String userId; // unique identifier
private boolean refreshRequired = false;
private List<Notification> notifications =
new ArrayList<Notification>(); // Notification implements Serializable
private String userName;
private int userAge;
// getter/setter
//
}
Listing 2
IMap<String, UserState> map = Hazelcast.getMap(userStateMap);
Collection<UserState> values = map.values(new com.hazelcast.query.Predicate() {
@Override
public boolean apply(MapEntry mapEntry) {
UserState userState = (UserState) mapEntry.getValue();
return userState.getUserAge() > 18 &&
userState.getUserName().startsWith(M);
}
});
};
javamagazin 11 | 2010 81
eine Notification zu einem UserState-Objekt hinzu. Dabei ist zu beachteten, dass das modifizierte Value-Objekt
wieder in die Map zurckgeschrieben werden muss:
map.lock(userId);
try {
UserState userState = map.get(userId); userState.
addNotification(notification);
userState.setRefreshRequired(true);
map.put(userId, userState);
} finally {
map.unlock(userId);
}
Abb. 1: Monitoring-Tool
diese Problematik bietet Hazelcast eine passende Lsung: Jeder Knoten durchsucht seine lokalen Elemente
nach Treffern und nur diese werden an den anfragenden
Knoten gesendet. Daraus resultieren zwei Vorteile: Zum
einen wird das Netzwerk entlastet, da nur die relevanten
Eintrge bertragen werden. Zum anderen verbessert
sich die Antwortzeit, da die Suchanfrage parallel auf allen Knoten ausgefhrt wird (Listing 2).
Neben der Mglichkeit, die Bedingung wie eben
gezeigt zu implementieren, bietet Hazelcast noch die
elegante Alternative, SQL-hnliche Abfragen zu formulieren:
Collection<UserState> values =
map.values(new com.hazelcast.query.SqlPredicate("userName like M%
and userAge > 18"));
Hierbei erfolgt der Zugriff auf die Attribute per Reflection durch Aufruf des zugehrigen Getters, alternativ
kann das Attribut auch als public deklariert werden.
Eine Weiternavigation ber Beziehungen, um dort weitere Kriterien auszuwerten, ist nicht mglich.
Um die Suche weiter zu optimieren, knnen die Eintrge wie bei einer relationalen Datenbank indiziert werden. Dabei wird der Performancegewinn bei der Suche
durch etwas hhere Kosten bei Schreiboperationen erkauft, da der Index aktualisiert werden muss. Ein Index
kann wie folgt zu einem beliebigen Zeitpunkt erzeugt
werden: map.addIndex("userAge", true);
Locks
Gerade bei verteilten Systemen besteht die Gefahr, dass
Daten von verschiedenen Prozessen/Threads gleichzeitig gendert werden, wobei nur die letzte der konkurrierenden nderungen gespeichert wrde, whrend die
anderen verloren gehen. Um diese Lost-Updates zu vermeiden, besteht die Mglichkeit, zu bearbeitende Eintrge exklusiv zu sperren. Hier fgen wir beispielsweise
82 javamagazin 11 | 2010
Executor Service
Genauso wichtig wie die Verteilung von Daten ist die
Verteilung der Verarbeitung im Cluster. Angelehnt an
das in Java 1.5 neu eingefhrte Executor Framework
[3] realisiert Hazelcast einen Distributed Executor Service. Wie im Java Executor Service mssen ausfhrbare
Tasks die Interfaces java.util.concurrent.Callable oder
java.lang.Runnable implementieren, je nachdem, ob
ein Rckgabewert bentigt wird oder nicht. Zustzlich
muss ein Hazelcast Task noch Serializable sein, da er
potenziell auf einem entfernten Cluster-Knoten ausgefhrt wird. Um einen Task, der hier beispielsweise
das Vorkommen bestimmter Wrter auf einer Website
zhlt, auf einem beliebigen Cluster-Knoten auszufhren,
werden lediglich folgende Zeilen bentigt:
java.util.concurrent.ExecutorService executorService =
com.hazelcast.core.Hazelcast.getExecutorService();
Future<String> future =
executorService.submit(new CountTask("www.java-magazin.de",
"hazelcast"));
// Wartezeit berbrcken.
Long result = future.get()
www.JAXenter.de
reits genannte Beispiel fr das Hinzufgen einer Notification zu einem UserState-Objekt wurde in Listing 3 als
Task realisiert.
Um diesen Task auf dem Cluster-Knoten auszufhren,
der das UserState-Objekt verwaltet, muss er in einen
DistributedTask eingepackt werden, der als zustzlichen Parameter den Schlsselwert des gewnschten
Objekts erhlt:
Callable<Boolean> task = new AddNotificationTask(notification);
executorService.submit(new DistributedTask<Boolean>(task,
notification.getReceiverUserId()));
Was bringt diese nderung im Detail? Die Implementierung fhrt zu vier Remote-Zugriffen, wenn der Task
nicht auf dem Knoten ausgefhrt wird, auf dem der Eintrag gespeichert ist, nmlich fr die Operationen lock,
get, put und unlock auf der Map. Zudem werden bei
get und put jeweils das UserState-Objekt und die damit
mglicherweise assoziierten Objekte, wie zum Beispiel
ein User-Objekt, bertragen. Wird hingegen die CallMethode auf dem richtigen Knoten ausgefhrt, ist
lediglich ein Remotecall notwendig, und es muss nur
einmal das Notification-Objekt bertragen werden. Der
ExecutorService bietet somit eine gute Mglichkeit, die
Verarbeitung zu parallelisieren und Netzwerk-Traffic zu
minimieren.
Persistenz
Bislang wurde gezeigt, wie Hazelcast Daten im Speicher
verteilt und verwaltet und wie man diese Daten wiederfindet und effizient verarbeitet. Dabei ging es immer um Daten, die im Speicher gehalten werden. Was passiert aber,
wenn der gesamte Cluster ausfllt oder auch nur (weit
weniger dramatisch) wegen einer neuen Softwareversion
neu gestartet werden soll. Es ist fast immer ntig, wichtige Daten einer Anwendung persistent zu hinterlegen.
Hazelcast bietet hierfr die Mglichkeit, mittels selbst
implementierter Loader- und Store-Klassen die Eintrge
einer Map zu speichern. Dazu mssen lediglich die Interfaces com.hazelcast.core.MapLoader und com.hazelcast.
MapStore implementiert werden und in der hazelcast.
xml, die die Konfiguration enthlt, fr die gewnschte
Map im map-store-Element angegeben werden.
Mittels write-delay-seconds kann konfiguriert werden, ob die Schreibvorgnge synchron (write-through)
oder alle n Sekunden asynchron (write-behind) erfolgen
sollen. Letzteres hat in der Regel einen Performancevorteil, da die Anwendung nicht auf die Persistierung
eines Eintrags warten muss und es mglich ist, mehrere
nderungen gesammelt zum Beispiel per Bulk-Insert in
eine relationale Datenbank zu schreiben. Der Nachteil
des asynchronen Schreibens liegt in der Datensicherheit,
da alle nderungen, die in den Sekunden zwischen den
Speichervorgngen erfolgen, verloren gehen knnen. Da
dies aber nur geschehen kann, wenn ein Cluster-Knoten
Listing 3
public class AddNotificationTask implements Callable<Boolean>, Serializable {
private Notification notification;
public AddNotificationTask(Notification notification) {
this.notification = notification;
}
@Override
public Boolean call() throws Exception {
IMap<String, UserState> map = Hazelcast.getMap(Sample.sUserStateMap);
String userId = notification.receiverUserId;
map.lock(userId);
try {
UserState userState = map.get(userId);
if (userState != null) {
userState.addNotification(notification);
userState.setRefreshRequired(true);
map.put(userId, userState);
return Boolean.TRUE;
} else {
return Boolean.FALSE;
}
} finally {
map.unlock(userId);
}
}
www.JAXenter.de
javamagazin 11 | 2010 83
Transaktionen
Hazelcast bietet ebenfalls die Mglichkeit, Transaktionen abzubilden. Zum einen existiert ein einfach gehaltenes Transaction-Interface, ber das beliebige Aktionen
auf den verteilten Datenstrukturen von Hazelcast zu einer Transaktion zusammengefasst werden knnen.
In einem JEE-Kontext kann Hazelcast zum anderen
ber einen Resource Adapter (JCA) in die eigene Anwendung eingebunden werden und somit an StandardJTA-Transaktionen teilnehmen. In diesem Kontext darf
allerdings nicht vergessen werden, dass durch die Verteilung der Daten schon die nderung eines Map-Eintrags dazu fhren kann, dass mehrere Cluster-Knoten
an einer Transaktion beteiligt sind und somit verteilte
Transaktionen entstehen, die einen Two-Phase-Commit
erforderlich machen. Um diese sehr teuren Operationen
zu verhindern, sollte darauf geachtet werden, Transaktionen so klein wie mglich zu halten, falls nicht ganz auf
transaktionales Verhalten verzichtet werden kann.
Monitoring
In der Hazelcast-Distribution ist bereits ein Monitoring-Tool als Webapplikation enthalten, das in einem
beliebigen Webcontainer (z.B. Tomcat) deployt werden
kann. Nachdem man sich mit dem Cluster-Namen und
Passwort sowie IP und Port eines Knotens eingeloggt
hat, erhlt man eine bersicht ber alle Knoten und
Datenstrukturen im Cluster (Abb. 1). Fr eine konkrete
Alternative Frameworks
Sowohl Open Source als auch kommerziell gibt es viele interessante Produkte,
die im Bereich Data Grid beziehungsweise Grid Computing angesiedelt sind.
Sie alle haben im Kern ein hnliches Feature-Set, setzen aber teilweise unterschiedliche Schwerpunkte. Hier eine kleine Aufzhlung der Bekannteren:
OpenSource
Apache Hadoop
GridGain
DAC
JBossCache/JGroups/Infinispan
Commercial
Oracle Coherence
GigaSpaces
IBM eXtreme Scale
Gemstone
Terracotta
84 javamagazin 11 | 2010
Weitere Features
Zu den weiteren Features von Hazelcast zhlen u. a. folgende:
Hibernate 2nd Level Cache: Entitten und Suchergebnisse werden verteilt im Cluster gespeichert
Http Session Cluster: Verteiltes Speichern der HTTPSession und Session Failover.
Cluster Clients: Java-Clients, die wie jeder Knoten
auf den Cluster zugreifen knnen, aber keine eigenen
Daten speichern.
Security: Die Kommunikation zwischen Knoten kann
auf Socket-Ebene, basierend auf der Java Cryptography Architecture, sowohl symmetrisch als auch asymmetrisch verschlsselt werden.
Fazit
Mit Hazelcast liegt eine frei verfgbare Lsung vor, um
hochskalierbare verteilte Software zu entwickeln. Es
bietet auf Standard-Java-Datentypen basierende verteilte Datenstrukturen, ein an den Executor Service angelehnten Dienst zur Verteilung von Tasks im Cluster
sowie eine einfache Pub/Sub-Messaging-Lsung. Durch
die Verwendung bekannter Java-Konstrukte ist die
Einstiegshrde gering, und da auch Konfiguration und
Deployment sehr einfach sind, kann schon nach kurzer
Zeit produktiv mit Hazelcast gearbeitet werden. Bestehende Anwendungen lassen sich mit berschaubarem
Aufwand skalierbarer gestalten.
Neben Hazelcast gibt es noch eine ganze Reihe sowohl kommerzieller als auch Open-Source-Frameworks
mit gleichem oder hnlichem Fokus (Kasten: Alternative Frameworks). Diese bieten teilweise mehr Features
und sind in bestimmten Einsatzgebieten zweifellos berlegen, bentigen allerdings eine meist erheblich hhere
Einarbeitungszeit und haben in der Regel auch greren
Einfluss auf die Softwarearchitektur und die Systemlandschaft.
Christian Lambert ist Diplom-Informatiker und seit 2000 fr die
adesso AG ttig. In Kundenprojekten entwickelt er alsBerater und
Softwarearchitekt groe Geschftsanwendungen basierend auf
JEE.
Matthias Ebbing arbeitet als Softwarearchitekt fr die adesso AG.
Seine Schwerpunkte sind modellgetriebene Softwareentwicklung
und der Entwurf von Java-basierten Geschftsanwendungen.
www.JAXenter.de