Troubleshooting Amazon ELB Keep-Alive Timeout Issues with Tomcat HTTPS Connector


2 views

When implementing Comet-style long polling with Tomcat 6.0.24 (JDK 1.6) behind an Amazon ELB, the keep-alive timeout setting isn't being respected. Despite configuring a 330-second (5.5 minute) timeout in the HTTPS connector, connections are being terminated prematurely at exactly 65 seconds.

The environment consists of:

OS: Ubuntu
Web Server: Tomcat 6.0.24
Java: JDK 1.6
Protocol: HTTPS (non-APR connector)
Load Balancer: Amazon ELB

Packet capture reveals the following sequence:

T=0   Client → Server: SYN (handshake initiation)
T=65  Server → Client: FIN (connection termination)
T=307 Client → Server: FIN (client-side cleanup)

The 65-second timeout is actually imposed by Amazon ELB's idle timeout setting, which defaults to 60 seconds. The extra 5 seconds comes from TCP-level timeouts. This setting overrides any application-level configuration.

You need to modify both your ELB configuration and Tomcat settings:

1. Update ELB Configuration

Increase the idle timeout through AWS CLI:

aws elb modify-load-balancer-attributes \
  --load-balancer-name your-elb-name \
  --load-balancer-attributes "{\"ConnectionSettings\":{\"IdleTimeout\":300}}"

2. Adjust Tomcat Configuration

Ensure your connector is properly configured:

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
           maxThreads="1000" keepAliveTimeout="330000"
           connectionTimeout="360000" maxKeepAliveRequests="-1"
           scheme="https" secure="true"
           clientAuth="false" sslProtocol="TLS" />
  1. Confirm ELB settings via AWS console or CLI
  2. Test with curl -v to verify connection duration
  3. Check Tomcat access logs for connection duration
  4. Use TCP dump for network-level verification
  • ELB maximum timeout is 4000 seconds
  • Consider TCP keepalive settings at OS level
  • Monitor for increased resource usage with longer timeouts

When implementing Comet-style long polling with Tomcat 6.0.24 behind an Amazon Elastic Load Balancer (ELB), many developers encounter an issue where HTTPS connections are being closed after exactly 65 seconds, despite setting a higher keepAliveTimeout value in the Tomcat connector configuration.

The 65-second timeout is actually imposed by the ELB's idle timeout setting, which defaults to 60 seconds (plus some buffer time). This setting overrides any keep-alive configuration you've set in Tomcat when the ELB is in the path.

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
           maxThreads="1000" keepAliveTimeout="330000"
           scheme="https" secure="true"
           clientAuth="false" sslProtocol="TLS" />

For AWS Classic Load Balancer:

  1. Go to EC2 Console → Load Balancers
  2. Select your load balancer
  3. Click the "Listener" tab
  4. Click "Edit" and set the "Idle Timeout" to your desired value (up to 3600 seconds)

For Application Load Balancer (ALB):

aws elbv2 modify-load-balancer-attributes \
    --load-balancer-arn your-lb-arn \
    --attributes Key=idle_timeout.timeout_seconds,Value=300

If you need even longer timeouts, consider using TCP load balancing instead of HTTPS:

# Nginx configuration example for TCP passthrough
stream {
    server {
        listen 443;
        proxy_pass tomcat_backend;
        proxy_timeout 300s;
    }
    
    upstream tomcat_backend {
        server tomcat1:8443;
        server tomcat2:8443;
    }
}

After making changes, verify with tcpdump:

sudo tcpdump -i any -nn -s 0 -w elb_test.pcap port 8443

Or using openssl to test the connection:

openssl s_client -connect your-elb:8443 -quiet
# Wait and observe when connection closes
  • Longer timeouts consume more resources on both ELB and Tomcat
  • Monitor connection counts and memory usage
  • Consider implementing heartbeat mechanisms for very long polls
  • For WebSocket connections, use ALB with proper protocol support