使用场景
不需要实时返回结果的处理,通常是异步的操作或者用户无感知的操作,例如:数据打点,文件上传等
代码来源
http://marcio.io/2015/07/handling-1-million-requests-per-minute-with-golang/
https://www.cnblogs.com/woodzcl/p/7602530.html
优化代码
main.go
package main import ( "fmt" "jobtest/tasks" "net/http" "os" ) type Test struct { Name string } func (t *Test) Exec() error { fmt.Println("Here is:", t.Name) return nil } type Test2 struct { Name string } func (t *Test2) Exec() error { fmt.Println("Here is another:", t.Name) return nil } func entry(res http.ResponseWriter, req *http.Request) { var work tasks.Job // fetch job t := Test{Name: "Coeus"} work = &t tasks.JobQueue <- work t2 := Test2{Name: "Coeus"} work = &t2 tasks.JobQueue <- work fmt.Fprintf(res, "Hello World ...again") } func main() { Port := "8086" IsHttp := true arg_num := len(os.Args) if 2 <= arg_num { Port = os.Args[1] } if 3 <= arg_num { if os.Args[2] == "true" { IsHttp = true } else { IsHttp = false } } fmt.Printf("server is http %t\n", IsHttp) fmt.Println("server listens at ", Port) http.HandleFunc("/", entry) var err error if IsHttp { err = http.ListenAndServe(":"+Port, nil) } else { err = http.ListenAndServeTLS(":"+Port, "server.crt", "server.key", nil) } if err != nil { fmt.Println("Server failure /// ", err) } fmt.Println("quit") }
tasks/define.go
package tasks import "runtime" var ( MaxWorker = runtime.NumCPU() MaxQueue = 512 ) type Job interface { Exec() error } var JobQueue chan Job
tasks/worker.go
package tasks import "fmt" type Worker struct { WorkerPool chan chan Job JobChannel chan Job Quit chan bool } func NewWorker(workPool chan chan Job) Worker { return Worker{ WorkerPool: workPool, JobChannel: make(chan Job), Quit: make(chan bool), } } func (w Worker) Start() { go func() { for { w.WorkerPool <- w.JobChannel select { case job := <-w.JobChannel: if err := job.Exec(); err != nil { fmt.Printf("excute job failed with err: %v", err) } case <-w.Quit: return } } }() } func (w Worker) Stop() { go func() { w.Quit <- true }() }
tasks/dispatcher.go
package tasks import "runtime" type Dispatcher struct { MaxWorkers int WorkerPool chan chan Job Quit chan bool } func init() { runtime.GOMAXPROCS(MaxWorker) JobQueue = make(chan Job, MaxQueue) dispatcher := NewDispatcher(MaxWorker) dispatcher.Run() } func NewDispatcher(maxWorkers int) *Dispatcher { pool := make(chan chan Job, maxWorkers) return &Dispatcher{MaxWorkers: maxWorkers, WorkerPool: pool, Quit: make(chan bool)} } func (d *Dispatcher) Run() { for i := 0; i < d.MaxWorkers; i++ { worker := NewWorker(d.WorkerPool) worker.Start() } go d.Dispatch() } func (d *Dispatcher) Stop() { go func() { d.Quit <- true }() } func (d *Dispatcher) Dispatch() { for { select { case job := <-JobQueue: go func(job Job) { jobChannel := <-d.WorkerPool jobChannel <- job }(job) case <-d.Quit: return } } }
如main.go中所示,你只需实现接口Job的Exec方法,就可以执行任意你要做的事情了