使用Go语言每分钟处理1百万请求

在Go中要实现高并发,可以使用 go routine 每个请求 都开启 一个 go routine 去处理,但这样的方式 当 流量大了 就不太可行了,另一种方法 是开启 一个 channel 缓存请求队列 然后 再 for select 循环去 取 任务 ,但是当 请求速度 达到最大 的channel 的时候 请求 就会阻塞, 所以 另一种 方法是结合 上面的2中有点 开启多个channel 每个channel 有一个 携程 去消化 ,这样 又可以利用多核的优势,用能控制携程 的数量。

package pool

import (
	"fmt"
	"sync"
)

//用于保存 的携程池
// 将实现 Job 接口的任务 扔到 任务池里
type Job interface {
	Do() error
}

type myjob struct {}

func(mj *myjob) Do()  error{
	fmt.Println("asdasdasds")
	return nil
}

type JobChan chan Job

type Workerchan chan JobChan

var(
	//Worker 数量
	MaxWorkerPoolSize = 100
)

type Worker struct {
	WorkerPool Workerchan
	JobChannel JobChan
	quit chan bool
}

func NewWorker(workerPool Workerchan) *Worker {
	//worker 自己注册一个管道
	return &Worker{JobChannel: make(chan Job,512),WorkerPool:workerPool}
}

//启动一个Worker
func (w *Worker) Start(){
	go func() {
		for{
			//注册自己的工作 管道 到全局任务管道中
			w.WorkerPool <- w.JobChannel
			select{
				//从自己管道 中获取任务
				case job := <- w.JobChannel:
					//执行任务
					if err := job.Do();err != nil{
						fmt.Printf("excute job failed with err: %v", err)
					}
					//接收退出型号
				case <-w.quit:
					//如果管道中 还有未完成的任务 等待完成后 退出
					if len(w.JobChannel) ==0 {
						return
					}
					w.quit <- true
					continue
			}
		}
	}()
}

//停止Worker
func (w Worker) Stop() {
	go func() {
		w.quit <- true
	}()
}


//分发器
type Dispatcher struct {
	jobs JobChan
	workPool Workerchan
	Workers []*Worker
	quit chan bool
}

func NewDispatcher(size int) *Dispatcher {
	return &Dispatcher{workPool: make(chan JobChan,MaxWorkerPoolSize), quit: make(chan bool,1),jobs: make(JobChan,size)}
}

//退出
func(d *Dispatcher) Close(){
	d.quit <- true
}

func(d *Dispatcher) Run(){
	//新建 一定数量的消费者WOrker
	for i:=0;i<MaxWorkerPoolSize;i++{
		worker := NewWorker(d.workPool)
		d.Workers = append(d.Workers, worker)
		worker.Start()
	}
	go d.dispatch()
}
func(d *Dispatcher) Apply(job Job){
	d.jobs <- job
}
func (d *Dispatcher) dispatch() {
	for{
		select{
		//取出任务
		case job := <- d.jobs:
			go func(job Job) {
				//如果有空闲的worker 可以处理请求
				jobChan := <-d.workPool
				//放入任务 让Worker 处理
				jobChan <- job
			}(job)
		//接收退出
		case <-d.quit:
			//遍历所有Worker 停止工作
			for _,v := range d.Workers{
				v.Stop()
			}
			return
		}
	}
}

func main(){
	wg := sync.WaitGroup{}
	wg.Add(1)
	b := NewDispatcher(1024)
	b.Run()
	//新建 一定数量的 任务 存入 临时存放任务的管道 再分配给 各个Worker
	for i:=0;i<1000000;i++{
		m := myjob{}
		b.Apply(&m)
	}
	wg.Wait()
}

你可能感兴趣的:(Go,golang,高并发,线程池)