When dealing with Apache-Tomcat integration via AJP connector, we often encounter intermittent connection issues that manifest as:
- Gradual thread exhaustion (MaxThreads limit reached)
- Database query latency spikes (2000-5000ms vs normal 5-50ms)
- Various AJP-related errors in Apache logs
The transition from dual-NIC to single-NIC setup appears to be a significant change point. While network simplification is desirable, it may introduce:
# Potential network bottleneck scenarios:
1. Bandwidth saturation between web/database layers
2. TCP connection reuse issues
3. Increased latency in localhost communication
The thread dump reveals a critical pattern - 199 threads blocked waiting on Oracle connection pool locks, while one thread remains stuck in socket read:
"TP-Processor2" daemon prio=1 tid=0x08f135a8 nid=0x6529 runnable [0x75cfe000..0x75cfef30]
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at oracle.net.ns.Packet.receive(Unknown Source)
The default Oracle connection pool settings may not handle network hiccups gracefully. Consider these adjustments:
# In context.xml or connection pool configuration
<Resource name="jdbc/myDB"
auth="Container"
type="javax.sql.DataSource"
maxActive="50"
maxIdle="10"
maxWait="10000"
validationQuery="SELECT 1 FROM DUAL"
testOnBorrow="true"
removeAbandoned="true"
removeAbandonedTimeout="60"
logAbandoned="true"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"/>
Modify your Tomcat's server.xml to handle connection timeouts better:
<Connector port="8009" protocol="AJP/1.3"
maxThreads="300"
minSpareThreads="25"
connectionTimeout="20000"
keepAliveTimeout="30000"
socketBuffer="8192"
packetSize="8192"
redirectPort="8443" />
For single-NIC setups, these sysctl adjustments may help:
# /etc/sysctl.conf additions
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 15
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 4096
Implement a simple watchdog script to detect and recover from hangs:
#!/bin/bash
# Monitor Oracle connection responsiveness
RESPONSE=$(echo "SELECT 1 FROM DUAL;" | sqlplus -s user/pass@DB)
if [[ $RESPONSE != *"1"* ]]; then
echo "$(date) - Database unresponsive" >> /var/log/tomcat_watchdog.log
/etc/init.d/tomcat restart
fi
If the issue persists, consider:
- Upgrading to Tomcat 7+ with improved AJP handling
- Using mod_jk instead of mod_proxy_ajp
- Implementing separate connection pools for read/write operations
When dealing with AJP connectivity between Apache and Tomcat, several telltale signs emerge in this scenario:
// Common error patterns in Apache logs
[error] (70007)The timeout specified has expired: ajp_ilink_receive() can't receive header
[error] (104)Connection reset by peer: ajp_ilink_receive() can't receive header
[error] proxy: AJP: disabled connection for (localhost)
The thread dump reveals a critical contention point in the Oracle connection pool:
// Sample thread stack trace showing lock contention
"TP-Processor200" daemon prio=1 tid=0x73a4dbf0 nid=0x70dd waiting for monitor entry
at oracle.jdbc.pool.OracleConnectionCacheImpl.getActiveSize(OracleConnectionCacheImpl.java:988)
- waiting to lock <0x7e3455a0> (a oracle.jdbc.pool.OracleConnectionCacheImpl)
First, adjust your AJP connector in server.xml:
<Connector port="8009" protocol="AJP/1.3"
connectionTimeout="20000"
keepAliveTimeout="30000"
maxThreads="500"
acceptorThreadCount="2"
socketBuffer="32768"
packetSize="32768"
redirectPort="8443" />
Modify your Oracle connection pool configuration:
// Recommended Oracle pool settings
OracleDataSource ds = new OracleDataSource();
ds.setConnectionCachingEnabled(true);
ds.setConnectionCacheProperties(
new Properties() {{
put("MinLimit", "10");
put("MaxLimit", "100");
put("InitialLimit", "10");
put("ConnectionWaitTimeout", "30");
put("InactivityTimeout", "180");
put("AbandonedConnectionTimeout", "300");
}});
For single-NIC environments, consider these sysctl tweaks:
# Add to /etc/sysctl.conf
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
net.core.somaxconn = 32768
net.ipv4.tcp_max_syn_backlog = 65536
Implement this JMX monitoring snippet for real-time insights:
// Java code to monitor thread states
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
long[] threadIds = threadBean.getAllThreadIds();
for (long threadId : threadIds) {
ThreadInfo threadInfo = threadBean.getThreadInfo(threadId, Integer.MAX_VALUE);
if (threadInfo != null && threadInfo.getLockName() != null
&& threadInfo.getLockName().contains("OracleConnectionCacheImpl")) {
System.out.println("Blocked thread detected: " + threadInfo);
}
}
Consider replacing AJP with HTTP connectors when possible:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
maxThreads="500"
redirectPort="8443" />