There are 2 approaches for doing this.
1. Class implementing Service Listener gets all service lifecycle Events .
public class PGServiceListener implements ServiceListener, BundleActivator {
……..
@Override
public void start(BundleContext cntxt) throws Exception {
cntxt.addServiceListener(this);
}
@Override
public void stop(BundleContext cntxt) throws Exception {
// TODO Auto-generated method stub
}
public void serviceChanged(ServiceEvent event) {
-à this is called for every service life cycle event
}
}
Here this class will be mentioned in the manifest file as a bundle Activator
2. Listening to the market Interface . Assuming that all the services implement a interface IService we can have the following listener which get all service related events.
<osgi:list id="listService"
interface="com.partygaming.service.monitor.external.IService"
cardinality="0..N">
<osgi:listener ref="serviceListener1" bind-method="bindService"
unbind-method="unBindService"></osgi:listener>
</osgi:list>
Looks like the second approach is better, as we get only 2 events, service register and unregister which we are interested in .It also gives all the properties of the service which will help us maintain other info like version.
Friday, October 23, 2009
Service Monitoring - OSGI
Distibuted OSGi
DOSGi helps in interaction between services which exists in different services in the same way as when they are co-hosted.
Specifications for DOSGi: http://www.osgi.org/Specifications/HomePage
Well Known implementations are
Apache CXF implementation : http://cxf.apache.org/distributed-osgi.html
Eclipse ECF implementation : http://wiki.eclipse.org/Distributed_OSGi_Services_with_ECF
Apache Tuscany implementation
Apache CXF implementation
-------------------------
http://cxf.apache.org/roadmap.html : Nothing more other than web services even in roadmap.
DOSGi Webinar : http://download.progress.com/open/adobe/prc/psc/042809_fuse_osgi_webinar/index.htm
Some answers to the questions on the webinar
http://coderthoughts.blogspot.com/2009/05/questions-from-rfc-119-webinar.html
Exposing service -has to mention the interace which can be remotely invoked.
Based on this Apache CXF creates a wsdl - which can be called by any web service client
(RFC 119) complaint discovery service - http://cxf.apache.org/dosgi-discovery.html
---------------------------------------
If discovery service is present - it will aurmtically detect , else we need to statically configure end points.
To enable automatic hooking of these remote services we need to have Service Registry Hooks -OSGi 4.2 spec(RFC 126)
Service Registry Hook Functionality(RFC 126 -OSGi spec 4.2) -Should be part of OSgi Core
Service Hook Functionalities
----------------------------
1. On Demand Registration of remote Services
2. Limiting Service Visibility
3. Service Proxification
How does it work [Refer Attached Diagram]
-----------------
Interface bundles are present in both the interacting containers.
Both teh containers have RFC 119 complaint discovery service and RFC 126 complaint registry hook
Service implementer registers with teh service with local OSGi container.
If this service has to be remotely accessed it needs to mention the property of remote interface.
Once this interface is mentioned the Discovery Service comes into picture which creates a remote end point for the service
It also register some meta data info with teh discovery service.
On the client side(in another Vm) when it expresses its interest in consuming this service , this information is passed
from the local osgi registry into the Registry hook which consults the discover service.
Now the discovery service will see if any one has remotely registered and if so creates a proxy for this service which will be reffered by the local osgi registry.
Current Apache CXF doesnt have either discovery service nor registry hook , hence end points need to be statically mentioned.
Apache is working on a discovery service under withthe ZooKepper Project
http://hadoop.apache.org/zookeeper/
http://wiki.apache.org/hadoop/ZooKeeper/ProjectDescription
[I think ZooKeeper is an alternative to Jgroups for sharing registry information between two nodes]
Working Demo is present in the link I have mentioned above, but without discovery service or service registry hook and it has a web service based implementaion for communication.
So to use Apache CXF we need minimum of these version - Equinox 3.5 / Felix 1.4.1 or later
Dmversion of equinox currntly- Dm 1.0.2 uses equinox 3 and 2.0 version uses equinox 3.5
Eclipse ECF implementation
----------------------------
http://wiki.eclipse.org/Distributed_OSGi_Services_with_ECF
http://eclipsesource.com/blogs/2008/12/19/rfc-119-and-ecf-part-1/
http://wiki.eclipse.org/Getting_Started_with_ECF%27s_RFC119_Implementation
Here changing the protocol for communication between services in diffrent VM's looks very simple
They claim to support the following protocols
Distribution
* r-OSGi (http) -r-OSGi is based upon a TCP-based protocols
* XMPP
* ECF Generic
* Skype
* Java Messaging Service (JMS)
* JavaGroups
Dynamic registring of the Spring Bean to the Application Context
I have come across use cases where we need to dynamicaly create a bean and register it to the Application Context rather than creating it through xmls during initialization.
This api doc helps to do that
http://static.springsource.org/spring/docs/2.5.6/api/org/springframework/context/support/StaticApplicationContext.html#registerSingleton%28java.lang.String,%20java.lang.Class%29
Usecase Ref:
http://forum.springsource.org/showthread.php?t=76490
Useful Blog
http://www.carlobonamico.com/blog/2008/01/22/how-to-dynamicallyprogrammatically-define-spring-beans/
Spring Integration Router Configuration
Just came across a router config in which based on the header it will route the messages to respective channels-provided both header and channel
l have same names .(No static definition required in application xmls)
1. Configuration where mapping of header values to channels is required
<header-value-router input-channel="routingChannel" header-name="testHeader">
<mapping value="someHeaderValue" channel="channelA" />
<mapping value="someOtherHeaderValue" channel="channelB" />
</header-value-router>
2. Configuration where mapping of header values is not required if header values themselves represent the channel names
<header-value-router input-channel="routingChannel" header-name="testHeader"/>
Ways to get Spring ApplicationContext -In Spring DM
Couple of other ways to get hold of ApplicationContext (rather than doing new ClasspathXmlApplicationContext()).
1. Create a bean which is ApplicationContextAware
MessageChannel msgCh = (MessageChannel)ApplicationContextHolder.getApplicationContext().getBean("eventChannel");
msgCh.send(msg);
public class ApplicationContextHolder implements ApplicationContextAware {
private static ApplicationContext appContext;
public void setApplicationContext(ApplicationContext ctx)
throws BeansException {
System.out.println("*** ApplicationContextHolder::setApplicationContext()...");
ApplicationContextHolder.appContext = ctx;
}
public static ApplicationContext getApplicationContext() {
return appContext;
}
}
This one is in the case of Spring DM
2. Accessing the ApplicationContext from BundleContext (By default every bundle publishes the Application Context as a Service).
public static ApplicationContext getApplicationContext() {
if (appCtx == null) {
try {
ServiceReference[] svcRef = bundleContext.getAllServiceReferences("org.springframework.context.ApplicationContext", "(org.springframework.context.service.name=ContextInClass)"); // Service name is the Bundle Symbolic Name
ServiceReference ref = svcRef[0];
appCtx = (ApplicationContext) bundleContext.getService(ref);
} catch (Exception e) {
e.printStackTrace();
}
}
return appCtx;
}
This is the preferred approach if you wish to use the Application Context from another bundle.
Java Monitoring Guidelines
Use the following command which gives the process size.
ps auxwww | grep java
Process size - Max size is 3 Gb on unix and 4 gb on solaris
[process size includes stacks,native code,therads created etc]
user 6451 180 30.2 [1416444-->process_size] 626888 ?
A check on the process size is critical because when there are leaks this gradually increases and finally the server crashes.
Command to get the Memory Details
jmap -dump:live,format=b,file=histo.bin
Command to generate Report Using JHat
jhat -J-mx256m histo.bin [histo.bin can be pscp'ed to windows machine and this command can be executed]
This starts a server gives a port number at the command line. using this url the details can be viewed through a explorer
Consequently the following command can be used to get the current memory picture in the JVM.
jmap -histo:live [process-id] > [filename].txt
The following command is also useful to understand the java heap and the GC behavior
jstat -gcutil 2361 1s
UseFull Vm parametres
-XX:+HeapDumpOnOutOfMemoryError
-XX:+PrintGCTimeStamps
-XX:+PrintGCDetails
-XX:+PrintGCApplicationStoppedTime
-verbose:gc
-XX:ErrorFile=/location/error.log
-XX:HeapDumpPath=/location/heap_dump.hprof
jstack [process_id] or kill -3 [process_id] can be used to get the thread dump of the process.