fastHttp服务端处理请求的过程
Github 地址 https://github.com/valyala/fasthttp
fastHttp 服务端的处理请求的过程
工作过程
主要代码
设置监听地址 server.go
func (s *Server) ListenAndServe(addr string) error {
ln, err := net.Listen("tcp4", addr)
if err != nil {
return err
}
if tcpln, ok := ln.(*net.TCPListener); ok {
return s.Serve(tcpKeepaliveListener{
TCPListener: tcpln,
keepalive: s.TCPKeepalive,
keepalivePeriod: s.TCPKeepalivePeriod,
})
}
return s.Serve(ln)
}
初始化协程池并启动,当接收到请求后,调 wp.Serve 交给协程池去处理请求 server.go
func (s *Server) Serve(ln net.Listener) error { ..... wp := &workerPool{
WorkerFunc: s.serveConn,
MaxWorkersCount: maxWorkersCount,
LogAllErrors: s.LogAllErrors,
Logger: s.logger(),
connState: s.setState,
}
wp.Start() for {
if c, err = acceptConn(s, ln, &lastPerIPErrorTime); err != nil {
wp.Stop()
return err
}
s.setState(c, StateNew)
atomic.AddInt32(&s.open, 1)
if !wp.Serve(c) {
atomic.AddInt32(&s.open, -1)
s.writeFastError(c, StatusServiceUnavailable,
"The connection cannot be served because Server.Concurrency limit exceeded")
c.Close()
s.setState(c, StateClosed)
}
}
......
}
获取请求的句柄 server.go
func acceptConn(s *Server, ln net.Listener, lastPerIPErrorTime *time.Time) (net.Conn, error) {
for {
c, err := ln.Accept()
......
return c, nil
}
}
协程池处理请求 workerPool.go
// 从协程池中获取某个协程对应的 句柄channel,然后将 3 中获取到的 请求句柄推入channel
func (wp *workerPool) Serve(c net.Conn) bool {
ch := wp.getCh()
if ch == nil {
return false
}
ch.ch <- c
return true
} // 这个是协程池工作最重要的部分,获取协程池中协程对应的channel
func (wp *workerPool) getCh() *workerChan {
var ch *workerChan
createWorker := false wp.lock.Lock()
ready := wp.ready
n := len(ready) - 1
// 获取协程句柄channel失败,如果可以新建协程的话就进行新建,如果不可用新建的话,返回的句柄channel为nil,本次请求被拒绝服务
if n < 0 {
if wp.workersCount < wp.MaxWorkersCount {
createWorker = true
wp.workersCount++
}
} else {
// 获取协程句柄channel 成功
ch = ready[n]
ready[n] = nil
wp.ready = ready[:n]
}
wp.lock.Unlock() if ch == nil {
if !createWorker {
return nil
}
// 新建协程句柄,且为之创建协程
vch := wp.workerChanPool.Get()
ch = vch.(*workerChan)
go func() {
wp.workerFunc(ch)
wp.workerChanPool.Put(vch)
}()
}
return ch
} func (wp *workerPool) workerFunc(ch *workerChan) {
var c net.Conn
var err error
for c = range ch.ch {
//协程的句柄channel 出现nil的时候 当前协程就退出了
if c == nil {
break
} // wp.WorkerFunc是在初始化协程池的时候注册的方法,是 s.serveConn
if err = wp.WorkerFunc(c); err != nil && err != errHijacked {
......
}
}
......
if !wp.release(ch) {
break
}
}
.....
// 协程的句柄channel 出现nil的时候 当前协程就退出了,退出后将work协程数自减
wp.workersCount--
......
} // 请求处理完之后 将当前协程的句柄channel 放入协程池的ready切片中,待下次获取协程的句柄channel的时候进行复用(复用这个句柄channel就相当于复用了对应的协程)
func (wp *workerPool) release(ch *workerChan) bool {
ch.lastUseTime = time.Now()
wp.lock.Lock()
if wp.mustStop {
wp.lock.Unlock()
return false
}
wp.ready = append(wp.ready, ch)
wp.lock.Unlock()
return true
}
实际处理请求的方法 server.go
func (s *Server) serveConn(c net.Conn) (err error) {
.....
//上下文对象复用并初始化上下文
ctx := s.acquireCtx(c)
......
//执行在初始化server的时候自定义的 逻辑
if continueReadingRequest {
s.Handler(ctx)
}
.....
// 处理http响应
}
高效的原因
- fastHttp 协程池 详情见 2.2.2 、2.2.4
- fastHttp 对象复用
- 协程channle对象 复用 详见2.2.4 的 getCh() 函数
- 上下文对象复用 详见2.2.5
注:
本文为自己对fastHttp的理解,如有疑问,欢迎一起讨论交流
如需转载请注明出处:https://www.cnblogs.com/zhuchenglin/p/14358612.html
fastHttp服务端处理请求的过程的更多相关文章
- Query通过Ajax向PHP服务端发送请求并返回JSON数据
Query通过Ajax向PHP服务端发送请求并返回JSON数据 服务端PHP读取MYSQL数据,并转换成JSON数据,传递给前端Javascript,并操作JSON数据.本文将通过实例演示了jQuer ...
- jQuery通过Ajax向PHP服务端发送请求并返回JSON数据
SON(JavaScript Object Notation) 是一种轻量级的数据交换格式.易于人阅读和编写,同时也易于机器解析和生成.JSON在前后台交互的过程中发挥着相当出色的作用.请接着往下看教 ...
- Request对象 --web浏览器向web服务端的请求
一]Request对象常用方法 1)StringBuffer getRequestURL() url表示访问web应用的完整路径 2)Stri ...
- 服务端CURL请求
服务端与服务端之间,也存在接口编程. 比如我们网站服务端,需要发送短信.发送邮件.查询快递等,都需要调用第三方平台的接口. 1.php中发送请求 ①file_get_contents函数 :传递完整的 ...
- 基于jFinal建立简单的服务端-接收请求并返回指定内容
本菜鸡是一名弱弱的测试工程师,最近完成了一个支付相关的项目,项目工作中,需要建立一个模拟支付宝的网关,主要是接收请求并返回数据.作为一名没有丝毫开发经验的菜鸡,初期入门相当费劲,主要还是思维上的转变. ...
- Visual Studio 2015 Bowser Link的功能不停的向服务端发送请求
Visual Studio 2015新建的mvc项目 默认在每个视图上生成一些JavaScript脚本
- 在java服务端判断请求是来自哪个终端
在servlet中,我们可以获取到HttpServletRequest,然后通过HttpServletRequest的getHeader("User-Agent")方法获取请求头中 ...
- ajax对服务端发送请求
//兼容处理获取ajax对象 var req = ''; if (window.XMLHttpRequest) req = new XMLHttpRequest(); else req = ...
- nextjs 服务端渲染请求参数
Post.getInitialProps = async function (context) { const { id } = context.query const res = await fet ...
随机推荐
- 漫画 | 小公司卧薪尝胆三年,意外拿到美团offer
今天给大家分享一篇,非科班出生的野生前端从业者的励志成长故事,故事的主人公王大拿(化名),在小公司打杂三年后,意外拿到了美团的offer,成功进阶大厂,跳槽到了美团的核心外卖事业部. 事故主人公:王大 ...
- ASP.NET Core路由中间件[3]: 终结点(Endpoint)
到目前为止,ASP.NET Core提供了两种不同的路由解决方案.传统的路由系统以IRouter对象为核心,我们姑且将其称为IRouter路由.本章介绍的是最早发布于ASP.NET Core 2.2中 ...
- 我的开源项目在五个月内超过了 600 star
其实我在 2016 年年底就开始写了这个项目:Forest,一个能够将 HTTP 的所有请求信息(包括 URL .Header 以及 Body 等信息)绑定到您自定义的 Interface 方法上,能 ...
- Npoi XWPF Word 导出时插入图片无法显示 bug 完美解决
一.来自客户的需求 最近客户来个新需求生成一个word 标签纸,并且需要在标签纸上插入一个logo,并且将erp 中的数据取出来自动写在文档上,不由得淡淡一笑,这不难呀! 于是乎我就写下了这样的代码: ...
- DB2在渗透中的应用(转载)
原文地址:http://drops.wooyun.org/tips/16673 0x00 DB2简介 DB2是IBM公司推出关系型数据库管理系统. 现今DB2主要包含以下三个系列: DB2 for L ...
- mysql 应用 持续更新2 转载
作者:彼岸Queen旅行链接:https://www.zhihu.com/question/27334963/answer/266624031来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非 ...
- 关于.NET中的控制反转(三)- 依赖注入之 Autofac
一.Autofac简介 Autofac和其他容器的不同之处是它和C#语言的结合非常紧密,在使用过程中对你的应用的侵入性几乎为零,更容易与第三方的组件集成.Autofac的主要特性如下: 组件侵入性为零 ...
- STP、PVST、MST协议
• STP:生成树协议 ○ 阻止环形链路的广播风暴 • PVST:VLAN生成树 ○ 是STP的进阶版不仅能阻止广播风暴,还可以做到基于VLAN进行流量均衡. ...
- 【Oracle】下载11.2.0.4的地址
https://updates.oracle.com/download/13390677.html 这个地址就是下载Oracle 11.2.0.4版本的地址,需要有metalink账号才可以下载
- XSS - Pikachu
概述: Cross-Site Scripting 简称为"CSS",为避免与前端叠成样式表的缩写"CSS"冲突,故又称XSS.一般XSS可以分为如下几种常见类型 ...