Search code examples
javajbossjndi

Do JNDI lookups keep their connection open - and is this why my load balancing is broken?


We have several JBoss servers sitting behind a hardware load balancer using a round robin strategy. All our (JBoss) clients used to sporadically connect and these would be correctly load balanced. However, a new client is sending ~100 queries a minute and these are all being directed to the same server.

I imagine what is happening is that the remote client creates its initial context, does the lookup, and maintains the connection to the JNDI server for a period (about 15s) to save on the overhead of recreating the connection. This means the 2nd, and Nth request go to the same server. We proved this with the following code (Jython using JBoss libraries):

def __call__(self):
    p = Properties()
    p[Context.PROVIDER_URL] = "jnp://my.load.balancer:1099"
    p[Context.INITIAL_CONTEXT_FACTORY] = JndiLoginInitialContextFactory.name
    p[Context.SECURITY_PRINCIPAL] = <redacted>
    p[Context.SECURITY_CREDENTIALS] = <redacted>

    ctx = InitialContext(p)
    home = ctx.lookup("ejb/ServerNameService")

    ejbQuery = home.create()


    print "Server name: %s", (ejbQuery.getServerName())

    ctx.close()

Now, if I call that 100 times within the same JVM (multiple threads) then I always get the same server. If I call that 100 times with new JVMs then I get a mixture.

Is there any way, without using clustering technology, to force JNDI to re-negotiate it's initial connection?


Solution

  • Maybe. JNDI is a kind of cache for objects. So if you ask it for the same name several times within the same VM, you always get the same result. That's the correct behavior but you don't like it.

    The solution is to register a factory in JNDI instead of the instance itself. That way, the factory can get the information for creating the connections from JNDI but return you a new instance each time it is called (or return one from an internal pool).

    The same approach is used with JDBC. Instead of adding JDBC connections to the JNDI cache, a DataSource is added - which is a factory for JDBC java.sql.Connection instances.