agentkeepalive
Advanced tools
Comparing version 0.2.0 to 0.2.1
@@ -20,3 +20,5 @@ /*! | ||
var agentKeepalive = new Agent({ | ||
keepAlive: true, | ||
maxSockets: maxSockets, | ||
maxFreeSockets: maxSockets, | ||
maxKeepAliveTime: 30000, | ||
@@ -67,3 +69,3 @@ }); | ||
console.log('----------------------------------------------------------------'); | ||
console.log('[proxy.js:%d] keepalive, %d created, %d requestFinished, %d req/socket, %s requests, %s sockets, %s unusedSockets, %d timeout\n%j', | ||
console.log('[proxy.js:%d] keepalive, %d created, %d requestFinished, %d req/socket, %s requests, %s sockets, %s freeSockets, %d timeout\n%j', | ||
count, | ||
@@ -75,3 +77,3 @@ agentKeepalive.createSocketCount, | ||
agentKeepalive.sockets[name] && agentKeepalive.sockets[name].length || 0, | ||
agentKeepalive.unusedSockets[name] && agentKeepalive.unusedSockets[name].length || 0, | ||
agentKeepalive.freeSockets[name] && agentKeepalive.freeSockets[name].length || 0, | ||
agentKeepalive.timeoutSocketCount, | ||
@@ -115,2 +117,3 @@ rtKeepalives | ||
}; | ||
req.on('data', function () {}); | ||
req.on('end', function () { | ||
@@ -167,2 +170,2 @@ var timer = null; | ||
console.log('proxy start, listen on 1985'); | ||
console.log('proxy start, listen on 1985'); |
0.2.1 / 2013-11-08 | ||
================== | ||
* fix socket does not timeout bug, it will hang on life, must use 0.2.x on node 0.11 | ||
0.2.0 / 2013-11-06 | ||
@@ -3,0 +8,0 @@ ================== |
126
lib/agent.js
@@ -23,13 +23,127 @@ /*! | ||
if (typeof http.Agent.request === 'function') { | ||
// node >= 0.11, default Agent is keepavlie | ||
module.exports = http.Agent; | ||
module.exports.HttpsAgent = https.Agent; | ||
return; | ||
var debug; | ||
if (process.env.NODE_DEBUG && /agentkeepalive/.test(process.env.NODE_DEBUG)) { | ||
debug = function (x) { | ||
console.error.apply(console, arguments); | ||
}; | ||
} else { | ||
debug = function () { }; | ||
} | ||
function Agent(options) { | ||
options = options || {}; | ||
options.keepAliveMsecs = options.keepAliveMsecs || options.maxKeepAliveTime; | ||
http.Agent.call(this, options); | ||
var Agent = require('./_http_agent').Agent; | ||
var self = this; | ||
// max requests per keepalive socket, default is 0, no limit. | ||
self.maxKeepAliveRequests = parseInt(options.maxKeepAliveRequests, 10) || 0; | ||
// max keep alive time, default 60 seconds. | ||
// if set `keepAliveMsecs = 0`, will disable keepalive feature. | ||
self.createSocketCount = 0; | ||
self.timeoutSocketCount = 0; | ||
self.requestFinishedCount = 0; | ||
// override the `free` event listener | ||
self.removeAllListeners('free'); | ||
self.on('free', function (socket, options) { | ||
self.requestFinishedCount++; | ||
socket._requestCount++; | ||
var name = self.getName(options); | ||
debug('agent.on(free)', name); | ||
if (!socket.destroyed && | ||
self.requests[name] && self.requests[name].length) { | ||
self.requests[name].shift().onSocket(socket); | ||
if (self.requests[name].length === 0) { | ||
// don't leak | ||
delete self.requests[name]; | ||
} | ||
} else { | ||
// If there are no pending requests, then put it in | ||
// the freeSockets pool, but only if we're allowed to do so. | ||
var req = socket._httpMessage; | ||
if (req && | ||
req.shouldKeepAlive && | ||
!socket.destroyed && | ||
self.options.keepAlive) { | ||
var freeSockets = self.freeSockets[name]; | ||
var freeLen = freeSockets ? freeSockets.length : 0; | ||
var count = freeLen; | ||
if (self.sockets[name]) | ||
count += self.sockets[name].length; | ||
if (count >= self.maxSockets || freeLen >= self.maxFreeSockets) { | ||
self.removeSocket(socket, options); | ||
socket.destroy(); | ||
} else { | ||
freeSockets = freeSockets || []; | ||
self.freeSockets[name] = freeSockets; | ||
socket.setKeepAlive(true, self.keepAliveMsecs); | ||
socket.unref && socket.unref(); | ||
socket._httpMessage = null; | ||
self.removeSocket(socket, options); | ||
freeSockets.push(socket); | ||
// Avoid duplicitive timeout events by removing timeout listeners set on | ||
// socket by previous requests. node does not do this normally because it | ||
// assumes sockets are too short-lived for it to matter. It becomes a | ||
// problem when sockets are being reused. Steps are being taken to fix | ||
// this issue upstream in node v0.10.0. | ||
// | ||
// See https://github.com/joyent/node/commit/451ff1540ab536237e8d751d241d7fc3391a4087 | ||
if (self.keepAliveMsecs && socket._events && Array.isArray(socket._events.timeout)) { | ||
socket.removeAllListeners('timeout'); | ||
// Restore the socket's setTimeout() that was remove as collateral | ||
// damage. | ||
socket.setTimeout(self.keepAliveMsecs, socket._maxKeepAliveTimeout); | ||
} | ||
} | ||
} else { | ||
self.removeSocket(socket, options); | ||
socket.destroy(); | ||
} | ||
} | ||
}); | ||
} | ||
util.inherits(Agent, http.Agent); | ||
module.exports = Agent; | ||
Agent.prototype.createSocket = function (req, options) { | ||
var self = this; | ||
var socket = http.Agent.prototype.createSocket.call(this, req, options); | ||
socket._requestCount = 0; | ||
if (self.keepAliveMsecs) { | ||
socket._maxKeepAliveTimeout = function () { | ||
debug('maxKeepAliveTimeout, socket destroy()'); | ||
socket.destroy(); | ||
self.timeoutSocketCount++; | ||
}; | ||
socket.setTimeout(self.keepAliveMsecs, socket._maxKeepAliveTimeout); | ||
// Disable Nagle's algorithm: http://blog.caustik.com/2012/04/08/scaling-node-js-to-100k-concurrent-connections/ | ||
socket.setNoDelay(true); | ||
} | ||
this.createSocketCount++; | ||
return socket; | ||
}; | ||
Agent.prototype.removeSocket = function (s, options) { | ||
http.Agent.prototype.removeSocket.call(this, s, options); | ||
var name = this.getName(options); | ||
debug('removeSocket', name, 'destroyed:', s.destroyed); | ||
if (s.destroyed && this.freeSockets[name]) { | ||
var index = this.freeSockets[name].indexOf(s); | ||
if (index !== -1) { | ||
this.freeSockets[name].splice(index, 1); | ||
if (this.freeSockets[name].length === 0) { | ||
// don't leak | ||
delete this.freeSockets[name]; | ||
} | ||
} | ||
} | ||
}; | ||
function HttpsAgent(options) { | ||
@@ -36,0 +150,0 @@ Agent.call(this, options); |
{ | ||
"name": "agentkeepalive", | ||
"version": "0.2.0", | ||
"version": "0.2.1", | ||
"description": "Missing keepalive http.Agent", | ||
@@ -35,5 +35,5 @@ "main": "index.js", | ||
}, | ||
"engines": { "node": ">= 0.10.0" }, | ||
"engines": { "node": ">= 0.11.8" }, | ||
"author": "fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)", | ||
"license": "MIT" | ||
} |
@@ -21,4 +21,5 @@ # agentkeepalive [![Build Status](https://secure.travis-ci.org/TBEDP/agentkeepalive.png?branch=master)](http://travis-ci.org/TBEDP/agentkeepalive) [![Coverage Status](https://coveralls.io/repos/TBEDP/agentkeepalive/badge.png)](https://coveralls.io/r/TBEDP/agentkeepalive) | ||
maxSockets: 10, | ||
maxKeepAliveRequests: 0, // max requests per keepalive socket, default is 0, no limit. | ||
maxKeepAliveTime: 30000 // keepalive for 30 seconds | ||
maxFreeSockets: 10, | ||
keepAlive: true, | ||
keepAliveMsecs: 30000 // keepalive for 30 seconds | ||
}); | ||
@@ -25,0 +26,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
61362
712
194
8
4