Summary
I have what is, essentially, a load balancer implemented in Node.js. It takes a requests from client sockets and pipes them to the appropriate server socket based on hostname. It works great for my use case except that after running for several hours with a steady stream of connections, memory usage grows from an initial 40% to 80% and beyond. I can't seem to find where the memory leak is.
What I've Tried
I've tried replacing all anonymous functions with named functions that use this
context instead of closures; didn't seem to help. I'll provide sample code below.
const run = async () => {
const gateways = await fetchGateways()
const gatewayIndexByHostname = {}
const getGatewayIP = (hostname) => {
// reads from gateways and mutates gatewayIndexByHostname
// returns destination IP address
}
const server = net.createServer()
server.on('connection', (clientSocket) => {
clientSocket.on('error', () => {
clientSocket.destroy()
})
clientSocket.once('data', (buffer) => {
const data = buffer.toString()
const destinationHostname = getDestinationHostname(data)
const gatewayIP = getGatewayIP(destinationHostname)
const [host, port] = gatewayIP.split(':')
const gatewaySocket = net.createConnection({ host, port })
gatewaySocket.on('error', (err) => {
clientSocket.end(handleError(500, err))
gatewaySocket.destroy()
}
gatewaySocket.on('connect', () => {
clientSocket.pipe(gatewaySocket)
gatewaySocket.pipe(clientSocket)
gatewaySocket.write(data)
})
})
})
server.listen(PORT, () => {
console.log(`listening on port ${PORT}`)
})
}
run()
That's more or less what the code is doing. My heap snapshots show that Socket and all things related to sockets are what are increasing with every request. Any help in understanding the cause of the memory leak would be awesome.