2019-02-09 01:07:47 -08:00
|
|
|
package rate
|
2019-01-27 22:45:55 -08:00
|
|
|
|
|
|
|
import (
|
|
|
|
"sync/atomic"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Rate struct {
|
2019-03-28 19:41:57 -07:00
|
|
|
bucketSize int64
|
|
|
|
bucketSurplusSize int64
|
|
|
|
bucketAddSize int64
|
|
|
|
stopChan chan bool
|
2019-03-25 20:13:07 -07:00
|
|
|
NowRate int64
|
2019-01-27 22:45:55 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewRate(addSize int64) *Rate {
|
|
|
|
return &Rate{
|
|
|
|
bucketSize: addSize * 2,
|
|
|
|
bucketSurplusSize: 0,
|
|
|
|
bucketAddSize: addSize,
|
|
|
|
stopChan: make(chan bool),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Rate) Start() {
|
|
|
|
go s.session()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Rate) add(size int64) {
|
2019-03-25 20:13:07 -07:00
|
|
|
if res := s.bucketSize - s.bucketSurplusSize; res < s.bucketAddSize {
|
|
|
|
atomic.AddInt64(&s.bucketSurplusSize, res)
|
2019-01-27 22:45:55 -08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
atomic.AddInt64(&s.bucketSurplusSize, size)
|
|
|
|
}
|
|
|
|
|
|
|
|
//回桶
|
|
|
|
func (s *Rate) ReturnBucket(size int64) {
|
|
|
|
s.add(size)
|
|
|
|
}
|
|
|
|
|
|
|
|
//停止
|
|
|
|
func (s *Rate) Stop() {
|
|
|
|
s.stopChan <- true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Rate) Get(size int64) {
|
|
|
|
if s.bucketSurplusSize >= size {
|
|
|
|
atomic.AddInt64(&s.bucketSurplusSize, -size)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
ticker := time.NewTicker(time.Millisecond * 100)
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ticker.C:
|
|
|
|
if s.bucketSurplusSize >= size {
|
|
|
|
atomic.AddInt64(&s.bucketSurplusSize, -size)
|
|
|
|
ticker.Stop()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Rate) session() {
|
|
|
|
ticker := time.NewTicker(time.Second * 1)
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ticker.C:
|
2019-03-25 20:13:07 -07:00
|
|
|
if rs := s.bucketAddSize - s.bucketSurplusSize; rs > 0 {
|
|
|
|
s.NowRate = rs
|
|
|
|
} else {
|
|
|
|
s.NowRate = s.bucketSize - s.bucketSurplusSize
|
|
|
|
}
|
2019-01-27 22:45:55 -08:00
|
|
|
s.add(s.bucketAddSize)
|
|
|
|
case <-s.stopChan:
|
|
|
|
ticker.Stop()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|