How can I reliably share a single property value between multiple servers in a Weblogic cluster -- which gets sets by one of the servers (the first one to try and access it).
Imagine it is like a static variable across the whole cluster, and the first server to access the variable gets to set it's value and that value is seen by every other server in the cluster.
I had thought the JNDI would be appropriate for this, as I read that the JNDI in a clustered environment ensures the object is shared amongst the cluster. So I set a string object in the cluster under a JNDI name and expected other servers who tried to bind the same name would get a Name Already Bound exception and thus know to use the already bound value from another server. But its not working. Each server is setting their own value in the JNDI with seemingly nothing to suggest they are accessing the same JNDI.
I propose to investigate distributed caches: http://java-source.net/open-source/cache-solutions. They have a mechanism to have single interface for all nodes in cluster. You can learn how they do it and then implement your lightweight implementation. Or add one library to your dependencies.
Related
I'm working with microservices in Java Spring MVC. With Kubernetes, the pods containing this microservice application logic can scale/replicate based on incoming load. In few words, there can be 2 or more copies of my application running.
I require to have a specific identifier mechanism which describes the specific pod replica / container containing the application. I was thinking to generate a random number as a descriptor at runtime and store it as an identifier to the container. But I was wondering if there is a better way, considering that I am working with Spring, TomCat and Kubernetes, I would expect that some of this tech stack can do something like this for me?
Kubernetes can do this. Each Pod will have a unique name that you can access as the hostname or through an environment variable. If you use a standard Deployment resource though this can change if the Pod dies and is recreated. It sounds to me like you want a StatefulSet, in which Pods are assigned unique ordinal indexes and retain these when recreated - https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#pod-identity
We have a set of integration tests, that use Oracle Coherence. All of them use the same config and the problem is that when you are running them in parallel, their coherence nodes join into one cluster and it is possible that one test affects others. Is there a simple way to prevent this joining?
Thanks!
We use LittleGrid in our tests rather than start Coherence natively. You can programmatically set up the grid and set the configuration.
For creating different clusters on a single machine for testing, you can use different tangosol-override config file.Just keep a tangosol-override file in the classpath of each cluster, provide different name to the clusters and specify different multi-cast address (not mandatory i guess). If you are using coherence 12C then you can also create different managed cluster in a single domain of weblogic server.
When you start a coherence node, it will read the tangosol-override file and issue multi-cast messages to the address mentioned in the file. When it doesn't find any other node or cluster with same cluster name. It starts it's own cluster as identifies itself as the master node.
In java EE, the way you get an EJB from a remote server is by looking it up in JNDI. The specification defines the JNDI name for a given bean type.
However, this seems to be only if you want to get a bean off your local computer. I want to get the bean off a remote server, like most users would. How do I specify the server URL? Do I pass a map to the InitialContext constructor?
Note: There is another question that is pretty much the same, but that has become out of date since the definition of portable JNDI names by the specification.
I want to get the bean off a remote server
Yes, you need specify the IP/port where the remote server (JNDI service) is running/listening.
How do I specify the server URL?
You have to set the propertie: java.naming.provider.url and make it available to the InitialConetxt.
This can be done in different ways:
to use a jndi.properties file
to use system properties
passing the value in a Hashtable when you create a new instance of
InitialContext object.
The concrete value of this and others necessary properties to instantiate the InitialConetct are vendor dependen.
An example for JBoss could be:
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=jnp://yourServer:1099
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
Keep in mind that there is no way that you can get the EJB's stub from a remote server if you donĀ“t indicate the url.
By "Remote" I mean the client and the server are running in different JVM.
You do JNDI lookups of remote EJBs using exactly the same code as you would use when running server-side:
Context context = new InitialContext(); // No properties needed
MyEJB myEjbInstance = (MyEJB) context.lookup("ejb/MyEJB");
Or, of course, you can inject it:
#EJB
private MyEJB myEjbInstance;
To make the naming context work, you must run your application as a Java EE application client. An application client is exactly like a regular standalone Java program, with a standard main method; the only difference is that it needs to be run in a different manner. That manner is not specified in the Java EE Spec, so each application server has its own way of doing it.
GlassFish, for example, requires an application client to include some special jars in the classpath, and set a couple system properties. Specifically, you must include lib/gf-installer.jar and all the jars referenced by its manifest in your classpath, and you must set the org.omg.CORBA.ORBInitialHost and org.omg.CORBA.ORBInitialPort system properties.
I want to use ehcacheas distributed ehcache.By distributed i mean i have number of appserver each having its own ehcache and if i put/update a object in one appserver cache all other caches(in other app servers) must automtically synchronize /update.
Now i dont want the address(hostname) of all other caches to be hardcoded in some config.
Because i can deploy my code in multiple boxes and new boxes can be added at any time and i dont want to modify the config file in all machines.
Can i pull the config file remotely?
Can i add list of servers in form of ip range? or network host class?
Consider using Terracotta if you don't want to implement it by your own. You can find a sample here.
Is there a way to find all nodes belonging to the cluster of the web-application? I know on JBoss i can use HAServiceMBeanSupport to get information about all nodes(hostname, IP-adress), but how can I achieve something similar on Tomcat, WebSpere, Glassfish, Oracle AS, Jetty, WebLogic?
(Best would be an interface which works for all of them)
There is no standard drop-in solution for what you are asking for.
Technically it can be achieved in many ways - both within java ecosystem and outside e.g. Jgroups cluster forming, Zookeeper or simple Redis or other K/V server where each server instance would register upon startup and subscribe for changes in the cluster group.
The support and required effort will vary though. The general approach would be to use some startup hook e.g. Servlet container initialization or EJB #Startup #Singleton to contact the topology discovery service(your redis server for example), provide the info about your instance and query info about the other instances already active. If you need leader election, you can use many algorithms, e.g. first come-first serve basis, or based on voting. Then you need to subscribe and actively listen for changes in topology, and possibly provide some kind of health metric - e.g. periodically let others know, that your instance is still active
On a general note, can you elaborate why would your app need to have the knowledge about other instances of the same type? Do you need Master election or HA cluster-wide singleton functionality? The best practice for building stable scalable solutions is to keep the app stateless and unaware of the scaling details.
Functions, that need to be only executed in sequence or on a single node at the time, could be extracted into a dedicated service e.g. batch job service, scheduler service etc.
Most JEE server vendors offer some custom solution for this e.g. JBoss HASingleton service, or HA singleton deployment(app will always run only on a single instance in the cluster) which also takes care of failover.
As far as I know, it depends of the capabilities of your Applicationserver.
There is no "standardway" to do this.
You can try the following:
The class ServletContextListener has two methods. You can calculate the hostname and the IP-Adress(es) within the create method, and delete the node in the destroy method.
This way has problems during a VM-crash the destroy-method will not be called, for instance.
EDIT:
Does your software need a Database? If so, all clusternodes have to use the same database instance. If your app is deployed without a cluster it uses a "private" database. You need a shared DB:
Table: NODES
HOST | IP
as1.cluster | < ip >
as2.cluster | < ip2 >
If only onne line inserted to that DB, there is no cluster.
But this table may be corrupted, if a node crashes and does not remove its entry from this Table.