これでよしであってくれーーー〜ーーーーーーーーーー!!!!!!!!
package main
import (
"fmt"
"sync"
"time"
)
func main() {
wg := sync.WaitGroup{}
mu := sync.RWMutex{}
processing := 0
before := 0
queue := []interface{}{}
go func() {
for {
fmt.Println(time.Now().Format(time.RFC3339), "processing", processing-before)
before = processing
time.Sleep(time.Second)
}
}()
process := func(wg *sync.WaitGroup, l sync.Locker) {
// ここが実際のリクエストを処理するところ
l.Lock() // リソースのロックを行って 1 つずつ処理するようにする
defer l.Unlock()
defer wg.Done()
time.Sleep(100 * time.Millisecond) // 1 処理辺り 100 ms なら最大でも 1 sec 10 になるやろうという雑な ...
var item interface{}
item, queue = queue[0], queue[1:]
// 実際にここで item.(type) で request を分けて request を投げる
processing++
fmt.Println("\\tprocessing", processing, item)
}
adder := func(name string) {
defer wg.Done()
count := 100
for {
// ここは実際にプロキシがリクエストを投げる直前のところみたいなイメージ
wg.Add(1)
// queue に足す item は本来であればリクエスト情報を含む何かしらにする(順序担保確認のため count と name を含ませてる
queue = append(queue, fmt.Sprintf("%s_%d", name, count))
go process(&wg, &mu) // こういう感じでリクエストをゴルーチンで生成する
count--
if count == 0 {
break
}
}
}
// 複数箇所から叩かれるみたいな想定
wg.Add(1)
go adder("hoge")
wg.Add(1)
go adder("foo")
wg.Add(1)
go adder("bar")
wg.Wait()
fmt.Println("Done")
}
2020-07-15T18:23:14+09:00 processing 10
processing 30 hoge_79
processing 31 bar_91
processing 32 hoge_78
processing 33 bar_90
processing 34 bar_89
processing 35 bar_88
processing 36 bar_87
processing 37 bar_86
processing 38 bar_85
2020-07-15T18:23:15+09:00 processing 9
processing 39 bar_84
processing 40 hoge_75
processing 41 hoge_74
processing 42 hoge_73
processing 43 hoge_72
processing 44 hoge_71
processing 45 hoge_70
processing 46 hoge_69
processing 47 hoge_68
processing 48 foo_99
2020-07-15T18:23:16+09:00 processing 10
processing 49 foo_98
processing 50 foo_97
動作確認してみると, foo, bar, hoge それぞれ別に投げてるリクエスト群が順番に秒間最大 10 程度処理されてるので一応要件にはそってるはず ......
なんか絶対もっと良い感じにするのはありそうなんだよな