Multi tenancy pattern using JGroups - Atmosphere/atmosphere GitHub Wiki
Each tenant requires a separate JGroups cluster to receive messages. This can cause issues with too many sockets opened and port conflict issues if using TCP.
The JGroupsBroadcaster can act as a hub for many local broadcasters on each node. Each instance of a local broadcaster represents a tenant on that node. Only a single JGroups cluster is created and shared. Messages are relayed from the JGroupBroadcaster to the local ones.
The tenant name needs to get passed around in order to match the local broadcaster held in a map
Client connection: ` public void doGet(AtmosphereResource ar) {
String tenantName = ar.getRequest().getParameter("tenant");
String broadcasterName = "LocalBroadcaster-" + tenantName;
BroadcasterFactory factory = ar.getAtmosphereConfig().getBroadcasterFactory();
Broadcaster globalBroadcaster = factory.lookup(JGroupsBroadcasterTCP.class, "GlobalBroadcaster", true);
// Create local broadcaster
Broadcaster localBroadcaster = factory.lookup(DefaultBroadcaster.class, broadcasterName, true);
// Add local broadcaster to registry
localBroadcasterRegistry.putIfAbsent(tenantName, broadcasterName);
// Attach broadcaster to the client connection
ar.setBroadcaster(localBroadcaster);
// Create listener and add to global broadcaster
BroadcasterListener globalBcListener = new BroadcasterListener() {
@Override
public void onRemoveAtmosphereResource(Broadcaster b, AtmosphereResource r) {
}
@Override
public void onPreDestroy(Broadcaster b) {
}
@Override
public void onPostCreate(Broadcaster b) {
}
@Override
public void onMessage(Broadcaster b, Deliver deliver) {
String key = ((MyPayload) deliver.getMessage()).getTenantName();
String localBcName = localBroadcasterRegistry.get(key);
Broadcaster localBc = factory.lookup(DefaultBroadcaster.class, localBcName, true);
localBc.broadcast(deliver.getMessage());
}
@Override
public void onComplete(Broadcaster b) {
}
@Override
public void onAddAtmosphereResource(Broadcaster b, AtmosphereResource r) {
}
};
globalBroadcaster.addBroadcasterListener(globalBcListener);
ar.suspend();
}
`
Send events:
`Broadcaster br = broadcasterFactory.lookup(JGroupsBroadcasterTCP.class, "GlobalBroadcaster", true);
br.broadcast(context);`