github.com/unionj-cloud/go-doudou/v2@v2.3.5/toolkit/memberlist/awareness.go (about)

     1  package memberlist
     2  
     3  import (
     4  	"sync"
     5  	"time"
     6  
     7  	"github.com/armon/go-metrics"
     8  )
     9  
    10  // awareness manages a simple metric for tracking the estimated health of the
    11  // local node. Health is primary the node's ability to respond in the soft
    12  // real-time manner required for correct health checking of other nodes in the
    13  // cluster.
    14  type awareness struct {
    15  	sync.RWMutex
    16  
    17  	// max is the upper threshold for the timeout scale (the score will be
    18  	// constrained to be from 0 <= score < max).
    19  	max int
    20  
    21  	// score is the current awareness score. Lower values are healthier and
    22  	// zero is the minimum value.
    23  	score int
    24  }
    25  
    26  // newAwareness returns a new awareness object.
    27  func newAwareness(max int) *awareness {
    28  	return &awareness{
    29  		max:   max,
    30  		score: 0,
    31  	}
    32  }
    33  
    34  // ApplyDelta takes the given delta and applies it to the score in a thread-safe
    35  // manner. It also enforces a floor of zero and a max of max, so deltas may not
    36  // change the overall score if it's railed at one of the extremes.
    37  func (a *awareness) ApplyDelta(delta int) {
    38  	a.Lock()
    39  	initial := a.score
    40  	a.score += delta
    41  	if a.score < 0 {
    42  		a.score = 0
    43  	} else if a.score > (a.max - 1) {
    44  		a.score = (a.max - 1)
    45  	}
    46  	final := a.score
    47  	a.Unlock()
    48  
    49  	if initial != final {
    50  		metrics.SetGauge([]string{"memberlist", "health", "score"}, float32(final))
    51  	}
    52  }
    53  
    54  // GetHealthScore returns the raw health score.
    55  func (a *awareness) GetHealthScore() int {
    56  	a.RLock()
    57  	score := a.score
    58  	a.RUnlock()
    59  	return score
    60  }
    61  
    62  // ScaleTimeout takes the given duration and scales it based on the current
    63  // score. Less healthyness will lead to longer timeouts.
    64  func (a *awareness) ScaleTimeout(timeout time.Duration) time.Duration {
    65  	a.RLock()
    66  	score := a.score
    67  	a.RUnlock()
    68  	return timeout * (time.Duration(score) + 1)
    69  }