【发布时间】:2014-11-03 12:19:43
【问题描述】:
我对 Go 很陌生,正在寻找一种方法来使用 100 个工作人员处理 3000 个查询并确保每个工作人员都有一个连接(MySQL 已经配置了超过 100 个连接)。这是我的尝试:
package main
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
var query *sql.Stmt
func worker(jobs <-chan int, results chan<- int) {
for _ = range jobs {
_, e := query.Exec("a")
if e != nil {
panic(e.Error())
}
results <- 1
}
}
func main() {
workers := 100
db, e := sql.Open("mysql", "foo:foo@/foo")
if e != nil {
panic(e.Error())
}
db.SetMaxOpenConns(workers)
db.SetMaxIdleConns(workers)
defer db.Close()
query, e = db.Prepare("INSERT INTO foo (foo) values(?)")
if e != nil {
panic(e.Error())
}
total := 30000
jobs := make(chan int, total)
results := make(chan int, total)
for w := 0; w < workers; w++ {
go worker(jobs, results)
}
for j := 0; j < total; j++ {
jobs <- j
}
close(jobs)
for r := 0; r < total; r++ {
<-results
}
}
它正在工作,但我不确定是否是最好的方法。
如果您认为这是基于意见或根本不是一个好问题,请将其标记为已关闭并发表评论解释原因。
【问题讨论】:
-
"Concurrency is not parallelism" by Rob Pike 从第 19 分钟开始——“一个非常简单的负载均衡器”,可以在一些工作人员之间分配工作。
-
@tomwilde,当然,我正在阅读它talks.golang.org/2012/waza.slide#40 谢谢!
-
@tomwilde,在该示例中,Rob 没有缓冲频道,但如果我不使用作业总数缓冲频道,那么我只会得到工作完成后的工人数量。跨度>
-
啊,我忘记了一些基本的东西:如果没有某种缓冲,你必须在工人插入结果时耗尽结果。 play.golang.org/p/251IzyIMnu 启动一个耗尽的 goroutine。我的排水器只是将结果推送到列表中;在具有大量工作的真实工作池场景中,您可能希望排水器做一些有趣的事情(可以说是应用程序管道的下一个阶段)。最后,您也可以将作业插入器放在后台 goroutine 中,并将排水保持在前台。
-
避免无缓冲挂起的最简单方法:play.golang.org/p/7EdxQNlX33。只需在单独的 goroutine 中插入作业。
WaitGroup确实是一个不相关的东西,我在同一个示例中添加两者有点混乱(也令人困惑)。