8. Nachrichten-orientierte Middleware

Werbung
Enterprise Application Integration
8. Nachrichten-orientierte
Middleware
Kommunikation zwischen IS in Unternehmen
eng
Remote Procedure Calls/ Remote
Method Invocation, z.B. bei:
Kopplung
CORBA
EJB
DCOM+
Web Services
Nachrichten
lose
2
Schnittstellen vs. Nachrichten
Kommunikation über Schnittstellen (bei RPC/RMI)
enge Kopplung der Systeme
ermöglicht Typprüfung während Kompilierung und Laufzeit
wenig Overhead
Anpassung umfangreicher Systeme aufwändig
Schnittstellen alter und neuer Systeme oft inkompatibel
Schnittstelle
int addiere(int x, int y);
Implementierung
int addiere(int x, int y) {
return x+y; }
3
17
25
42
Aufrufende Klasse
int result = schnittstelle.addiere(17, 25)
Schnittstellen vs. Nachrichten
Nachrichten
lose Kopplung der Systeme
bietet ggf. Zustellgarantie (bei Systemausfall später zugestellt)
keine Typprüfung
etwas größerer Overhead (z.B. durch Warteschlange, Metadaten)
einfache Anpassung auch bei größeren Systemen
für Kompatibilität mit Altsystemen
alte Nachrichteninhalte beibehalten, neue ergänzen
Sender
4
An: Empfänger
Dienst: addiere
x: 17
y: 25
Nachrichtenwarteschlange
Empfänger
Kommunikationsmodelle
Synchrone Kommunikation
Sender und Empfänger in Ablauf aneinander gekoppelt
Sender blockiert, bis Empfänger antwortet
Sender
Empfänger
Asynchrone Kommunikation
Sender und Empfänger in Ablauf nicht gekoppelt
Während Empfänger Antwort berechnet, kann Sender weiterarbeiten
Sender
5
Empfänger
Kommunikationsvarianten
Synchrone Einwegkommunikation
z.B. entfernter Methodenaufruf ohne Rückgabe
1. Sender sendet Anfrage an Empfänger und blockiert
2. Empfänger nimmt Nachricht entgegen, sendet Bestätigung
("Acknowledgement") und verarbeitet dann Nachricht
3. Sender erhält Bestätigung und kann direkt weiterarbeiten
Sender
Empfänger
Ack
6
Kommunikationsvarianten
Synchrones Polling
Sender fragt periodisch bei Empfänger an, ob Resultate vorliegen
Antwort entweder als Nachricht oder in gemeinsamem Speicher
1. Sender schickt Anfrage an Empfänger und arbeitet weiter
2. Empfänger startet Verarbeitung
3. Sender fragt regelmäßig nach Ergebnissen
Falls keine vorhanden, wird weitergearbeitet und später erneut nachgefragt
4. Ergebnis liegt vor: Ergebnis wird geliefert, Empfänger kann weiterarbeiten
5. Sender arbeitet mit Ergebnis weiter
Sender
7
Empfänger
Kommunikationsvarianten
Asynchrones Broadcasting
Sender sendet Nachricht an mehrere Empfänger gleichzeitig, arbeitet weiter
jeder Empfänger erhält Nachricht und kann reagieren
Empfänger 1
Sender
Empfänger 2
Empfänger 3
8
Kommunikationsvarianten
Asynchrones Publish/Subscribe
Ähnlich zum Broadcast, aber Empfänger abonnieren bei "Zusteller" Themen
nur registrierte Empfänger erhalten Nachricht
Abo
Sender
A
Zusteller
aB
m
e
h
eT
nnier
A Abonniere Thema A
Empfänger 1
Empfänger 2
A
Abon
niere
9
Them
a
A
Empfänger 3
Nachrichten-orientierte Middleware
Middleware, die die Weitergabe von Nachrichten übernimmt
Dienste zentriert auf Nachrichten
Anlegen
Weitergabe
Auslieferung
Speicherung (Persistierung)
Transaktionssicherheit
MoM als Vermittler zwischen Sender und Empfänger
Message-Server / Message-Broker
10
Nachrichten-orientierte Middleware
Vorteile:
asynchrone Kommunikation sehr allgemein;
ermöglicht Emulation anderer Modelle
aufgrund allgemeinen Charakters hohes Maß an Interoperabilität zwischen
heterogenen Systemen
für lose gekoppelte Systeme sehr gut geeignet
Nachteile:
fehlende Typsicherheit
Overhead durch Ver-/Entpacken und Übermittlung der Nachrichten
11
Nachrichten-orientierte Middleware
Entweder Standalone…
IBM Websphere MQ
Sun Java System Message Queue
MS Message Queue Server
ObjectWeb JORAM
BEA MessageQ
TIBCO ActiveEnterprise
…
…oder als Bestandteil anderer Middleware-Systeme
Java EE (JMS und Message-Driven Beans)
z.B. JBoss
…
12
Java Message Service
Spezifikation, definiert Schnittstellen und Protokolle für
Kommunikation durch Nachrichtenaustausch
Kommunikationsvarianten
asynchrones Senden (asynchrone Punkt-zu-Punkt-Kommunikation)
asynchrones Publish/Subscribe
asynchrones Request/Reply
synchrones Request/Reply (blockierend)
synchrone Einwegkommunikation
ermöglicht Programmierung weiterer Kommunikationsvarianten
13
Java Message Service
Zwei Arten von Nachrichtenkanälen
Queues: einfache Warteschlangen für n:m-Kommunikation (einer empfängt)
Topics: Publish/Subscribe-Kanäle für n:m-Kommunikation (alle empfangen)
Queues und Topics sind zueinander inkompatibel
Empfänger 1
Sender 1
xor
xor
Sender 2
Empfänger 2
Sender 1
Empfänger 1
xor
Sender 2
14
Queue
Topic
und
Empfänger 2
Java Message Service
Queue:
jede Nachricht wird nur einmal ausgeliefert
eine Nachricht wird ggf. solange gespeichert, bis ein Empfänger sie abholt
eine Übermittlungsreihenfolge wird nicht garantiert
Topic:
Variante 1:
nur die Abonnenten zum Sendezeitpunkt empfangen
Nachrichten können ggf. gar nicht empfangen werden
Variante 2 (durable):
auch die später hinzukommenden Empfänger erhalten die Nachricht
15
Java Message Service
Nachrichten
Bestehen aus Header, Properties und Body
Header enthält Meta-Angaben (Empfänger, Lebensdauer, ...)
Properties enthalten zusätzliche, frei definierbare Angaben
(primitive Datentypen und Strings)
Body enthält den eigentlichen Inhalt
Nachrichtenarten (implementieren javax.jms.Message)
TextMessage: zum Übermitteln eines Strings
MapMessage: für Namen-Werte-Paare primitiver Datentypen
ObjectMessage: zum Übermitteln eines serialisierbaren Objektes
BytesMessage: liefert einen beschreibbaren Byte-Stream
StreamMessage: für einen Stream primitiver Datentypen
SpyMessage (JBoss-spezifisch): Nachricht ohne Inhalt ("Ping")
16
Header
Properties
Body
Java Message Service
Für Versand und Empfang existiert Interface-Hierarchie
javax.jms.ConnectionFactory: Baut Verbindungen zwischen JMS Client
und JMS Provider auf; wird von Java EE bereitgestellt
javax.jms.Connection: Kapselt Verbindungen
javax.jms.Session: Sitzung, innerhalb der Nachrichten gesendet und
empfangen werden können
javax.jms.Destination: Ziel einer Nachricht (z.B. Queue oder Topic), muss
im Java EE-Kontext bereitliegen
javax.jms.MessageProducer/MessageConsumer: Sender/Empfänger einer
Nachricht, kommunizieren mit Destination
Destinations können auch temporär sein
17
Java Message Service
ConnectionFactory
erzeugt
Connection
erzeugt
MessageProducer
erzeugt
Session
erzeugt
MessageConsumer
erzeugt
sendet an
Nachricht
Destination
18
erhält von
Java Message Service
Grundsätzlicher Ablauf der Kommunikation
1. ConnectionFactory im JNDI-Kontext auffinden und referenzieren
2. mit Hilfe der Factory Connection erzeugen
3. Destination auffinden
4. Session erzeugen
5. Verbindung starten
6. MessageProducer und/oder MessageConsumer erzeugen
7. Nachrichten austauschen
8. Verbindung schließen
19
Java Message Service
Implementierung: Grundlegendes Gerüst für JMS-Clients
try { // alternativ: Properties in Datei jndi.properties hinterlegen
Properties p = System.getProperties();
p.setProperty("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");
p.setProperty("java.naming.factory.url.pkgs",
"org.jboss.naming:org.jnp.interfaces");
p.setProperty("java.naming.provider.url", "localhost:1099");
InitialContext ic = new InitialContext();
// ...
}
catch (JMSException e) {e.printStackTrace();}
catch (NamingException e) {e.printStackTrace();}
20
Java Message Service
Nachricht an Queue senden
ConnectionFactory cf =
(ConnectionFactory) ic.lookup("ConnectionFactory");
Connection con = cf.createConnection();
Session session = con.createSession(false,Session.AUTO_ACKNOWLEDGE);
con.start();
Queue queue = (Queue) ic.lookup("queue/testQueue");
MessageProducer sender = session.createProducer(queue);
MapMessage message = session.createMapMessage();
// message mit Inhalt füllen
sender.send(message);
con.close();
21
Auslieferung an
Message Server
als Transaktion?
Java Message Service
Beispiel: Map-Nachricht mit Inhalt füllen
message.setInt("anz",a.length);
for(int i=0; i<a.length;i++)
message.setDouble("arg"+i,a[i]);
// Referenz auf temporäre Queue für die Antwort mitschicken
message.setJMSReplyTo(temporaryQueue);
22
Java Message Service
Nachricht an Topic senden
ConnectionFactory cf =
(ConnectionFactory) ic.lookup("ConnectionFactory");
Connection con = cf.createConnection();
Session sesssion =
con.createSession(false,Session.AUTO_ACKNOWLEDGE);
con.start();
Topic topic = (Topic) ic.lookup("topic/testTopic");
MessageProducer publisher = session.createProducer(topic);
MapMessage message = session.createMapMessage();
// Nachricht mit Inhalt füllen
publisher.send(message);
con.close();
23
Java Message Service
Asynchrones Empfangen mit Message-Driven Bean
Implementieren des Interfaces javax.jms.MessageListener und der
Methode public void onMessage
Registrieren des MessageListeners
public class ExampleListener
implements javax.jms.MessageListener {
public void onMessage(Message message) {
// message verarbeiten
}
}
24
Java Message Service
Nachricht aus Queue synchron empfangen
InitialContext ic = new InitialContext();
ConnectionFactory cf =
(ConnectionFactory) ic.lookup("ConnectionFactory");
Connection con = cf.createConnection();
Session session =
con.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = (Queue) ctx.lookup("queue/testQueue");
MessageConsumer consumer = session.createConsumer(queue);
con.start();
StreamMessage msg = (StreamMessage) consumer.receive(10000);
// ggf. weitere Nachrichten empfangen
qc.close();
bei Topic analog
25
Java Message Service
Message-Selektoren
Nachrichten können anhand ihrer Properties selektiert werden, z.B.:
Sender:
message.setStringProperty("Ergebnistyp","Median");
Empfänger:
consumer =
session.createConsumer("Ergebnistyp=´Median´");
msg = (StreamMessage) consumer.receive(0);
“nicht passende” Nachrichten werden ignoriert
26
Message-Driven Beans
Message-Driven Beans
stellen JMS-Nachrichten-Empfänger dar
können Queues oder Topics abfragen
kapseln das Empfangen einer Nachricht
nur Verarbeitung muss implementiert werden
Interface MessageListener muss implementiert werden
Verarbeitung über onMessage()-Methode
27
Message-Driven Beans
Beantworten von Nachrichten
MDBs schicken nicht automatisch eine Antwort
dies muss ggf. explizit erfolgen (wie oben erläutert)
hierzu wird oft eine temporäre Queue verwendet,
die als Property der Nachricht mitgeschickt wurde
Sender:
Queue temp = session.createTemporaryQueue();
// …
message.setJMSReplyTo(temp);
MDB:
Destination replyTo = message.getJMSReplyTo();
MessageProducer producer = session.getProducer(replyTo);
// Antwortnachricht erstellen und verschicken …
28
Message-Driven Beans
Verwendung von Annotationen:
import
import
import
import
javax.ejb.ActivationConfigProperty;
javax.ejb.Messagedriven;
javax.jms.Message;
javax.jms.MessageListener;
@MessageDriven(activationConfig={
@ActivationConfigProperty(propertyName=“destinationType”,
propertyValue=“javax.jms.Topic”),
@ActivationConfigProperty(propertyName=“destination”,
propertyValue=“queue/meinTopic”),
@ActivationConfigProperty(propertyName=“messageSelector”,
propertyValue=“Nachrichtentyp=´Storno´”),
@ActivationConfigProperty(propertyName=“subscriptionDurability”,
propertyValue=“Durable”)})
public class MeinMDB implements MessageListener{
public void onMessage(Message m){…}
}
29
Literatur
Roman, E., et. al.: Mastering Enterprise JavaBeans 3.0, Wiley 2006
http://www.theserverside.com/tt/books/wiley/masteringEJB3/index.tss
(vollständiges Buch kostenlos herunterladbar)
W. Eberling, J. Lessner: Enterprise JavaBeans 3, Hanser, 2007
http://www.hanser.de/3-446-41085-6 (JMS s. Leseprobe 1, Beispiele)
D. Abts: Masterkurs Client/Server-Programmierung mit Java, vieweg
http://www.vieweg.de/index.php;do=show/site=v/book_id=10777/sid=c099bd7834a500ad479cc8c845df07a0
(Beispiele s. ONLINEPLUS)
Java Message Service Specification 1.1
http://java.sun.com/products/jms/docs.html
30
Herunterladen