在AWS Lambda与RDS环境中遭遇Handshake Inactivity TimeOut错误求助
Hey there, I’ve dealt with this exact Handshake Inactivity Timeout issue when using Lambda with RDS before—let’s walk through why it happens and how to fix it in your code.
Why This Happens
Lambda’s execution environment is ephemeral, and RDS will automatically drop idle connections after a period (usually 8 hours by default, but sometimes shorter). The mysql client’s default pool settings don’t handle this well—if a pooled connection gets dropped by RDS but the client doesn’t detect it, the next time you try to use that connection, you’ll hit this timeout error.
Step-by-Step Fixes
1. Update Connection Pool Configuration
Add timeout and keep-alive settings to your pool to manage idle connections and keep them active:
var mysql = require('mysql'); var config = require('./config.json'); var pool = mysql.createPool({ host : config.dbhost, user : config.dbuser, password : config.dbpassword, database : config.dbname, // Critical pool settings to prevent timeouts waitForConnections: true, connectionLimit: 10, // Adjust based on your traffic needs queueLimit: 0, idleTimeoutMillis: 30000, // Drop idle connections after 30 seconds acquireTimeout: 60000, // Timeout after 60s trying to get a connection timeout: 60000, // Overall connection timeout connectionConfig: { keepAlive: true, keepAliveInitialDelay: 300000 // Send a keep-alive packet every 5 minutes } });
idleTimeoutMillisensures idle connections are cleaned up before RDS drops them.keepAlivesends periodic packets to keep the connection active, preventing RDS from marking it as idle.
2. Handle Connection Errors with Retries
Modify your connection logic to detect and retry on common connection loss errors:
module.exports.handler = (event, context, callback) => { context.callbackWaitsForEmptyEventLoop = false; // Helper function to execute the query cleanly const executeQuery = (connection) => { connection.query("Select * from allBlogs", (error, results) => { connection.release(); if (error) { console.error('Query failed:', error); return callback({ statusCode: 400, headers: { "Access-Control-Allow-Origin": "*" }, body: JSON.stringify(error) }, null); } // Simplify tag splitting logic results.forEach(blog => { blog.tag = blog.tag.split(","); }); callback(null, { statusCode: 200, headers: { "Access-Control-Allow-Origin": "*" }, body: JSON.stringify(results) }); }); }; pool.getConnection((err, connection) => { if (err) { // Retry if connection was lost by RDS if (['PROTOCOL_CONNECTION_LOST', 'ECONNRESET'].includes(err.code)) { console.log('Connection lost—retrying...'); return pool.getConnection((retryErr, retryConn) => { if (retryErr) return callback(retryErr, null); executeQuery(retryConn); }); } return callback(err, null); } executeQuery(connection); }); };
This way, if a connection is already dropped by RDS, we automatically try to get a new one instead of failing immediately.
3. Verify VPC & Security Group Settings
Don’t overlook network configuration—this is a common hidden cause:
- Ensure your Lambda’s VPC security group allows outbound traffic to RDS’s port (usually 3306 for MySQL).
- Ensure your RDS security group allows inbound traffic from Lambda’s security group on port 3306.
A blocked network connection can also trigger handshake timeouts, even if your code is correct.
4. Optional: Warm Up Lambda (for infrequent invocations)
If your Lambda is rarely called, its execution environment (and pooled connections) can go idle for hours. To fix this:
- Use CloudWatch Events to trigger your Lambda every 5-10 minutes. This keeps the execution environment warm and maintains active connections in the pool.
Final Notes
These changes should resolve the Handshake Inactivity Timeout by ensuring your connection pool manages connections properly, handles dropped connections gracefully, and keeps active connections alive.
内容的提问来源于stack exchange,提问作者Prateek Pareek

