• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..18-Dec-2021-

lib/H03-May-2022-

LICENSEH A D18-Dec-20211.1 KiB2419

README.mdH A D18-Dec-20217.2 KiB242192

package.jsonH A D18-Dec-20211.4 KiB6766

README.md

1# agentkeepalive
2
3[![NPM version][npm-image]][npm-url]
4[![Known Vulnerabilities][snyk-image]][snyk-url]
5[![npm download][download-image]][download-url]
6
7[npm-image]: https://img.shields.io/npm/v/agentkeepalive.svg?style=flat
8[npm-url]: https://npmjs.org/package/agentkeepalive
9[snyk-image]: https://snyk.io/test/npm/agentkeepalive/badge.svg?style=flat-square
10[snyk-url]: https://snyk.io/test/npm/agentkeepalive
11[download-image]: https://img.shields.io/npm/dm/agentkeepalive.svg?style=flat-square
12[download-url]: https://npmjs.org/package/agentkeepalive
13
14The enhancement features `keep alive` `http.Agent`. Support `http` and `https`.
15
16## What's different from original `http.Agent`?
17
18- `keepAlive=true` by default
19- Disable Nagle's algorithm: `socket.setNoDelay(true)`
20- Add free socket timeout: avoid long time inactivity socket leak in the free-sockets queue.
21- Add active socket timeout: avoid long time inactivity socket leak in the active-sockets queue.
22- TTL for active socket.
23
24## Node.js version required
25
26Support Node.js >= `8.0.0`
27
28## Install
29
30```bash
31$ npm install agentkeepalive --save
32```
33
34## new Agent([options])
35
36* `options` {Object} Set of configurable options to set on the agent.
37  Can have the following fields:
38  * `keepAlive` {Boolean} Keep sockets around in a pool to be used by
39    other requests in the future. Default = `true`.
40  * `keepAliveMsecs` {Number} When using the keepAlive option, specifies the initial delay
41    for TCP Keep-Alive packets. Ignored when the keepAlive option is false or undefined. Defaults to 1000.
42    Default = `1000`.  Only relevant if `keepAlive` is set to `true`.
43  * `freeSocketTimeout`: {Number} Sets the free socket to timeout
44    after `freeSocketTimeout` milliseconds of inactivity on the free socket.
45    Default is `15000`.
46    Only relevant if `keepAlive` is set to `true`.
47  * `timeout`: {Number} Sets the working socket to timeout
48    after `timeout` milliseconds of inactivity on the working socket.
49    Default is `freeSocketTimeout * 2`.
50  * `maxSockets` {Number} Maximum number of sockets to allow per
51    host. Default = `Infinity`.
52  * `maxFreeSockets` {Number} Maximum number of sockets (per host) to leave open
53    in a free state. Only relevant if `keepAlive` is set to `true`.
54    Default = `256`.
55  * `socketActiveTTL` {Number} Sets the socket active time to live, even if it's in use.
56    If not set, the behaviour keeps the same (the socket will be released only when free)
57    Default = `null`.
58
59## Usage
60
61```js
62const http = require('http');
63const Agent = require('agentkeepalive');
64
65const keepaliveAgent = new Agent({
66  maxSockets: 100,
67  maxFreeSockets: 10,
68  timeout: 60000, // active socket keepalive for 60 seconds
69  freeSocketTimeout: 30000, // free socket keepalive for 30 seconds
70});
71
72const options = {
73  host: 'cnodejs.org',
74  port: 80,
75  path: '/',
76  method: 'GET',
77  agent: keepaliveAgent,
78};
79
80const req = http.request(options, res => {
81  console.log('STATUS: ' + res.statusCode);
82  console.log('HEADERS: ' + JSON.stringify(res.headers));
83  res.setEncoding('utf8');
84  res.on('data', function (chunk) {
85    console.log('BODY: ' + chunk);
86  });
87});
88req.on('error', e => {
89  console.log('problem with request: ' + e.message);
90});
91req.end();
92
93setTimeout(() => {
94  if (keepaliveAgent.statusChanged) {
95    console.log('[%s] agent status changed: %j', Date(), keepaliveAgent.getCurrentStatus());
96  }
97}, 2000);
98
99```
100
101### `getter agent.statusChanged`
102
103counters have change or not after last checkpoint.
104
105### `agent.getCurrentStatus()`
106
107`agent.getCurrentStatus()` will return a object to show the status of this agent:
108
109```js
110{
111  createSocketCount: 10,
112  closeSocketCount: 5,
113  timeoutSocketCount: 0,
114  requestCount: 5,
115  freeSockets: { 'localhost:57479:': 3 },
116  sockets: { 'localhost:57479:': 5 },
117  requests: {}
118}
119```
120
121### Support `https`
122
123```js
124const https = require('https');
125const HttpsAgent = require('agentkeepalive').HttpsAgent;
126
127const keepaliveAgent = new HttpsAgent();
128// https://www.google.com/search?q=nodejs&sugexp=chrome,mod=12&sourceid=chrome&ie=UTF-8
129const options = {
130  host: 'www.google.com',
131  port: 443,
132  path: '/search?q=nodejs&sugexp=chrome,mod=12&sourceid=chrome&ie=UTF-8',
133  method: 'GET',
134  agent: keepaliveAgent,
135};
136
137const req = https.request(options, res => {
138  console.log('STATUS: ' + res.statusCode);
139  console.log('HEADERS: ' + JSON.stringify(res.headers));
140  res.setEncoding('utf8');
141  res.on('data', chunk => {
142    console.log('BODY: ' + chunk);
143  });
144});
145
146req.on('error', e => {
147  console.log('problem with request: ' + e.message);
148});
149req.end();
150
151setTimeout(() => {
152  console.log('agent status: %j', keepaliveAgent.getCurrentStatus());
153}, 2000);
154```
155
156### Support `req.reusedSocket`
157
158This agent implements the `req.reusedSocket` to determine whether a request is send through a reused socket.
159
160When server closes connection at unfortunate time ([keep-alive race](https://code-examples.net/en/q/28a8069)), the http client will throw a `ECONNRESET` error. Under this circumstance, `req.reusedSocket` is useful when we want to retry the request automatically.
161
162```js
163const http = require('http');
164const Agent = require('agentkeepalive');
165const agent = new Agent();
166
167const req = http
168  .get('http://localhost:3000', { agent }, (res) => {
169    // ...
170  })
171  .on('error', (err) => {
172    if (req.reusedSocket && err.code === 'ECONNRESET') {
173      // retry the request or anything else...
174    }
175  })
176```
177
178This behavior is consistent with Node.js core. But through `agentkeepalive`, you can use this feature in older Node.js version.
179
180## [Benchmark](https://github.com/node-modules/agentkeepalive/tree/master/benchmark)
181
182run the benchmark:
183
184```bash
185cd benchmark
186sh start.sh
187```
188
189Intel(R) Core(TM)2 Duo CPU     P8600  @ 2.40GHz
190
191node@v0.8.9
192
19350 maxSockets, 60 concurrent, 1000 requests per concurrent, 5ms delay
194
195Keep alive agent (30 seconds):
196
197```js
198Transactions:          60000 hits
199Availability:         100.00 %
200Elapsed time:          29.70 secs
201Data transferred:        14.88 MB
202Response time:            0.03 secs
203Transaction rate:      2020.20 trans/sec
204Throughput:           0.50 MB/sec
205Concurrency:           59.84
206Successful transactions:       60000
207Failed transactions:             0
208Longest transaction:          0.15
209Shortest transaction:         0.01
210```
211
212Normal agent:
213
214```js
215Transactions:          60000 hits
216Availability:         100.00 %
217Elapsed time:          46.53 secs
218Data transferred:        14.88 MB
219Response time:            0.05 secs
220Transaction rate:      1289.49 trans/sec
221Throughput:           0.32 MB/sec
222Concurrency:           59.81
223Successful transactions:       60000
224Failed transactions:             0
225Longest transaction:          0.45
226Shortest transaction:         0.00
227```
228
229Socket created:
230
231```bash
232[proxy.js:120000] keepalive, 50 created, 60000 requestFinished, 1200 req/socket, 0 requests, 0 sockets, 0 unusedSockets, 50 timeout
233{" <10ms":662," <15ms":17825," <20ms":20552," <30ms":17646," <40ms":2315," <50ms":567," <100ms":377," <150ms":56," <200ms":0," >=200ms+":0}
234----------------------------------------------------------------
235[proxy.js:120000] normal   , 53866 created, 84260 requestFinished, 1.56 req/socket, 0 requests, 0 sockets
236{" <10ms":75," <15ms":1112," <20ms":10947," <30ms":32130," <40ms":8228," <50ms":3002," <100ms":4274," <150ms":181," <200ms":18," >=200ms+":33}
237```
238
239## License
240
241[MIT](LICENSE)
242