How to use Golang to write detailed code for high concurrency

  • 2020-06-07 04:39:59
  • OfStack

preface

Before 1 straight Golang how to deal with high concurrent http request 1 confused, these days also checked a lot of related blogs, vaguely understand, do not know how to write specific code

In the afternoon, I happened to see an article written by a foreign technician on the developer's headline APP, which used Golang to deal with millions of requests per minute. After reading the code in the article, I wrote the code once by myself

The core points

The request is queued, and an worker pool (pool) is formed by a fixed number of goroutine (for example, the number of CPU cores). The worker in the workder pool reads the queue to perform the task

The sample code

The following code is simplified according to my own understanding, mainly to express my personal thoughts. In the actual back-end development, it is modified according to the actual scenario


func doTask() {
 // Take the hype ( simulation )
 time.Sleep(200 * time.Millisecond)
 wg.Done()
}

// Here's the simulated http interface , Each request is abstracted as 1 a job
func handle() {
 //wg.Add(1)
 job := Job{}
 JobQueue <- job
}

var (
 MaxWorker = 1000
 MaxQueue = 200000
 wg  sync.WaitGroup
)

type Worker struct {
 quit chan bool
}

func NewWorker() Worker {
 return Worker{
  quit: make(chan bool)}
}

// Start method starts the run loop for the worker, listening for a quit channel in
// case we need to stop it
func (w Worker) Start() {
 go func() {
  for {
   select {
   case <-JobQueue:
    // we have received a work request.
    doTask()
   case <-w.quit:
    // we have received a signal to stop
    return
   }
  }
 }()
}

// Stop signals the worker to stop listening for work requests.
func (w Worker) Stop() {
 go func() {
  w.quit <- true
 }()
}

type Job struct {
}

var JobQueue chan Job = make(chan Job, MaxQueue)

type Dispatcher struct {
}

func NewDispatcher() *Dispatcher {
 return &Dispatcher{}
}

func (d *Dispatcher) Run() {
 // starting n number of workers
 for i := 0; i < MaxWorker; i++ {
  worker := NewWorker()
  worker.Start()
 }
}

test


func Benchmark_handle(b *testing.B) {
 runtime.GOMAXPROCS(runtime.NumCPU())
 d := NewDispatcher()
 d.Run()
 for i:=0;i<10000;i++ {
  wg.Add(1)
  handle()
 }
 wg.Wait()
}

The test results


pkg: golang-study-demo/goroutine
1 2029931652 ns/op
PASS

1w tasks were put into the queue,1000 worker tasks were executed, each task took 200ms time, and the completion of the task required more than 2s

The above is just my personal opinion. I don't know if my understanding of Golang concurrent programming is correct or not. If there are any mistakes, I hope you can give me some advice

conclusion


Related articles: