@@ -25,6 +25,8 @@ import (
25
25
"sync"
26
26
"time"
27
27
28
+ "golang.org/x/time/rate"
29
+
28
30
"github.com/coreos/etcd/etcdserver/stats"
29
31
"github.com/coreos/etcd/pkg/httputil"
30
32
"github.com/coreos/etcd/pkg/transport"
@@ -243,7 +245,9 @@ func (cw *streamWriter) closeUnlocked() bool {
243
245
if ! cw .working {
244
246
return false
245
247
}
246
- cw .closer .Close ()
248
+ if err := cw .closer .Close (); err != nil {
249
+ plog .Errorf ("peer %s (writer) connection close error: %v" , cw .peerID , err )
250
+ }
247
251
if len (cw .msgc ) > 0 {
248
252
cw .r .ReportUnreachable (uint64 (cw .peerID ))
249
253
}
@@ -278,25 +282,28 @@ type streamReader struct {
278
282
recvc chan <- raftpb.Message
279
283
propc chan <- raftpb.Message
280
284
285
+ rl * rate.Limiter // alters the frequency of dial retrial attempts
286
+
281
287
errorc chan <- error
282
288
283
289
mu sync.Mutex
284
290
paused bool
285
- cancel func ()
286
291
closer io.Closer
287
292
288
- stopc chan struct {}
289
- done chan struct {}
293
+ ctx context.Context
294
+ cancel context.CancelFunc
295
+ done chan struct {}
290
296
}
291
297
292
- func (r * streamReader ) start () {
293
- r .stopc = make (chan struct {})
294
- r .done = make (chan struct {})
295
- if r .errorc == nil {
296
- r .errorc = r .tr .ErrorC
298
+ func (cr * streamReader ) start () {
299
+ cr .done = make (chan struct {})
300
+ if cr .errorc == nil {
301
+ cr .errorc = cr .tr .ErrorC
297
302
}
298
-
299
- go r .run ()
303
+ if cr .ctx == nil {
304
+ cr .ctx , cr .cancel = context .WithCancel (context .Background ())
305
+ }
306
+ go cr .run ()
300
307
}
301
308
302
309
func (cr * streamReader ) run () {
@@ -311,7 +318,7 @@ func (cr *streamReader) run() {
311
318
} else {
312
319
cr .status .activate ()
313
320
plog .Infof ("established a TCP streaming connection with peer %s (%s reader)" , cr .peerID , cr .typ )
314
- err : = cr .decodeLoop (rc , t )
321
+ err = cr .decodeLoop (rc , t )
315
322
plog .Warningf ("lost the TCP streaming connection with peer %s (%s reader)" , cr .peerID , cr .typ )
316
323
switch {
317
324
// all data is read out
@@ -322,15 +329,16 @@ func (cr *streamReader) run() {
322
329
cr .status .deactivate (failureType {source : t .String (), action : "read" }, err .Error ())
323
330
}
324
331
}
325
- select {
326
- // Wait 100ms to create a new stream, so it doesn't bring too much
327
- // overhead when retry.
328
- case <- time .After (100 * time .Millisecond ):
329
- case <- cr .stopc :
332
+ // Wait for a while before new dial attempt
333
+ err = cr .rl .Wait (cr .ctx )
334
+ if cr .ctx .Err () != nil {
330
335
plog .Infof ("stopped streaming with peer %s (%s reader)" , cr .peerID , t )
331
336
close (cr .done )
332
337
return
333
338
}
339
+ if err != nil {
340
+ plog .Errorf ("streaming with peer %s (%s reader) rate limiter error: %v" , cr .peerID , t , err )
341
+ }
334
342
}
335
343
}
336
344
@@ -346,7 +354,7 @@ func (cr *streamReader) decodeLoop(rc io.ReadCloser, t streamType) error {
346
354
plog .Panicf ("unhandled stream type %s" , t )
347
355
}
348
356
select {
349
- case <- cr .stopc :
357
+ case <- cr .ctx . Done () :
350
358
cr .mu .Unlock ()
351
359
if err := rc .Close (); err != nil {
352
360
return err
@@ -401,11 +409,8 @@ func (cr *streamReader) decodeLoop(rc io.ReadCloser, t streamType) error {
401
409
}
402
410
403
411
func (cr * streamReader ) stop () {
404
- close (cr .stopc )
405
412
cr .mu .Lock ()
406
- if cr .cancel != nil {
407
- cr .cancel ()
408
- }
413
+ cr .cancel ()
409
414
cr .close ()
410
415
cr .mu .Unlock ()
411
416
<- cr .done
@@ -429,13 +434,11 @@ func (cr *streamReader) dial(t streamType) (io.ReadCloser, error) {
429
434
430
435
setPeerURLsHeader (req , cr .tr .URLs )
431
436
432
- ctx , cancel := context .WithCancel (context .Background ())
433
- req = req .WithContext (ctx )
437
+ req = req .WithContext (cr .ctx )
434
438
435
439
cr .mu .Lock ()
436
- cr .cancel = cancel
437
440
select {
438
- case <- cr .stopc :
441
+ case <- cr .ctx . Done () :
439
442
cr .mu .Unlock ()
440
443
return nil , fmt .Errorf ("stream reader is stopped" )
441
444
default :
@@ -497,7 +500,9 @@ func (cr *streamReader) dial(t streamType) (io.ReadCloser, error) {
497
500
498
501
func (cr * streamReader ) close () {
499
502
if cr .closer != nil {
500
- cr .closer .Close ()
503
+ if err := cr .closer .Close (); err != nil {
504
+ plog .Errorf ("peer %s (reader) connection close error: %v" , cr .peerID , err )
505
+ }
501
506
}
502
507
cr .closer = nil
503
508
}
0 commit comments