http并发demo中,定义的worker chan用完了就没法访问了是什么回事?

jiuzhuc · · 780 次点击 · 开始浏览    置顶
这是一个创建于 的主题,其中的信息可能已经有所发展或是发生改变。

新手不懂提问,在中文网中的一个 高并发demo中,定义了一个worker chan ,然后服务器curl访问了几次后就无法访问了。新手找来找去发现不了问题。下面是我的代码。有大佬可以解答下吗? --- **db.go** ```golang package main // 返回db实例 import ( "database/sql" _ "github.com/go-sql-driver/mysql" "log" "sync" ) type Database struct { database *sql.DB } var dbinstance Database var once sync.Once // 返回数据库实例 func GetDB() *sql.DB { once.Do(func() { log.Println("mysql init") var e error dbinstance.database, e = sql.Open("mysql", "aaa@aaa@123tcp(localhost:3306)/box") if e != nil { log.Println("open sql err: ", e.Error()) } }) return dbinstance.database } ``` --- **job.go** ```golang package main // 定义job接口 import "database/sql" type job interface { Do(db *sql.DB) } ``` --- ** worker.go ** ```golang package main // 打工人 import "log" // 打工人的工作和推出状态 type Worker struct { jobs chan job quit chan bool } func NewWorker() Worker{ return Worker{make(chan job), make(chan bool)} } var database = GetDB() // 打工人开始工作,从chanel接受job func (w Worker) Run( wp chan chan job ) { log.Println("worker start run ") go func() { for { wp <- w.jobs select { case job := <- w.jobs: job.Do(database) // 这里的stop无效,为什么? w.Stop() case q := <- w.quit : if q { log.Println("worker stop ") return } } } }() } // 发送停止工作状态 func (w Worker) Stop(){ log.Println("stop start") go func() { w.quit <- false }() log.Println("stop end") } ``` --- ** workerpool.go** ```golang package main // 打工人的.....池 import "log" // 定义很多打工人、要有多少个人、有多少个工作 type workerpool struct { workers chan chan job workernum int jobqueue chan job } // 创建workerpool func NewWorkerPool(workernum int) *workerpool{ return &workerpool{ workers: make(chan chan job, workernum), workernum: workernum, jobqueue: make(chan job)} } // 根据workernum生成worker func (wp workerpool) init(){ log.Println("workerpool init ") for i := 0; i < wp.workernum;i++{ worker := NewWorker() worker.Run(wp.workers) } } // 工人池开始工作 func (wp workerpool) Run (){ log.Println("workerpool start run ") go func() { for { select { case job := <- wp.jobqueue: log.Println("worker start working ") worker := <- wp.workers worker <- job } } }() } ``` --- ** main.go ** ```golang package main import ( "database/sql" "encoding/json" "fmt" _ "github.com/go-sql-driver/mysql" "log" "net/http" "runtime" "time" ) type netInfo struct { SNCode string Option string Status chan string } // 实现DO接口,接受从http发送来的数据(netInfo),来做查询或插入操作 func (n *netInfo) Do(db *sql.DB) { log.Println("doing sth") db.Ping() if n.Option == "query" { log.Println("doing query") row := db.QueryRow("select SNCode from boxInfo where SNCode = ?", n.SNCode) var res string err := row.Scan(&res) if err != nil{ log.Println("query err: ", err.Error()) n.Status <- "false" } else { log.Println("query res: "+ res + " len: ", len(res)) n.Status <- "true" } }else if n.Option == "save" { log.Println("doing save") _, e := db.Exec("insert into boxInfo(SNCode) values (?)", n.SNCode) if e != nil { log.Println("insert err: ", e.Error()) n.Status <- "false" //time.Sleep(10 * time.Microsecond) } else { n.Status <- "true" // time.Sleep(10 * time.Microsecond) } } n.Status <- "false" time.Sleep(10 * time.Microsecond) } // 根据cpu核心数量来定义最多有多少个打工人 var wp = NewWorkerPool(runtime.NumCPU()) func main() { http.HandleFunc("/", save_info_from_http) log.Println("start") db := GetDB() db.Ping() // workerpool初始化 wp.init() wp.Run() // 这边是为了看wp中还有多少个worker, // 在测试的时候用服务器 curl 一次少一个,还不会自动恢复 // 电脑是六个核心的,也就是访问六次后 就一直被阻塞了。curl一直卡住 go func() { for { log.Println(len(wp.workers)) time.Sleep(time.Second * 3) } }() err := http.ListenAndServe(":8000", nil) if err != nil { log.Fatal("ListenAndServe: ", err.Error()) } } // http访问('/') 调用的函数 func save_info_from_http(w http.ResponseWriter, r *http.Request){ // 解析http的body数据 var netinfo netInfo e := json.NewDecoder(r.Body).Decode(&netinfo) if e != nil{ fmt.Println("json err:", e.Error()) } // Status用于http返回状态,设置为 true或false netinfo.Status = make(chan string) // 给打工人发工作 wp.jobqueue <- &netinfo // 接受返回状态 status := <- netinfo.Status time.Sleep(time.Microsecond) fmt.Fprintf(w,status) } ``` . . . . . . . . 上面是我的代码,想请问下,非缓冲的chanel使用了上限后就没法在访问了。在我的电脑上是六个,也就是curl访问六次后就一直无法返回数据,服务端的日志也没有接受到信息。请论坛大佬解答下

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

780 次点击  
加入收藏 微博
1 回复  |  直到 2021-09-05 16:03:50
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传