Go http server 高併發

先來個段子:【併發處理鏈接數】web

多高?算法

很高!服務器

到底多高?網絡

沒有一億,都算少了!併發

.分佈式

.性能

.學習

而後就沒有而後了。。。fetch

「段子 END」ui

 

這就是目前中國企業的通病:提個概念,沒有答案,最後形成概念也模糊了,其實,我感受它根本不知道要幹什麼!從頭到腳都是病啊!

 

下面,咱們談談,web服務鏈接和速度問題

如今,隨着網絡普及,對於服務的響應速度和併發處理能力都有了不一樣尋常的要求

因此,對於服務的標準也愈來愈高

我以最簡潔的說法把問題描述一下,其它不解釋

1. 響應速度,是指:對於客戶端請求的事務處理時間的快慢,通常,要用分佈式處理來快速獲得能夠分佈式處理的事務的結果

2. 併發處理,是指:對於客戶端的請求的事務能夠並行在服務端處理,一盤要有線程池,工做者的邏輯概念介入

須要澄清一個概念,併發不是指客戶端併發鏈接到服務器!!!!!!,這個是大多數中國開發者的死穴,並且死不悔改!!!!!

因此,你要好好考慮一下,這些執拗的人羣裏,算不算有你有一個!!!

3. 服務器硬件性能越高,天然併發能力越高(多CPU,多內核);分佈式算法優秀,天然響應越快了

好吧,關於文字,我就算這麼多,個人博文不是教小白上路的,而是給學者指出路上哪裏有坑的。但願你好好揣摩,也許直到今天你也是不懂web的吧

//DEMO

下面,仍是上例程,出自於國外的一篇文章。

原做者,出於公司商業性質,說了90%的話,剩下的10%有問題,這些都體如今他給出的源碼裏露出了馬腳,固然這就是把正確改不能用的代價。原諒他吧,擱你身上也同樣。這就是公司,萬惡的公司,不關做者的事,他只是想得意一下而已!

若是你看了他的文章和源碼,你仍是跑不起來的,因此,聽個人,看個人吧

仍是那句話,不過多解釋,但不會不說明,若是你須要掰着指頭教你寫1,2,3,那麼請回到親愛的小學,去找老去的園丁吧,哈哈哈(對了,推薦電影:神祕代碼)

/////////////////////////////////////

//go-server-effic.go

package main

import (
  "fmt"
  "os"
  "runtime"
  "net/http"
)

var (
  //Max_Num = os.Getenv("MAX_NUM")
  MaxWorker = runtime.NumCPU()
  MaxQueue = 1000
)

type Serload struct {
  pri string
}

type Job struct {
  serload Serload
}

var JobQueue chan Job

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:
        // excute job
        fmt.Println(job.serload.pri)
      case <- w.Quit:
        return
      }
    }
  }()
}

func (w Worker) Stop() {
  go func() {
    w.Quit <- true
  }()
}

type Dispatcher struct {
  MaxWorkers int
  WorkerPool chan chan Job
  Quit chan bool
}

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
    }
  }
}

func entry(res http.ResponseWriter, req *http.Request) {
  // fetch job
  work := Job{serload:Serload{pri:"Just do it"}}
  JobQueue <- work
  fmt.Fprintf(res, "Hello World ...again")
}

func init() {
  runtime.GOMAXPROCS(MaxWorker)
  JobQueue = make(chan Job, MaxQueue)
  dispatcher := NewDispatcher(MaxWorker)
  dispatcher.Run()
}

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")
}

//結果

 

Finally:

爲了不你們陷入困境,我只給你們指出思路,這樣就不會引導你們進入似懂非懂的怪圈

1. 協程池裏的協程數目應該與CPU內核數一致,這個好理解,這時候效率和利用率都是最高的

2. 每一個協程運行一個工做者出來處理客戶端請求(咱們就是簡單的打印出「Just do it」而已,不在於複雜度,在於處理流程)

好吧,再簡單講講代碼

首先,請本身去學習:Go的協程和渠道(文字概念能夠去看書,例子,我以前的博文都有涉及,保證都是可運行的例子)

這個demo的核心:

1. 工做者工做協程,掛入調度器,取Job,執行Job,周而復始

2. 調度器,從Job隊列取Job,分配給工做者,周而復始

3. web響應裏,模擬了客戶的請求-Job,並將此Job放入Job隊列,只有有客戶端請求,就周而復始的工做

好了,真的好了

 

師傅領進門,修行在我的

 

哈哈,我是教"孫悟空"的導師!,哈哈哈哈哈

祝你Go的快,Go的好,Go的高

 

關於Go,大概真的只能到這裏啦,天下沒有不散的宴席,就到這兒吧

祝,順利!!!!!

相關文章
相關標籤/搜索