Verteiltes Subject-Observer-Pattern mit ano-plass und DistributeMe
Das Subject/Observer-Pattern von ano-plass war bisher auf eine JVM beschränkt. Mit DistributeMe und einem Konfigurationsschalter erreichen Änderungsbenachrichtigungen wie Cache-Invalidierungen jetzt auch andere JVMs.
Asynchrone Benachrichtigung, auch bekannt als Publisher/Subscriber-Modell, ist ein mächtiges Pattern. Sowohl ano-plass als auch DistributeMe boten einen Weg dafür, das eine mit dem Subject/Observer-Pattern, das andere mit den klassischen EventChannels. Das Subject/Observer-Pattern von ano-plass war auf die aktuelle VM beschränkt. Jetzt kann es global werden.
Wir gehen davon aus, dass Sie ano-plass mit dem Subject-Observer-Pattern sowie DistributeMe bereits in Ihrem Tech-Stack einsetzen. Sie könnten es zum Beispiel nutzen, um Caches als dirty zu markieren und Ähnliches. Wenn etwa ein Account-Objekt gecacht ist, aber jemand das Account-Objekt ändert, sollten alle gecachten Kopien invalidiert werden. Normalerweise würden Sie dazu ein Change-Event auslösen:
observationAPI.fireSubjectUpdateForUser("ACCOUNT", "ME", accountId);
Jeder Codeteil, der Accounts cacht, wüsste dann, dass dieser Account geändert wurde, und würde entsprechend reagieren. Mit ano-plass funktionierte das aber nur innerhalb einer JVM. Bis jetzt.
Um die Unterstützung mehrerer JVMs über DistributeMe zu aktivieren, müssen Sie eine kleine verpflichtende und eine weitere optionale Änderung vornehmen.
Die verpflichtende Änderung besteht darin, Remoting in der ano-plass-Konfigurationsdatei namens apiconfig.json. zu aktivieren. Fügen Sie ihr folgende Property hinzu:
"supportRemotingForObservation": true
Wenn in Ihrer VM bereits ein DistributeMe-Service läuft, war es das schon. Falls nicht, zum Beispiel wenn Sie einen Webserver betreiben und nur Clients verwenden, die andere Services nutzen, müssen Sie das DistributeMe-Eventing manuell starten:
public class StartDistributeMeEventing {
public static final void startDistributeMeEventing(int port) throws Exception {
RMIRegistryUtil.findOrCreateRegistry(port);
org.distributeme.support.eventservice.generated.EventServiceRMIBridgeServer.init();
org.distributeme.support.eventservice.generated.EventServiceRMIBridgeServer.createServiceAndRegisterLocally();
}
}
Schließlich müssen Sie StartDistributeMeEventing.startDistributeMeEventing irgendwo aufrufen. Am besten eignet sich dafür die context.xml, und die Portnummer können Sie Ihrer Webanwendung ebenfalls als Parameter übergeben:
public void contextInitialized(ServletContextEvent event) {
LOGGER.info("--- " + APPLICATION_NAME + " --- APPLICATION INITIALIZATION: STARTED --- ");
//start distributeme eventing for the api.
String distributemePortAsString = event.getServletContext().getInitParameter("distributeMePort");
try{
int port = Integer.parseInt(distributemePortAsString);
StartDistributeMeEventing.startDistributeMeEventing(port);
}catch(Exception any){
LOGGER.error("Can not start distributeme eventing on port "+distributemePortAsString, any);
} //end start distributeme
//...
}
Das ist alles. Fröhliche Subject-Observation!