在pacer.go中增加如下代码.
pacer接口实现类作用就是控制吞吐量, 什么时间吞吐量多少.
摸高模式(梯度加压)效果如下
type HighTouchPacer struct {
StartAt Rate
Slope float64
HighTouchTimes float64
PerHighTouchDuration float64
PerStayDuration float64
}
func (h HighTouchPacer) Rate(elapsed time.Duration) float64 {
a := h.Slope
//x := elapsed.Seconds()
xp := elapsed.Seconds()
b := h.StartAt.hitsPerNs() * 1e9
l := h.PerHighTouchDuration + h.PerStayDuration
count := float64(0)
for xp > l {
xp = xp - l
count = count + 1
}
if xp >= h.PerHighTouchDuration {
return a*h.PerHighTouchDuration*(count+1) + b
}
return a*h.PerHighTouchDuration*count + a*xp + b
}
// Pace determines the length of time to sleep until the next hit is sent.
func (h HighTouchPacer) Pace(elapsed time.Duration, hits uint64) (time.Duration, bool) {
switch {
case h.StartAt.Per == 0 || h.StartAt.Freq == 0:
return 0, false // Zero value = infinite rate
case h.StartAt.Per < 0 || h.StartAt.Freq < 0:
return 0, true
}
expectedHits := h.hits(elapsed)
if hits == 0 || hits < uint64(expectedHits) {
// Running behind, send next hit immediately.
return 0, false
}
rate := h.Rate(elapsed)
interval := math.Round(1e9 / rate)
if n := uint64(interval); n != 0 && math.MaxInt64/n < hits {
// We would overflow wait if we continued, so stop the attack.
return 0, true
}
delta := float64(hits+1) - expectedHits
wait := time.Duration(interval * delta)
return wait, false
}
// hits returns the number of hits that have been sent during an attack
// lasting t nanoseconds. It returns a float so we can tell exactly how
// much we've missed our target by when solving numerically in Pace.
func (h HighTouchPacer) hits(t time.Duration) float64 {
if t < 0 {
return 0
}
a := h.Slope
x := t.Seconds()
xp := t.Seconds()
b := h.StartAt.hitsPerNs() * 1e9
l := h.PerHighTouchDuration + h.PerStayDuration
count := float64(0)
for xp > l {
xp = xp - l
count = count + 1
}
if xp >= h.PerHighTouchDuration {
return b*x + a*math.Pow(h.PerHighTouchDuration*(count+1), 2)/2 + h.PerStayDuration*a*h.PerHighTouchDuration*((1+count)*count/2) + (xp-h.PerHighTouchDuration)*a*h.PerHighTouchDuration*(count+1)
}
return b*x + a*math.Pow(h.PerHighTouchDuration*count+xp, 2)/2 + h.PerStayDuration*a*h.PerHighTouchDuration*((1+count)*count/2)
}