There is also a handy property for Application Server,
jndi.LDAP.URLContextImplementation, regarding re-using existing or
creating new connections for ldap searches/lookups. Less attractive areas
to look at are java programmatic JNDI TimeKeeper thread implementation for
the actual jndi client where LDAP provider timeout mechanism already
exists and OS/TCP settings for such parameters as timewait &
keepalive.
Extracted from Application Server V4.0 Release Notes and Information
Center:
A URL context implementation is a context that can handle arbitrary URL
strings of the URL scheme supported by the context. If the implementation
is enabled, a new connection is established for each search operation and
the connection is closed when the search is completed. If the network
dispatcher or IP sprayer in use does not support session affinity, this
needs to be enabled. Session affinity means that once a connection is
established between a client and a server, for example, WebSphere
Application Server, the LDAP client, and an LDAP server, and then all new
requests are routed to the same server. To support URL context
implementation, add the following property to the admin.config file:
jndi.LDAP.URLContextImplementation = true
*The same feature is available in V5.0 under ReUse Connection setting.
Version 4.0 introduced properties to support tuning the JNDI search
timeout value along with LDAP reuse connection. These two properties are
now settings in the Security Center of the V5.0 administrative console.
There is no migration of V4.0 property values to the V5.0 settings.
The jndi.LDAP.SearchControl.TimeLimit property is equivalent to the V5.0
Search Timeout setting, which is 300 by default.
The jndi.LDAP.URLContextImplementation property is equivalent to the V5.0
Reuse Connection setting, which is true by default.
1. let me clarify a little how "URL Context Implementation" works now in
Application Server, and its history. This property was originally added to
force JNDI to make new connection for each search operation, by passing
LDAP URL with Base search Distinguished Name (DN). This way, JNDI will
automatically open a new connection when it sees URL, and it is supposed
to close connection, as WebSphere Application Server does not explicitly
manage the new connection. Later, this implementation was modified to
initiate a new InitialDirContext instance directly, so a new connection is
also established along, and the context and connection is closed after
search or exception.
2. If JNDI does not return, the connection would not be closed until this
thread is recycled. In Application Server V4.0, a registry call is a
remote Enterprise Javabean call, and after transaction timeout, this not
responding call would be abandoned, so eventually the failing
InitialDirContext (and its connection) should be recycled by Java or
Software Developer Kit.
3. If proven that developer kit does not recycle the abandoned
InitialDirContext and its connection the problem should go to Java or
Software developer kit support. If the InitailContext instance and its
connection is not eventually recycled after transaction timeout (default
10 minutes), please provide evidence and JNDI trace, so Java or Software
developer kit support can investigate the problem.
4. However, if maintained that it takes 10 minutes to recycle a hang
condition (no response) from LDAPsearch, this is because JNDI does not
have timeout mechanism.
As per the doc in the following Sun JNDI LDAP Connection Closure url:
http://java.sun.com/products/jndi/tutorial/ldap/connect/close.html
per the section, "Forced Implicit Closures", need to explicitly call the
NamingEnumaration.close to close the physical connection.
Sample Testcase Scenario:
Closing LDAP connections and performance on ctx.close() operations.
Bad CASE
DirContext ctx = new InitialDirContext(env);
// Search for objects with those matching attributes
NamingEnumeration answer =
ctx.search("","(objectclass=*)", ctls );
// Close the context when we're done
ctx.close();
Good CASE
DirContext ctx = new InitialDirContext(env);
// Search for objects with those matching attributes
NamingEnumeration answer =
ctx.search("","(objectclass=*)", ctls );
answer.close(); // Added to close enum instance!!!!
// Close the context when we're done
ctx.close();
This testcase illustrates that Java Virtual Machine (JVM) closes LDAP
socket very quickly with Good case. In Bad case, LDAP socket remained for
sometime under heavy stress.
Sample(Bad case): This case can not enable JVM to close LDAP socket as
soon as possible. Repeating this will be reason of LDAP socket leak with
high stress access.
<extract>
ctx = new InitialDirContext(ldapConfig);
nEnum = ctx.search(base, filter, controls);
ctx.close();
</extract>
.
Sample (Good case): This case enable JVM to close LDAP socket as soon as
possible.
<extract>
ctx = new InitialDirContext(ldapConfig);
nEnum = ctx.search(base, filter, controls);
nEnum.close();
ctx.close();
</extract>
{Worth noting also that LDAP servers often have an idle timeout period
after which they will close connections no longer being used}
TimeKeeper JNDI Client Implementation:
*Can not implement timeout mechanism within the JNDI provider if the LDAP
itself doesn't have a timeout mechanism built-in.
To explain it further, need to have a time keeping mechanism on top of the
LDAP protocol without interfering with the normal protocol flow.
One of the complexities involved in this is, if can be imposed a timeout
on an LDAP operation (it could be using socket timeout for ex.), the
mechanism should ignore the response when the server eventually returns
back the results after the operation has timed out. This requires
book-keeping of the multiple requests sent by the client to determine
which ones have timed out.
The current and best way is to handle the timeout in the client
application is by using a time keeper thread. In a JNDI application one
can set a timer before the operation that needs a timeout, as shown below
posted on JNDI forum at:
http://forum.java.sun.com/thread.jsp?forum=51&thread=4954
...
class SimpleTimeKeeperTest {
public static void main(String args[]) throws Exception {
TimeKeeper.start(5000);
// perform the JNDI operation that needs a timeout
// In this example the while loop below requires a timeout
while(true) {
Thread.currentThread().sleep(10000);
}
}
}
class TimeKeeper extends Thread {
long timeout; // in milliseconds
long timerStart;
Thread parent;
TimeKeeper(long timeout) {
parent = Thread.currentThread();
this.timeout = timeout;
this.start();
}
public static void start(long timeout) {
new TimeKeeper(timeout);
}
public void run() {
timerStart = System.currentTimeMillis();
long waitTime = timeout;
while (waitTime > 0) {
try {
this.sleep(waitTime);
} catch (InterruptedException ie) {
// ignore and continue
}
waitTime = timeout - (System.currentTimeMillis() -
merStart); }
parent.interrupt();
}
}
PQ93851open for WebSphere Application Server V4.0 and related.
Changes necessary for this APAR have system integrity implications.
Resolution is to set jndi.LDAP.URLContextImplementation=true in
admin.config.
PQ96574 open for WebSphere Application Server V. 5.0 and being
considered for implementation of ldap socket_timeout mechanism, possibly
at jndi level, JNDI Search Timeout Implemented.
Related Apar for WebSphere Application Server /LDAP Hangs:
PQ96046 was included in WebSphere Application Server version 5.1.1
fixpack 3, server credential for LTPA no longer needs to be refreshed when
user registry is not available.
|