先来个段子:【并发处理链接数】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,大概真的只能到这里啦,天下没有不散的宴席,就到这儿吧
祝,顺利!!!!!