使用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()
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Go语言中,可以使用标准库中的`net/http`包来进行HTTP请求处理HTTP响应。 下面是一个简单的HTTP GET请求的示例代码: ```go package main import ( "fmt" "io/ioutil" "net/http" ) func main() { resp, err := http.Get("https://www.baidu.com") if err != nil { fmt.Println("http get error:", err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("read body error:", err) return } fmt.Println(string(body)) } ``` 在上面的代码中,`http.Get`函数用于发送HTTP GET请求,并返回一个`*http.Response`类型的响应对象。通过`resp.Body`可以获取响应的正文内容,需要在使用完毕后记得关闭。 对于HTTP响应,可以通过`resp.StatusCode`获取状态码,通过`resp.Header`获取响应头,通过`ioutil.ReadAll(resp.Body)`读取响应正文内容。 下面是一个简单的HTTP POST请求的示例代码: ```go package main import ( "bytes" "fmt" "io/ioutil" "net/http" ) func main() { url := "http://httpbin.org/post" data := []byte(`{"name": "John", "age": 30}`) resp, err := http.Post(url, "application/json", bytes.NewReader(data)) if err != nil { fmt.Println("http post error:", err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("read body error:", err) return } fmt.Println(string(body)) } ``` 在上面的代码中,`http.Post`函数用于发送HTTP POST请求,并返回一个`*http.Response`类型的响应对象。需要注意的是,在发送POST请求时需要指定请求头`Content-Type`为`application/json`,并将请求正文通过`bytes.NewReader`转为`io.Reader`类型。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值