1# agentkeepalive 2 3[![NPM version][npm-image]][npm-url] 4[![build status][travis-image]][travis-url] 5[![Appveyor status][appveyor-image]][appveyor-url] 6[![Test coverage][codecov-image]][codecov-url] 7[![David deps][david-image]][david-url] 8[![Known Vulnerabilities][snyk-image]][snyk-url] 9[![npm download][download-image]][download-url] 10 11[npm-image]: https://img.shields.io/npm/v/agentkeepalive.svg?style=flat 12[npm-url]: https://npmjs.org/package/agentkeepalive 13[travis-image]: https://img.shields.io/travis/node-modules/agentkeepalive.svg?style=flat 14[travis-url]: https://travis-ci.org/node-modules/agentkeepalive 15[appveyor-image]: https://ci.appveyor.com/api/projects/status/k7ct4s47di6m5uy2?svg=true 16[appveyor-url]: https://ci.appveyor.com/project/fengmk2/agentkeepalive 17[codecov-image]: https://codecov.io/gh/node-modules/agentkeepalive/branch/master/graph/badge.svg 18[codecov-url]: https://codecov.io/gh/node-modules/agentkeepalive 19[david-image]: https://img.shields.io/david/node-modules/agentkeepalive.svg?style=flat 20[david-url]: https://david-dm.org/node-modules/agentkeepalive 21[snyk-image]: https://snyk.io/test/npm/agentkeepalive/badge.svg?style=flat-square 22[snyk-url]: https://snyk.io/test/npm/agentkeepalive 23[download-image]: https://img.shields.io/npm/dm/agentkeepalive.svg?style=flat-square 24[download-url]: https://npmjs.org/package/agentkeepalive 25 26The Node.js's missing `keep alive` `http.Agent`. Support `http` and `https`. 27 28## What's different from original `http.Agent`? 29 30- `keepAlive=true` by default 31- Disable Nagle's algorithm: `socket.setNoDelay(true)` 32- Add free socket timeout: avoid long time inactivity socket leak in the free-sockets queue. 33- Add active socket timeout: avoid long time inactivity socket leak in the active-sockets queue. 34 35## Install 36 37```bash 38$ npm install agentkeepalive --save 39``` 40 41## new Agent([options]) 42 43* `options` {Object} Set of configurable options to set on the agent. 44 Can have the following fields: 45 * `keepAlive` {Boolean} Keep sockets around in a pool to be used by 46 other requests in the future. Default = `true`. 47 * `keepAliveMsecs` {Number} When using the keepAlive option, specifies the initial delay 48 for TCP Keep-Alive packets. Ignored when the keepAlive option is false or undefined. Defaults to 1000. 49 Default = `1000`. Only relevant if `keepAlive` is set to `true`. 50 * `freeSocketKeepAliveTimeout`: {Number} Sets the free socket to timeout 51 after `freeSocketKeepAliveTimeout` milliseconds of inactivity on the free socket. 52 Default is `15000`. 53 Only relevant if `keepAlive` is set to `true`. 54 * `timeout`: {Number} Sets the working socket to timeout 55 after `timeout` milliseconds of inactivity on the working socket. 56 Default is `freeSocketKeepAliveTimeout * 2`. 57 * `maxSockets` {Number} Maximum number of sockets to allow per 58 host. Default = `Infinity`. 59 * `maxFreeSockets` {Number} Maximum number of sockets (per host) to leave open 60 in a free state. Only relevant if `keepAlive` is set to `true`. 61 Default = `256`. 62 * `socketActiveTTL` {Number} Sets the socket active time to live, even if it's in use. 63 If not setted the behaviour continues the same (the socket will be released only when free) 64 Default = `null`. 65 66## Usage 67 68```js 69const http = require('http'); 70const Agent = require('agentkeepalive'); 71 72const keepaliveAgent = new Agent({ 73 maxSockets: 100, 74 maxFreeSockets: 10, 75 timeout: 60000, 76 freeSocketKeepAliveTimeout: 30000, // free socket keepalive for 30 seconds 77}); 78 79const options = { 80 host: 'cnodejs.org', 81 port: 80, 82 path: '/', 83 method: 'GET', 84 agent: keepaliveAgent, 85}; 86 87const req = http.request(options, res => { 88 console.log('STATUS: ' + res.statusCode); 89 console.log('HEADERS: ' + JSON.stringify(res.headers)); 90 res.setEncoding('utf8'); 91 res.on('data', function (chunk) { 92 console.log('BODY: ' + chunk); 93 }); 94}); 95req.on('error', e => { 96 console.log('problem with request: ' + e.message); 97}); 98req.end(); 99 100setTimeout(() => { 101 if (keepaliveAgent.statusChanged) { 102 console.log('[%s] agent status changed: %j', Date(), keepaliveAgent.getCurrentStatus()); 103 } 104}, 2000); 105 106``` 107 108### `getter agent.statusChanged` 109 110counters have change or not after last checkpoint. 111 112### `agent.getCurrentStatus()` 113 114`agent.getCurrentStatus()` will return a object to show the status of this agent: 115 116```js 117{ 118 createSocketCount: 10, 119 closeSocketCount: 5, 120 timeoutSocketCount: 0, 121 requestCount: 5, 122 freeSockets: { 'localhost:57479:': 3 }, 123 sockets: { 'localhost:57479:': 5 }, 124 requests: {} 125} 126``` 127 128### Support `https` 129 130```js 131const https = require('https'); 132const HttpsAgent = require('agentkeepalive').HttpsAgent; 133 134const keepaliveAgent = new HttpsAgent(); 135// https://www.google.com/search?q=nodejs&sugexp=chrome,mod=12&sourceid=chrome&ie=UTF-8 136const options = { 137 host: 'www.google.com', 138 port: 443, 139 path: '/search?q=nodejs&sugexp=chrome,mod=12&sourceid=chrome&ie=UTF-8', 140 method: 'GET', 141 agent: keepaliveAgent, 142}; 143 144const req = https.request(options, res => { 145 console.log('STATUS: ' + res.statusCode); 146 console.log('HEADERS: ' + JSON.stringify(res.headers)); 147 res.setEncoding('utf8'); 148 res.on('data', chunk => { 149 console.log('BODY: ' + chunk); 150 }); 151}); 152 153req.on('error', e => { 154 console.log('problem with request: ' + e.message); 155}); 156req.end(); 157 158setTimeout(() => { 159 console.log('agent status: %j', keepaliveAgent.getCurrentStatus()); 160}, 2000); 161``` 162 163## [Benchmark](https://github.com/node-modules/agentkeepalive/tree/master/benchmark) 164 165run the benchmark: 166 167```bash 168cd benchmark 169sh start.sh 170``` 171 172Intel(R) Core(TM)2 Duo CPU P8600 @ 2.40GHz 173 174node@v0.8.9 175 17650 maxSockets, 60 concurrent, 1000 requests per concurrent, 5ms delay 177 178Keep alive agent (30 seconds): 179 180```js 181Transactions: 60000 hits 182Availability: 100.00 % 183Elapsed time: 29.70 secs 184Data transferred: 14.88 MB 185Response time: 0.03 secs 186Transaction rate: 2020.20 trans/sec 187Throughput: 0.50 MB/sec 188Concurrency: 59.84 189Successful transactions: 60000 190Failed transactions: 0 191Longest transaction: 0.15 192Shortest transaction: 0.01 193``` 194 195Normal agent: 196 197```js 198Transactions: 60000 hits 199Availability: 100.00 % 200Elapsed time: 46.53 secs 201Data transferred: 14.88 MB 202Response time: 0.05 secs 203Transaction rate: 1289.49 trans/sec 204Throughput: 0.32 MB/sec 205Concurrency: 59.81 206Successful transactions: 60000 207Failed transactions: 0 208Longest transaction: 0.45 209Shortest transaction: 0.00 210``` 211 212Socket created: 213 214``` 215[proxy.js:120000] keepalive, 50 created, 60000 requestFinished, 1200 req/socket, 0 requests, 0 sockets, 0 unusedSockets, 50 timeout 216{" <10ms":662," <15ms":17825," <20ms":20552," <30ms":17646," <40ms":2315," <50ms":567," <100ms":377," <150ms":56," <200ms":0," >=200ms+":0} 217---------------------------------------------------------------- 218[proxy.js:120000] normal , 53866 created, 84260 requestFinished, 1.56 req/socket, 0 requests, 0 sockets 219{" <10ms":75," <15ms":1112," <20ms":10947," <30ms":32130," <40ms":8228," <50ms":3002," <100ms":4274," <150ms":181," <200ms":18," >=200ms+":33} 220``` 221 222## License 223 224``` 225(The MIT License) 226 227Copyright(c) node-modules and other contributors. 228Copyright(c) 2012 - 2015 fengmk2 <fengmk2@gmail.com> 229 230Permission is hereby granted, free of charge, to any person obtaining 231a copy of this software and associated documentation files (the 232'Software'), to deal in the Software without restriction, including 233without limitation the rights to use, copy, modify, merge, publish, 234distribute, sublicense, and/or sell copies of the Software, and to 235permit persons to whom the Software is furnished to do so, subject to 236the following conditions: 237 238The above copyright notice and this permission notice shall be 239included in all copies or substantial portions of the Software. 240 241THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 242EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 243MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 244IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 245CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 246TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 247SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 248``` 249