Artikel

 
Dezember 2011 | Artikel

(Funktionales) Skalieren mittels Messaging

(Link zum Artikel: http://www.it-republik.de/jaxenter/artikel/4234)

Enterprise Tales

Text: Lars Röwekamp und Matthias Weßendorf
  • Teilen
  • kommentieren
  • empfehlen
  • Bookmark and Share
Zur Kommunikation innerhalb von verteilten Systemen gibt es eine Reihe von Möglichkeiten. Neben schwergewichtigen Web-Service-Ansätzen (SOAP) kann der geneigte Entwickler beispielsweise auch auf leichtgewichtigere Varianten wie Remote Procedure Calls (RPC) oder HTTP REST zurückgreifen. Eine weitere, häufig unterschätzte Alternative stellt das Messaging dar.
Teil 1   Teil 2   

Asynchrones Arbeiten: Einfache Integration neuer Anforderungen
Bei der Verwendung von Web Services oder RPCs erfolgt der Aufruf eines entfernten „Dienstes“ in der Regel synchron. Das bedeutet, dass ein aufrufendes Programm erst dann fortgesetzt wird, wenn der aufgerufene Dienst seine Arbeit erledigt und das Ergebnis zurückgeliefert hat. Das kann für den aufrufenden Client, insbesondere bei lang laufenden Methoden, ein Problem darstellen. Messaging dagegen basiert auf einem asynchronen Ansatz: Ein Client schickt eine Nachricht an einen Server, der auf die eintreffenden Nachrichten in einer beliebigen Art und Weise reagiert. Das Clientprogramm kann direkt nach dem Absenden der Nachricht weiterarbeiten. Aber nicht nur die eben beschriebene Reduktion von Latenzzeiten ist ein valider Grund für den Einsatz von Messaging-Lösungen, wie beispielsweise JMS [1] oder AMQP [2]. Durch die Entkopplung der Systeme lassen sich auch neue fachliche Anforderungen deutlich einfacher umsetzten.

Ein traditionelles Beispiel
Als Beispiel soll ein JSF-basiertes Onlineredaktionssystem dienen, das beim Veröffentlichen eines (Online-)Artikels verschiedene Aktionen vornimmt. Die Action-Methode eines auf CDI aufbauenden JSF Controllers könnte wie in Listing 1 aussehen. Das verdeutlicht mehrere Probleme: Die JSF-Controller-Methode publishArticle()ruft der Reihe nach drei verschiedene Systeme auf, die alle unterschiedliche Antwortzeiten haben (können). Dabei erfolgt der Aufruf des jeweils nächsten Systems immer erst nach der vollständigen Abarbeitung seines Vorgängers. Besonders beim „posten“ auf externe Webressourcen, wie im Fall von Twitter, können jede Menge unterschiedlicher Probleme und Latenzen auftreten, die hier im Detail nicht behandelt wurden. Erst nach der Abarbeitung aller aufgerufenen Systeme kann die JSF-Applikation mit ihrer Ausführung fortfahren. Sollen später übrigens noch weitere Systeme mithilfe des JSF Controllers über den neuen Artikel informiert werden, so muss der Controller-Code allerdings erneut angepasst werden.

Listing 1
  1. @Named
  2. @RequestScoped
  3. public class PublishArticle{ @Inject PublisherService publisherService;
  4. @Inject AuthorService authorService;
  5. @Inject TwitterService twitterService;
  6. @Inject Article article;
  7. ...
  8. public String publishArticle() {
  9. URL articleUrl = publisherService.publishArticle(article);
  10. authorService.notifyAboutPublishedArticle(article.getAuthor(), articleURL);
  11. twitterService.post(article.getTitle(), url);
  12. return "publishe"; }
  13. }

Beispiel mit Messaging
Werfen wir noch einmal einen Blick auf das Redaktionssystem, diesmal nehmen wir ein Messaging-Systems hinzu (Listing 2). Statt dass der JSF Controller eigenhändig zahlreiche Systeme aufruft, versendet er nun lediglich eine (JMS) Nachricht. Listener, die an dem Veröffentlichen eines (Online-)Artikels interessiert sind, um beispielsweise den Link auf Twitter zu posten, können so autonom von dem JSF Controller entwickelt und gewartet werden (Listing 3). Der Code für das Gesamtsystem, z. B. der des JSF Controllers oder der eines (JMS) MessageListeners, wird durch die Trennung deutlich übersichtlicher. Zusätzlich wird die Fachlichkeit, wie die Benachrichtigung eines Autors, einer Interessentengruppe etc., sauber voneinander getrennt (Separation of Concerns). Diese Tatsache führt zu Code, der wesentlich wartbarer ist.

Listing 2
  1. @Named
  2. @RequestScoped
  3. public class publishArticle{ @Inject Connection connection;
  4. @Inject MessageProducer producer;
  5. ...
  6. @Inject Article article;
  7. ...
  8. public String publishArticle() {
  9. ...
  10. Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
  11. ...
  12. ObjectMessage message = session.createObjectMessage();
  13. message.setObject(article);
  14. // send the article message to various (sub) systems
  15. producer.send(message);
  16. connection.close();
  17. return "published"; }
  18. }

Listing 3
  1. public class TwitterPoster implements MessageListener {
  2. @Inject TwitterService twitterService;
  3. ...
  4. @Override
  5. public void onMessage(Message message) {
  6. Article article = (Article) ((ObjectMessage) message).getObject();
  7. // post information about this article...
  8. twitterService.post(article.getTitle(), article.getOnlineUrl());
  9. }
  10. }

Teil 1   Teil 2   

andere Artikel dieser Serie


Anzeige

Kommentare

Gravatar Hugo 20.12.2011
um 13:51 Uhr
... und weil Entwicklung mit Messaging so effektiv ist, schaut man sich das am Besten nicht nur für client/server Remote-Calls an, sondern auch für interne Strukturen.

Stichtwort: Aktoren.

Weiteres Stichwort: Akka Framework: http://akka.io/
#zitieren

Anzeige

zurück zum Seitenanfang