【发布时间】:2014-11-09 11:35:53
【问题描述】:
package main
import ()
func main() {
msgQueue := make(chan int, 1000000)
netAddr := "127.0.0.1"
token := make(chan int, 10)
for i := 0; i < 10; i++ {
token <- i
}
go RecvReq(netAddr, msgQueue)
for {
select {
case req := <-msgQueue:
go HandleReq(req, token)
}
}
}
func RecvReq(addr string,msgQueue chan int){
msgQueue<-//get from network
}
func HandleReq(msg int, token chan int) {
//step 1
t := <-token
//step 2
//codo here...(don't call runtime.park)
//step 3
//code here...(may call runtime.park)
//step 4
token <- t
}
系统:1cpu 2core
Go 版本:go1.3 linux/amd64
问题描述:
msgQueue revc 一直由 RecvReq 请求,然后主 goroutine 一直创建新的 goroutine,但是等待的 goroutine 一直等待。前 10 个 goroutine 在第 3 步停止,新的 goroutine 在第 1 步停止。
Q1:如何让等待的goroutine在新的goroutine一直被创建的时候运行。
Q2:如何平衡RevcReq和HandleReq? Revc msg 速率比 Handle msg 快 10 倍。
【问题讨论】:
-
您似乎在使用
token通道缓冲区之前对其进行了填充。然后您将其弹出 (10-1=9) .. 然后将值直接放回 (9+1=10)。因此,您的token频道基本上是无缓冲的。因此,算法两侧的处理速度大相径庭。我建议停止token预填充和缓冲区对齐。 -
你可以让十个 goroutine 一直在运行,每个 goroutine 都有一个令牌作为局部变量,也许。我不确定这些观察是否有帮助,但是 1) 调度程序不能保证给定的 goroutine 将运行,直到几乎没有其他东西可以运行,2) 巨大的缓冲通道可能导致奇怪的行为,3) 没有完整的很难调试有问题的可运行代码示例。
-
Heh 和 4) 确保您设置了 GOMAXPROCS。 :)
-
为什么不使用真正的消息队列,比如 nsq 或 rabbit?