大佬教程收集整理的这篇文章主要介绍了Go 自带的 http/server.go 的连接解析 与 如何结合 master-worker 并发模式,提高单机并发能力,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
从我们启动http.ListenAndServe(port,router)
开始,server.go
内部最终在一个for
循环中的 accept
方法中不停地等待客户端
的连接到来。
每接收到一个accept
就启动一个 goruTine
去处理当前ip
的连接。也就是源码里的go c.serve(ctX)
。这一个步骤在 c.serve(ctX)
它并不是简单的形式:
请求-->处理请求-->返回结果-->断开这个连接-->结束当前的 goruTine
调试结果
与源码分析
显示,正确的形式是下面这样的:为每一个连接的用户启动了一个长连接,serve
方法内部有个超时的设置是c.rwc.SetReadDeadline(time.Time{})
,这样子的情况,如果内部不出错,当前的连接断开的条件是客户端
自己断开,或nat
超时。
这个连接建立后,以ip
为单位,当前的客户端
,此时它的所有http请求
,例如get
,post
,它们都会在这个启动的goruTine
内进行分发
与被处理
。
如果有 100万
个 accept
,就证明有100万
个连接,100万
个ip
与当前server
连接。即是我们说的百万连接
百万连接
不是百万请求
c.serve(...)
源码中的for 死循环
就是负责读取每个请求再分发for {
w,err := c.readrequest(ctX) // 读取一个 http 请求
//...
Servehttp(...)
}
根据我们上面的分析,每一个新连接到来,go 就会启动一个 goruTine
,在源码里面也没有看到有一个量级的限制,也就是达到多少连接就不再接收。我们也知道,服务器是有处理瓶颈的。
所以,在这里插播一个优化点
,就是在server.go
内部做一个连接数目的限制。
@H_496_3@master-worker 模式本身是启动多个worker
线程,去并发读取
有界队列里面的任务,并执行。
我自身已经实现了一个go版本
的@H_496_3@master-worker,做过下面的尝试:
if srv.masterWorkerModel {
// lgh --- way to execute
PoolMaster.AddJob(
masterworker.Job{
Tag:" http server ",Handler: func() {
c.serve(ctX)
fmt.Println("finish job") // 这一句在当前 ip 断开连接后才会输出
},})
}else{
go c.serve(ctX)
}
func (m Master) AddJob(job Job) {
fmt.Println("add a job ")
m.JobQueue <- job // jobQueue 是具备缓冲的
}
// worker
func (w Worker) startWork(master @H_712_195@master) {
go func() {
for {
SELEct {
case job := <-master.JobQueue:
job.doJob(master)
}
}
}()
}
// job
func (j Job) doJob(master Master) {
go func() {
fmt.Println(j.Tag+" --- doing job...")
j.Handler()
}()
}
不难理解它的模式。
现在我们使用生产者--消费者模式
进行假设,连接的产生
是生产者
,<>
是消费者
,因为每一次消费就是启动一个处理的goruTine
。
因为我们在accept
一个请求到<>
,管道输出一个的这个过程中,可以说是没有耗时操作的,这个job
,它很快就被输出了管道。也就是说,消费很快
,那么实际的生产环境
中,我们的worker
工作协程
启动5~10
个就有余了。
考虑如果出现了消费跟不上
的情况,那么多出来的job
将会被缓冲到chAnnel
里面。这种情况可能出现的情景是:
也就说,短时间
大量连接的建立,它的瓶颈在队列的缓冲数
。但是即使瓶颈发生了,它又能很快被分发处理掉。所以说:
func (x XHandler) Servehttp(w http.ResponseWriter,r *http.request) {
//...
if x.MasterWorker {
poolMaster.AddJob(master_worker.Job{
Tag:"normal",XContext:xc,Handler: func(context model.XContext) {
x.HandleFunc(w,r)
},})
return
}
x.HandleFunc(w,r)
//...
}
这样的话,我们就能控制所有连接的并发请求最大数。超出的将会进行排队,等待被执行,而不会因为短时间 http 请求数目不受控暴增
而导致服务器
挂掉。
此外上述第二种
还存在一个:读,过早关闭问题
,这个留给读者尝试解决。
以上是大佬教程为你收集整理的Go 自带的 http/server.go 的连接解析 与 如何结合 master-worker 并发模式,提高单机并发能力全部内容,希望文章能够帮你解决Go 自带的 http/server.go 的连接解析 与 如何结合 master-worker 并发模式,提高单机并发能力所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。