tchannel 3.6.14 → 3.6.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/as/http.js CHANGED
@@ -261,7 +261,7 @@ TChannelHTTP.prototype.sendRequest = function send(treq, hreq, start, options, c
261
261
  self.logger.error('Buffer read for arg2 failed', {
262
262
  error: arg2res.err
263
263
  });
264
- var fromBufferErr = errors.HTTPReqArg2fromoBufferError(arg2res.err, {
264
+ var fromBufferErr = errors.HTTPReqArg2fromBufferError(arg2res.err, {
265
265
  arg2: res1
266
266
  });
267
267
  callback(fromBufferErr, null, null, null);
@@ -557,7 +557,7 @@ AsHTTPHandler.prototype.handleRequest = function handleRequest(req, buildRespons
557
557
  self.logger.error('Buffer read for arg2 failed', {
558
558
  error: arg2res.err
559
559
  });
560
- var fromBufferErr = errors.HTTPResArg2fromoBufferError(arg2res.err, {
560
+ var fromBufferErr = errors.HTTPResArg2fromBufferError(arg2res.err, {
561
561
  arg2: arg2
562
562
  });
563
563
  sendError(fromBufferErr);
@@ -1,6 +1,10 @@
1
1
  torch-client-bench:
2
2
  node index.js --relay --torch client --torchFile ./flame.raw --torchTime 10 \
3
- -- --relay --skipPing -s 4096,16384 -p 1000,10000,20000
3
+ -- --relay --skipPing -s 4096,16384 -p 1000 -m 3
4
+
5
+ torch-client-only-bench:
6
+ node index.js --torch client --torchFile ./flame.raw --torchTime 10 \
7
+ -- --skipPing -s 4096,16384 -p 1000 -m 3
4
8
 
5
9
  torch-server-bench:
6
10
  node index.js --relay --torch server --torchFile ./flame.raw --torchTime 10 \
@@ -265,6 +265,7 @@ function startClient(clientPort) {
265
265
  '--benchPort', String(self.ports.serverPort),
266
266
  '--relayServerPort', String(self.ports.relayServerPort),
267
267
  '--clientPort', String(clientPort),
268
+ '--instances', String(self.instanceCount),
268
269
  '--instanceNumber', String(self.benchCounter)
269
270
  ]);
270
271
  var benchProc = self.run(bench, args);
@@ -63,13 +63,17 @@ argv.pipeline = parseIntList(argv.pipeline);
63
63
  argv.sizes = parseIntList(argv.sizes);
64
64
 
65
65
  var DESTINATION_SERVER;
66
+ var DESTINATION_PORT;
66
67
  var TRACE_SERVER;
67
68
  var CLIENT_PORT = argv.clientPort;
69
+ var INSTANCES = 0;
68
70
 
69
71
  if (argv.relay) {
70
72
  DESTINATION_SERVER = '127.0.0.1:' + argv.relayServerPort;
71
73
  } else {
72
74
  DESTINATION_SERVER = '127.0.0.1:' + argv.benchPort;
75
+ DESTINATION_PORT = argv.benchPort;
76
+ INSTANCES = parseInt(argv.instances, 10);
73
77
  }
74
78
 
75
79
  if (argv.trace) {
@@ -171,9 +175,19 @@ Test.prototype.newClient = function newClient(id, callback) {
171
175
  };
172
176
  }
173
177
 
178
+ var peers = [DESTINATION_SERVER];
179
+ if (INSTANCES > 0) {
180
+ peers = [];
181
+ var basePort = DESTINATION_PORT;
182
+ for (var i = 0; i < INSTANCES; i++) {
183
+ peers.push('127.0.0.1:' + (basePort + i));
184
+ }
185
+ }
186
+
174
187
  var client = clientChan.makeSubChannel({
175
188
  serviceName: 'benchmark',
176
- peers: [DESTINATION_SERVER]
189
+ peers: peers,
190
+ minConnections: INSTANCES > 0 ? 10 : 1
177
191
  });
178
192
  client.createTime = Date.now();
179
193
  clientChan.listen(port, '127.0.0.1', function listened(err) {
package/channel.js CHANGED
@@ -55,6 +55,7 @@ var TChannelRequest = require('./request');
55
55
  var TChannelServiceNameHandler = require('./service-name-handler');
56
56
  var errors = require('./errors');
57
57
  var EventEmitter = require('./lib/event_emitter.js');
58
+ var ObjectPool = require('./lib/object_pool');
58
59
 
59
60
  var TChannelAsThrift = require('./as/thrift');
60
61
  var TChannelAsJSON = require('./as/json');
@@ -121,7 +122,8 @@ function TChannel(options) {
121
122
  this.emitConnectionMetrics =
122
123
  typeof this.options.emitConnectionMetrics === 'boolean' ?
123
124
  this.options.emitConnectionMetrics : false;
124
- this.choosePeerWithHeap = this.options.choosePeerWithHeap || false;
125
+ this.choosePeerWithHeap = typeof this.options.choosePeerWithHeap === 'boolean' ?
126
+ this.options.choosePeerWithHeap : true;
125
127
 
126
128
  this.setObservePeerScoreEvents(this.options.observePeerScoreEvents);
127
129
 
@@ -253,6 +255,15 @@ function TChannel(options) {
253
255
  this.batchStats = this.topChannel.batchStats;
254
256
  }
255
257
 
258
+ if (this.batchStats) {
259
+ ObjectPool.bootstrap({
260
+ channel: this,
261
+ reportInterval: 5000,
262
+ timers: this.timers,
263
+ debug: this.options.objectPoolDebug ? true : false
264
+ });
265
+ }
266
+
256
267
  this.maximumRelayTTL = MAXIMUM_TTL_ALLOWED;
257
268
 
258
269
  function doSanitySweep() {
@@ -521,9 +532,6 @@ TChannel.prototype.onServerSocketConnection = function onServerSocketConnection(
521
532
  TChannel.prototype.onServerSocketListening = function onServerSocketListening() {
522
533
  var self = this;
523
534
 
524
- var address = self.serverSocket.address();
525
- var hostPort = self.host + ':' + address.port;
526
-
527
535
  if (self.destroyed) {
528
536
  self.logger.error('got serverSocket listen whilst destroyed', self.extendLogInfo({
529
537
  requestedPort: self.requestedPort
@@ -531,7 +539,8 @@ TChannel.prototype.onServerSocketListening = function onServerSocketListening()
531
539
  return;
532
540
  }
533
541
 
534
- self.hostPort = hostPort;
542
+ var address = self.serverSocket.address();
543
+ self.hostPort = self.host + ':' + address.port;
535
544
  self.listening = true;
536
545
 
537
546
  if (self.subChannels) {
@@ -911,6 +920,10 @@ TChannel.prototype.close = function close(callback) {
911
920
 
912
921
  var counter = 1;
913
922
 
923
+ if (self.batchStats) {
924
+ ObjectPool.unref();
925
+ }
926
+
914
927
  if (self.sanityTimer) {
915
928
  self.timers.clearTimeout(self.sanityTimer);
916
929
  self.sanityTimer = null;
@@ -454,7 +454,9 @@ function advertiseAgain(delay) {
454
454
 
455
455
  self._advertisementTimer = timers.setTimeout(
456
456
  function advertiseTimeout() {
457
- self.advertise();
457
+ if (!self._destroyed) {
458
+ self.advertise();
459
+ }
458
460
  },
459
461
  delay
460
462
  );
package/lazy_relay.js CHANGED
@@ -20,9 +20,16 @@
20
20
 
21
21
  'use strict';
22
22
 
23
+ var process = require('process');
23
24
  var errors = require('./errors');
24
25
  var v2 = require('./v2');
25
26
  var stat = require('./stat-tags.js');
27
+ var ObjectPool = require('./lib/object_pool');
28
+ var ReadResult = require('bufrw').ReadResult;
29
+ var WriteResult = require('bufrw').WriteResult;
30
+
31
+ var readRes = new ReadResult();
32
+ var writeRes = new WriteResult();
26
33
 
27
34
  module.exports = {
28
35
  LazyRelayInReq: LazyRelayInReq,
@@ -35,30 +42,30 @@ module.exports = {
35
42
 
36
43
  /*eslint max-statements: [2, 40]*/
37
44
  function LazyRelayInReq(conn, reqFrame) {
38
- this.channel = conn.channel;
39
- this.conn = conn;
40
- this.start = conn.timers.now();
41
- this.remoteAddr = conn.remoteName;
42
- this.logger = conn.logger;
45
+ this.channel = null;
46
+ this.conn = null;
47
+ this.start = null;
48
+ this.remoteAddr = null;
49
+ this.logger = null;
43
50
  this.peer = null;
44
51
  this.outreq = null;
45
- this.reqFrame = reqFrame;
46
- this.id = this.reqFrame.id;
47
- this.serviceName = '';
48
- this.callerName = '';
49
- this.timeout = 0;
50
- this.alive = true;
52
+ this.reqFrame = null;
53
+ this.id = null;
54
+ this.serviceName = null;
55
+ this.callerName = null;
56
+ this.timeout = null;
57
+ this.alive = null;
51
58
  this.operations = null;
52
59
  this.timeHeapHandle = null;
53
- this.endpoint = '';
60
+ this.endpoint = null;
54
61
  this.error = null;
55
62
  this.tracing = null;
56
63
  this.reqContFrames = [];
57
- this.hasRead = false;
64
+ this.hasRead = null;
65
+ this.waitForIdentSlot = null;
58
66
 
59
67
  this.boundExtendLogInfo = extendLogInfo;
60
68
  this.boundOnIdentified = onIdentified;
61
- this.circuit = reqFrame.circuit;
62
69
 
63
70
  var self = this;
64
71
 
@@ -67,6 +74,10 @@ function LazyRelayInReq(conn, reqFrame) {
67
74
  }
68
75
 
69
76
  function onIdentified(err) {
77
+ // The ident descriptor will be cleared out of the peer when the ident
78
+ // comes back, so this slot id will be invalid once ident happens.
79
+ self.waitForIdentSlot = -1;
80
+
70
81
  if (err) {
71
82
  self.onError(err);
72
83
  } else {
@@ -75,6 +86,66 @@ function LazyRelayInReq(conn, reqFrame) {
75
86
  }
76
87
  }
77
88
 
89
+ LazyRelayInReq.prototype.reset = function reset(conn, reqFrame) {
90
+ this.channel = conn.channel;
91
+ this.conn = conn;
92
+ this.start = conn.timers.now();
93
+ this.remoteAddr = conn.remoteName;
94
+ this.logger = conn.logger;
95
+ this.peer = null;
96
+ this.outreq = null;
97
+ this.reqFrame = reqFrame;
98
+ this.id = this.reqFrame.id;
99
+ this.serviceName = '';
100
+ this.callerName = '';
101
+ this.timeout = 0;
102
+ this.alive = true;
103
+ this.operations = null;
104
+ this.timeHeapHandle = null;
105
+ this.endpoint = '';
106
+ this.error = null;
107
+ this.tracing = null;
108
+ this.reqContFrames.length = 0;
109
+ this.hasRead = false;
110
+ this.circuit = reqFrame.circuit;
111
+ this.waitForIdentSlot = null;
112
+ };
113
+
114
+ LazyRelayInReq.prototype.clear = function clear() {
115
+ if (this.outreq && !this.outreq._objectPoolIsFreed) {
116
+ this.outreq.free();
117
+ }
118
+
119
+ if (this.peer && this.waitForIdentSlot !== null) {
120
+ this.peer.stopWaitingForIdentified(this.waitForIdentSlot);
121
+ }
122
+
123
+ this.channel = null;
124
+ this.conn = null;
125
+ this.start = null;
126
+ this.remoteAddr = null;
127
+ this.logger = null;
128
+ this.peer = null;
129
+ this.outreq = null;
130
+ this.reqFrame = null;
131
+ this.id = null;
132
+ this.serviceName = null;
133
+ this.callerName = null;
134
+ this.timeout = null;
135
+ this.alive = null;
136
+ this.operations = null;
137
+ this.timeHeapHandle = null;
138
+ this.endpoint = null;
139
+ this.error = null;
140
+ this.tracing = null;
141
+ this.reqContFrames.length = 0;
142
+ this.hasRead = null;
143
+ this.circuit = null;
144
+ this.waitForIdentSlot = null;
145
+ };
146
+
147
+ ObjectPool.setup({Type: LazyRelayInReq, maxSize: 200});
148
+
78
149
  LazyRelayInReq.prototype.type = 'tchannel.lazy.incoming-request';
79
150
 
80
151
  LazyRelayInReq.prototype.initRead =
@@ -128,7 +199,7 @@ function initRead() {
128
199
  self.endpoint = endpoint;
129
200
 
130
201
  var tracing = self.reqFrame.bodyRW.lazy
131
- .readTracingValue(self.reqFrame);
202
+ .poolReadTracingValue(readRes, self.reqFrame);
132
203
  self.tracing = tracing || v2.Tracing.emptyTracing;
133
204
 
134
205
  self.channel.emitFastStat(
@@ -214,7 +285,7 @@ function createOutRequest() {
214
285
  if (conn && conn.remoteName && !conn.closing) {
215
286
  self.forwardTo(conn);
216
287
  } else {
217
- self.peer.waitForIdentified(self.boundOnIdentified);
288
+ self.waitForIdentSlot = self.peer.waitForIdentified(self.boundOnIdentified);
218
289
  }
219
290
  };
220
291
 
@@ -259,7 +330,8 @@ LazyRelayInReq.prototype.forwardTo =
259
330
  function forwardTo(conn) {
260
331
  var self = this;
261
332
 
262
- self.outreq = new LazyRelayOutReq(conn, self);
333
+ self.outreq = LazyRelayOutReq.alloc();
334
+ self.outreq.reset(conn, self);
263
335
 
264
336
  var ttl = self.updateTTL(self.outreq.start);
265
337
  if (!ttl || ttl < 0) {
@@ -315,7 +387,7 @@ function updateTTL(now) {
315
387
  timeout = self.channel.maximumRelayTTL;
316
388
  }
317
389
 
318
- var res = self.reqFrame.bodyRW.lazy.writeTTL(timeout, self.reqFrame);
390
+ var res = self.reqFrame.bodyRW.lazy.poolWriteTTL(writeRes, timeout, self.reqFrame);
319
391
  if (res.err) {
320
392
  // TODO: wrap? protocol write error?
321
393
  self.onError(res.err);
@@ -339,8 +411,10 @@ function onReadError(err) {
339
411
  );
340
412
  }
341
413
 
414
+ var conn = self.conn;
342
415
  self.onError(err);
343
- self.conn.resetAll(err);
416
+
417
+ conn.resetAll(err);
344
418
  };
345
419
 
346
420
  LazyRelayInReq.prototype.onError =
@@ -351,6 +425,7 @@ function onError(err) {
351
425
  self.logger.warn('dropping error from dead relay request', self.extendLogInfo({
352
426
  error: err
353
427
  }));
428
+ self.free();
354
429
  return;
355
430
  }
356
431
 
@@ -370,6 +445,8 @@ function onError(err) {
370
445
  }));
371
446
 
372
447
  self.reqContFrames.length = 0;
448
+
449
+ self.free();
373
450
  };
374
451
 
375
452
  LazyRelayInReq.prototype.sendErrorFrame =
@@ -391,6 +468,7 @@ function handleFrameLazily(frame) {
391
468
 
392
469
  if (!self.alive) {
393
470
  self.logger.warn('dropping frame from dead relay request', self.extendLogInfo({}));
471
+ self.free();
394
472
  return;
395
473
  }
396
474
 
@@ -518,6 +596,22 @@ function _observeCallReqContFrame(frame) {
518
596
  };
519
597
 
520
598
  function LazyRelayOutReq(conn, inreq) {
599
+ this.channel = null;
600
+ this.conn = null;
601
+ this.start = null;
602
+ this.remoteAddr = null;
603
+ this.logger = null;
604
+ this.inreq = null;
605
+ this.id = null;
606
+ this.serviceName = null;
607
+ this.callerName = null;
608
+ this.timeout = null;
609
+ this.operations = null;
610
+ this.timeHeapHandle = null;
611
+ this.alive = null;
612
+ }
613
+
614
+ LazyRelayOutReq.prototype.reset = function reset(conn, inreq) {
521
615
  this.channel = conn.channel;
522
616
  this.conn = conn;
523
617
  this.start = conn.timers.now();
@@ -530,7 +624,26 @@ function LazyRelayOutReq(conn, inreq) {
530
624
  this.timeout = 0;
531
625
  this.operations = null;
532
626
  this.timeHeapHandle = null;
533
- }
627
+ this.alive = true;
628
+ };
629
+
630
+ LazyRelayOutReq.prototype.clear = function clear() {
631
+ this.channel = null;
632
+ this.conn = null;
633
+ this.start = null;
634
+ this.remoteAddr = null;
635
+ this.logger = null;
636
+ this.inreq = null;
637
+ this.id = null;
638
+ this.serviceName = null;
639
+ this.callerName = null;
640
+ this.timeout = null;
641
+ this.operations = null;
642
+ this.timeHeapHandle = null;
643
+ this.alive = null;
644
+ };
645
+
646
+ ObjectPool.setup({Type: LazyRelayOutReq, maxSize: 200});
534
647
 
535
648
  LazyRelayOutReq.prototype.type = 'tchannel.lazy.outgoing-request';
536
649
 
@@ -566,6 +679,11 @@ LazyRelayOutReq.prototype.emitError =
566
679
  function emitError(err) {
567
680
  var self = this;
568
681
 
682
+ // ObjectPool weird free() issue; bail early
683
+ if (!self.channel) {
684
+ return;
685
+ }
686
+
569
687
  var now = self.channel.timers.now();
570
688
  var elapsed = now - self.start;
571
689
 
@@ -599,7 +717,16 @@ function emitError(err) {
599
717
  self.inreq.circuit.state.onRequestError(err);
600
718
  }
601
719
 
602
- self.inreq.onError(err);
720
+ // We need to defer the inreq onError work, because we might be
721
+ // *syncronously* processing an error after an attempt to write to a
722
+ // socket. Otherwise, we might end up freeing the in/outreq pair before a
723
+ // handleFrameLazily has completed.
724
+ process.nextTick(deferInReqOnError);
725
+ function deferInReqOnError() {
726
+ if (self.inreq) {
727
+ self.inreq.onError(err);
728
+ }
729
+ }
603
730
  };
604
731
 
605
732
  LazyRelayOutReq.prototype.logError =
@@ -613,6 +740,11 @@ LazyRelayOutReq.prototype.onTimeout =
613
740
  function onTimeout(now) {
614
741
  var self = this;
615
742
 
743
+ // ObjectPool weird free() issue; bail early
744
+ if (!self.conn) {
745
+ return;
746
+ }
747
+
616
748
  self.conn.ops.checkLastTimeoutTime(now);
617
749
  self.conn.ops.popOutReq(self.id, self.extendLogInfo({
618
750
  info: 'lazy out request timed out',
@@ -636,9 +768,15 @@ function handleFrameLazily(frame) {
636
768
  // - v2.Types.ErrorResponse
637
769
  var self = this;
638
770
 
771
+ // ObjectPool weird free() issue; bail early
772
+ if (!self.inreq) {
773
+ return;
774
+ }
775
+
639
776
  frame.setId(self.inreq.id);
640
777
  self.inreq.conn.writeToSocket(frame.buffer);
641
778
  if (frame.bodyRW.lazy.isFrameTerminal(frame)) {
779
+ self.alive = false;
642
780
  self.conn.ops.popOutReq(self.id, self.extendLogInfo({
643
781
  info: 'lazy relay request done',
644
782
  relayDirection: 'out'
@@ -655,6 +793,11 @@ function handleFrameLazily(frame) {
655
793
  self._observeErrorFrame(frame, now);
656
794
  // } else { TODO: log
657
795
  }
796
+
797
+ if (!self.alive && !self.inreq.alive) {
798
+ // Implicitly frees this because inreq.clear will free outreq
799
+ self.inreq.free();
800
+ }
658
801
  };
659
802
 
660
803
  LazyRelayOutReq.prototype._observeErrorFrame =
@@ -767,7 +910,7 @@ function _observeCallResFrame(frame, now) {
767
910
  self.inreq.circuit.state.onRequestHealthy();
768
911
  }
769
912
 
770
- var res = frame.bodyRW.lazy.readFlags(frame);
913
+ var res = frame.bodyRW.lazy.poolReadCode(readRes, frame);
771
914
  if (res.err) {
772
915
  self.logger.error('failed to read error frame code', self.extendLogInfo({
773
916
  error: res.err
@@ -775,8 +918,8 @@ function _observeCallResFrame(frame, now) {
775
918
  return;
776
919
  }
777
920
 
778
- var flags = res.value;
779
- var ok = flags === 0;
921
+ var code = res.value;
922
+ var ok = code === 0;
780
923
 
781
924
  if (ok) {
782
925
  self.channel.emitFastStat(