throttle more dynamically if throttling multiple times is needed
This commit is contained in:
37
main.go
37
main.go
@@ -18,9 +18,9 @@ import (
|
|||||||
|
|
||||||
type Conf struct {
|
type Conf struct {
|
||||||
Bandwidth struct {
|
Bandwidth struct {
|
||||||
Max int `yaml:"max"`
|
Max float64 `yaml:"max"`
|
||||||
Min int `yaml:"min"`
|
Min float64 `yaml:"min"`
|
||||||
Step int `yaml:"step"`
|
Step float64 `yaml:"step"`
|
||||||
} `yaml:"bandwidth"`
|
} `yaml:"bandwidth"`
|
||||||
Interval int `yaml:"interval"`
|
Interval int `yaml:"interval"`
|
||||||
Host string `yaml:"host"`
|
Host string `yaml:"host"`
|
||||||
@@ -43,7 +43,7 @@ type UploadManager struct {
|
|||||||
LastOver time.Time
|
LastOver time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m UploadManager) Upload() (int, error) {
|
func (m UploadManager) Upload() (float64, error) {
|
||||||
tcCmd := exec.Command("tc", "qdisc", "show", "dev", conf.UploadInterface)
|
tcCmd := exec.Command("tc", "qdisc", "show", "dev", conf.UploadInterface)
|
||||||
out, err := tcCmd.CombinedOutput()
|
out, err := tcCmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -54,14 +54,14 @@ func (m UploadManager) Upload() (int, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
return up, nil
|
return float64(up), nil
|
||||||
} else {
|
} else {
|
||||||
return 0, fmt.Errorf("could not parse bandwidth from tc")
|
return 0, fmt.Errorf("could not parse bandwidth from tc")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m UploadManager) SetUpload(upload int) (int, error) {
|
func (m UploadManager) SetUpload(upload float64) (float64, error) {
|
||||||
tcCmd := exec.Command("tc", "qdisc", "change", "dev", conf.UploadInterface, "root", "cake", "bandwidth", fmt.Sprintf("%dMbit", upload))
|
tcCmd := exec.Command("tc", "qdisc", "change", "dev", conf.UploadInterface, "root", "cake", "bandwidth", fmt.Sprintf("%dMbit", int(upload)))
|
||||||
log.Debugf("[TC] exec %s", tcCmd.String())
|
log.Debugf("[TC] exec %s", tcCmd.String())
|
||||||
out, err := tcCmd.CombinedOutput()
|
out, err := tcCmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -89,7 +89,7 @@ func doPing(host string, count int, interval time.Duration) (*ping.Statistics, e
|
|||||||
return pinger.Statistics(), nil
|
return pinger.Statistics(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m UploadManager) isBWInRange(bw int) bool {
|
func (m UploadManager) isBWInRange(bw float64) bool {
|
||||||
return bw <= conf.Bandwidth.Max && bw >= conf.Bandwidth.Min
|
return bw <= conf.Bandwidth.Max && bw >= conf.Bandwidth.Min
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,13 +104,14 @@ func (m UploadManager) pingWorker() error {
|
|||||||
|
|
||||||
if stats.AvgRtt.Milliseconds() >= conf.ThrottlePingThreshold {
|
if stats.AvgRtt.Milliseconds() >= conf.ThrottlePingThreshold {
|
||||||
m.LastOver = time.Now()
|
m.LastOver = time.Now()
|
||||||
|
lastStep := conf.Bandwidth.Step * 0.5
|
||||||
up, err := m.Upload()
|
up, err := m.Upload()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("ping %s over threshold detected, starting extended pings...", stats.AvgRtt)
|
log.Infof("ping %s over threshold detected, starting extended pings...", stats.AvgRtt)
|
||||||
for stats.AvgRtt.Milliseconds() >= conf.ThrottlePingThreshold && m.isBWInRange(up-conf.Bandwidth.Step) {
|
for stats.AvgRtt.Milliseconds() >= conf.ThrottlePingThreshold && m.isBWInRange(up-lastStep*2) {
|
||||||
stats, err = doPing(conf.Host, conf.ConformationPPP, time.Second)
|
stats, err = doPing(conf.Host, conf.ConformationPPP, time.Second)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warningf("ping to %s failed: %v", conf.Host, err)
|
log.Warningf("ping to %s failed: %v", conf.Host, err)
|
||||||
@@ -119,14 +120,26 @@ func (m UploadManager) pingWorker() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if stats.AvgRtt.Milliseconds() >= conf.ThrottlePingThreshold {
|
if stats.AvgRtt.Milliseconds() >= conf.ThrottlePingThreshold {
|
||||||
log.Infof("extended ping %s, adjusting upload TC %d->%d", stats.AvgRtt, up, up-conf.Bandwidth.Step)
|
lastStep *= 2
|
||||||
up, err = m.SetUpload(up - conf.Bandwidth.Step)
|
newUp := up - lastStep
|
||||||
|
|
||||||
|
if !m.isBWInRange(newUp) {
|
||||||
|
newUp = conf.Bandwidth.Min
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("extended ping %s, adjusting upload TC %f->%f", stats.AvgRtt, up, newUp)
|
||||||
|
up, err = m.SetUpload(newUp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
m.LastOver = time.Now()
|
m.LastOver = time.Now()
|
||||||
|
|
||||||
|
if newUp == conf.Bandwidth.Min {
|
||||||
|
log.Infof("reached lower limit, stopping extended pings")
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
time.Sleep(20 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
}
|
}
|
||||||
} else if time.Since(m.LastOver) >= time.Duration(conf.TryRestoringAfter)*time.Minute {
|
} else if time.Since(m.LastOver) >= time.Duration(conf.TryRestoringAfter)*time.Minute {
|
||||||
up, err := m.Upload()
|
up, err := m.Upload()
|
||||||
|
Reference in New Issue
Block a user