|
|
Federating MBeanServers with OpenDMK |
Project OpenDMK includes a cascading API that makes it possible
to federate MBeanServers. When several applications are running in
the same JVM, this example shows how the OpenDMK cascading API can be
used to keep applications MBeans isolated by using one MBeanServer
per application instance, but still presenting a single point of access
to remote clients by federating all MBeanServers in a single global
MBeanServer.
Federation of MBeanServers is also discussed for JMX 2.0. Although
it does share some concepts with the cascading feature of OpenDMK,
it will also have some noticeable differences.
In OpenDMK, the cascading API lets you federate MBeanServers in a
global MBeanServer by prefixing the domain name of federated MBean
ObjectNames with a directory name prefix. This is somewhat
analogous to a filesystem mount operation, where each
MBeanServer would be seen as a filesystem directory (folder).
If you mount an MBeanServer A into the directory "serverA" of your
global MBeanServer, then all MBeans belonging to MBeanServer A
will be mounted in the global MBeanServer with an ObjectName whose
domain begin with the string "serverA/".
So for instance, the MBeanServerDelegateMBean of MBeanServer A
appears in the global MBeanServer as:
serverA/JMImplementation:type=MBeanServerDelegate
In JMX 2.0 we're planning to keep this concept - but we will be
using "//" as separator instead of "/", so as not to
conflict with
existing ObjectNames. Moreover, MBeans whose names contain a "//" will
no longer exist as MBeans in the MBeanServer but will need to be
handled by a special object called a NamespaceHandler.
Another important difference in JMX 2.0 is that MBeans whose names
contain a "//" will not be returned by
MBeanServer.queryNames(null,null);.
The federation feature is still being discussed in JSR 255 expert
group, and thus I do not want to launch in a detailed explanation of
its concepts and APIs yet, but I wanted to give a warning here that
although some of its concepts are quite close to what can be seen in
the cascading feature of OpenDMK today, some of it will also be
significantly different:
The JMX 2.0 federation feature will be based on the concept of
ObjectName namespaces, which can have broader applications and address
shortcomings not handled by the OpenDMK Project's API, such as
scalability.
So do not be confused in thinking that OpenDMK cascading feature is
the code base for what will be in JMX 2.0: it's not.
An example of federated MBeanServers with OpenDMK cascading
Some time ago I answered a question on the SDN JMX forum, from
someone who wanted to run several applications in the same JVM, but
keep the MBeans of each application isolated from each other.
Here is how this can be achieved with OpenDMK cascading feature.
This example shows:
|
A Main class that creates applications whose MBeans are registered in
an application-private MBeanServer, and then federates all these
MBeanServers in a global MBeanServer - this example uses the platform
MBeanServer: if you wanted to keep all applications really isolated
and prevent them to access each other's MBeans by any means,
and didn't want to set up a complex java policy file, you would
probably create and use another MBeanServer for that, since
the application code could also call
ManagementFactory.getPlatformMBeanServer().
An ApplicationContoller MBean that we use for the sake of the example:
since I had to code and set up two dummy applications that basically did
the same thing (create an application MBeanServer and register their
MBeans in it) I choose to factorize all this common code in a base
ApplicationController MBean - of which each application provide
its own subclass. You can view these ApplicationContollers as the
main JMX entry point (MBean setup) for each application. Of course in
the real world you do not need your applications to share any code: all
you need is a reference to a private MBeanServer in which the
application has registered its own MBeans.
Dummy application MBeans for each applications. Application A has
Wombat MBeans, and Application B has Bandicoot MBeans.
|
|
The Main class creates an instance of Application A and mounts its
MBeanServer in a directory "a" in the platform MBeanServer. Then it
creates two instances of Application B, and mounts them in directories
"b1" and "b2" respectively.
The tree on the left shows how the platform MBeanServer now looks
like. If we were using JMX 2.0, we would not be seeing the mounted
MBeans at this level. We would see only special MBeans called
NamespaceHandlers, on which we would have to click in order to enter
their namespaces (in this case, the corresponding private
application MBeanServer).
The popup on the right part of the image shows all the MBeans that
the BandicootMBean bandicoot0 was able to find using
queryNames(null,null) on its MBeanServer reference.
This is because each application is using a private MBeanServer,
and the global MBeanServer in which they all have been federated
was not provided to them.
|
The code below shows how the Main class uses OpenDMK APIs in order
to mount each application MBeanServer into the global MBeanServer:
package example.opendmk.cascading;
import com.sun.jdmk.remote.cascading.CascadingAgent;
import com.sun.jdmk.remote.cascading.LocalMBeanServerConnectionFactory;
import com.sun.jdmk.remote.cascading.MBeanServerConnectionFactory;
import com.sun.jdmk.remote.cascading.proxy.ProxyCascadingAgent;
import example.application.ApplicationController;
import example.application.a.ApplicationA;
import example.application.b.ApplicationB;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.util.logging.Logger;
import javax.management.JMException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
@author
public class Main {
private static final Logger LOG =
Logger.getLogger(Main.class.getName());
@paramtarget@paramname@paramappl
private static CascadingAgent createCascadingAgentFor(MBeanServer target,
String name, ApplicationController appl) {
final MBeanServerConnectionFactory mbsfa =
new LocalMBeanServerConnectionFactory(appl.getMBeanServer(),
"application "+name);
return new ProxyCascadingAgent(mbsfa,null,null,name,
target,"application "+name);
}
@paramtarget@paramname@paramappl@return
public static CascadingAgent mount(MBeanServer target, String name,
ApplicationController appl)
throws JMException, IOException {
appl.register();
final CascadingAgent ag = createCascadingAgentFor(target,name,appl);
target.registerMBean(ag,getCascadingAgentNameFor(name));
ag.start();
return ag;
}
@name
public static ObjectName getCascadingAgentNameFor(String name)
throws MalformedObjectNameException {
return new ObjectName("opendmk.cascading.agents:type=CascadingAgent,name="+name);
}
@paramargs
public static void main(String[] args) throws Exception {
final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
final ApplicationA a = new ApplicationA("a");
final ApplicationB b1 = new ApplicationB("b1");
final ApplicationB b2 = new ApplicationB("b2");
final CascadingAgent ca = mount(server,"a",a);
final CascadingAgent cb1 = mount(server,"b1",b1);
final CascadingAgent cb2 = mount(server,"b2",b2);
System.out.println("Now use JCondsole to connect to " +
ManagementFactory.getRuntimeMXBean().getName());
System.out.println("Strike <Enter> to exit: ");
System.in.read();
}
}
|
You can get a binary (or source) zip of the OpenDMK APIs from
http://opendmk.dev.jav.net/
and you can download a zip containing the sources
of the example discussed in this blog entry from
here.
Cheers, and let me know if I've been too concise!
-- daniel
Tags:
cascading
java
jmx
opendmk
opensource
Posted by dfuchs
( May 29 2007, 05:48:14 PM CEST )
Permalink
|
Hi,
really interesting example.
I've to manage some mBeans in few mBeanServers. So I tried your example (I've only added a filter like mydomain:*,myAttr=true in ProxyCascadingAgent creation).
two qustions:
- How is possible to have a dynamic mirror of my managed Mbeans?...e.g. I connect with mBean servers once, and I'd be notified when an mbean register/deregister;
- What happen when jmx connection shut down?
thanks
luke
Posted by lukebike on March 13, 2008 at 04:13 PM CET #
Hi Luke,
I don't understand your question, because it's already a dynamic mirror...
Best regards,
-- daniel
Posted by daniel on March 19, 2008 at 11:14 AM CET #
The only difference to blog example is that my subagent application run on a different jvm and I retry remote mbeanServer connection via rmi.
In this case it seems that when I add/remove an Mbean in subagent MbeanServer, my masterAgent isn't updated....
thanks
Posted by lukebike on March 20, 2008 at 09:23 AM CET #
Hi Luke,
This is strange, and is not an expected behaviour - the ProxyCascadingAgent registers for MBeanServerNotification with the subagent in order to add/remove proxies when MBeans are added/removed in the sub agent.
How did you create set up the cascading link between the master agent and the subagent?
regards,
-- daniel
Posted by daniel on March 21, 2008 at 10:27 AM CET #
I've implemented something like this:
MBeanServer target = MBeanServerFactory.createMBeanServer();
MBeanServerConnection remoteConn = ....//retry a connection with subAgtMbServer
CascadingAgent ag = createCascadingAgentFor(target,"myAppl",remoteConn);
target.registerMBean(ag,new ObjectName("opendmk.cascading.agents:type=CascadingAgent,name="+name));
ag.start();
private static CascadingAgent createCascadingAgentFor(MBeanServer target,
String name, MBeanServerConnection remoteMBserverC) {
try {
final MBeanServerConnectionFactory mbsfa = new LocalMBeanServerConnectionFactory(remoteMBserverC, "application " + name);
ObjectName filter = new ObjectName("mydomain:*");//I'm only interested in manage mbeans in this domain
return new ProxyCascadingAgent(mbsfa, filter, null, name, target, "application " + name);
} catch (MalformedObjectNameException ex) {
return null;
} catch (NullPointerException ex) {
return null;
}
}
thank Daniel...and Happy Easter
luke
Posted by lukebike on March 21, 2008 at 01:08 PM CET #
Hi Luke,
Two remarks:
1) when federating remote MBeanServers I would recommend using the CasadingService MBean, rather than working directly with proxy cascading agents.
2) If you prefer to use the ProxyCascadingAgent directly for remote MBeanServers as you do know, you should use the BasicMBeanServerConnectionFactory instead of the LocalMBeanServerConnectionFactory.
The BasicMBeanServerConnectionFactory has additional logics to handle notification losts, connection closed notifications, etc...
Take care however that you must connect the JMXConnector before passing it to the BasicMBeanServerConnectionFactory.
Cheers,
-- daniel
Posted by daniel on March 21, 2008 at 02:41 PM CET #
Hi,
As I suggested you, I try to use CascadingService, as follow
JMXServiceURL agentURLs= ......
Hashtable h = new Hashtable();
h.put(Context.SECURITY_PRINCIPAL, username);
CascadingService service = new CascadingService();
service.mount(agentURLs[i],h,
new ObjectName("mySubAgtDomain:*"), "subagents/agent"+(i+1));
// Store the mountPointID for further use.
mountPoints[i] = mountPointID;
System.out.println(mountPointID);
but again my masterAgent isn't updated after an Mbean has been added/removed in subagent MbeanServer
thanks
Posted by lukebike on March 25, 2008 at 04:30 PM CET #
Hi Luke,
This is strange indeed. If you have a test case for this I'll have a look at it. You can send it to me directly by email.
What kind of connector are you using (what protocol? service:jmx:rmi: ?)
regards,
-- daniel
Posted by daniel on March 25, 2008 at 04:50 PM CET #