1. Github 地址 https://github.com/valyala/fasthttp

  2. fastHttp 服务端的处理请求的过程

    1. 工作过程

    2. 主要代码

      1. 设置监听地址 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)
        }
      2. 初始化协程池并启动,当接收到请求后,调 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)
      }
      }
      ......
      }
      1. 获取请求的句柄 server.go

        func acceptConn(s *Server, ln net.Listener, lastPerIPErrorTime *time.Time) (net.Conn, error) {
        for {
        c, err := ln.Accept()
        ......
        return c, nil
        }
        }
      2. 协程池处理请求 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
        }
      3. 实际处理请求的方法 server.go

        func (s *Server) serveConn(c net.Conn) (err error) {
        .....
        //上下文对象复用并初始化上下文
        ctx := s.acquireCtx(c)
        ......
        //执行在初始化server的时候自定义的 逻辑
        if continueReadingRequest {
        s.Handler(ctx)
        }
        .....
        // 处理http响应
        }
  3. 高效的原因

    1. fastHttp 协程池 详情见 2.2.2 、2.2.4
    2. fastHttp 对象复用
      1. 协程channle对象 复用 详见2.2.4 的 getCh() 函数
      2. 上下文对象复用 详见2.2.5

注:

本文为自己对fastHttp的理解,如有疑问,欢迎一起讨论交流

如需转载请注明出处:https://www.cnblogs.com/zhuchenglin/p/14358612.html

fastHttp服务端处理请求的过程的更多相关文章

  1. Query通过Ajax向PHP服务端发送请求并返回JSON数据

    Query通过Ajax向PHP服务端发送请求并返回JSON数据 服务端PHP读取MYSQL数据,并转换成JSON数据,传递给前端Javascript,并操作JSON数据.本文将通过实例演示了jQuer ...

  2. jQuery通过Ajax向PHP服务端发送请求并返回JSON数据

    SON(JavaScript Object Notation) 是一种轻量级的数据交换格式.易于人阅读和编写,同时也易于机器解析和生成.JSON在前后台交互的过程中发挥着相当出色的作用.请接着往下看教 ...

  3. Request对象 --web浏览器向web服务端的请求

    一]Request对象常用方法        1)StringBuffer getRequestURL()            url表示访问web应用的完整路径            2)Stri ...

  4. 服务端CURL请求

    服务端与服务端之间,也存在接口编程. 比如我们网站服务端,需要发送短信.发送邮件.查询快递等,都需要调用第三方平台的接口. 1.php中发送请求 ①file_get_contents函数 :传递完整的 ...

  5. 基于jFinal建立简单的服务端-接收请求并返回指定内容

    本菜鸡是一名弱弱的测试工程师,最近完成了一个支付相关的项目,项目工作中,需要建立一个模拟支付宝的网关,主要是接收请求并返回数据.作为一名没有丝毫开发经验的菜鸡,初期入门相当费劲,主要还是思维上的转变. ...

  6. Visual Studio 2015 Bowser Link的功能不停的向服务端发送请求

    Visual Studio 2015新建的mvc项目 默认在每个视图上生成一些JavaScript脚本

  7. 在java服务端判断请求是来自哪个终端

    在servlet中,我们可以获取到HttpServletRequest,然后通过HttpServletRequest的getHeader("User-Agent")方法获取请求头中 ...

  8. ajax对服务端发送请求

    //兼容处理获取ajax对象 var req = ''; if (window.XMLHttpRequest)    req = new XMLHttpRequest(); else    req = ...

  9. nextjs 服务端渲染请求参数

    Post.getInitialProps = async function (context) { const { id } = context.query const res = await fet ...

随机推荐

  1. Spring Data JPA简介 Spring Data JPA特点

    Spring Data JPA 是Spring基于ORM框架.JPA规范的基础上封装的一套JPA 应用框架,底层使用了Hibernate 的JPA技术实现,可使开发者用极简的代码即可实现对数据的访问和 ...

  2. Hi,这里是我的2020年,请查收!

    Part 1. 回顾 还记得新年第一天,我在刚租的房子给自己做了一顿咖喱饭 (不好意思放照片...),然后回顾并展望了一下自己的 2020. 转眼间,2020 就过去了. 总的来说,今年小目标 (比如 ...

  3. Vue利用v-for渲染时表单信息出不来

    今天在写项目时,Controller的值已经传入到html,但是利用vue进行渲染的时候就是出不来, 原因如下: 注意,in 之前的空格.

  4. HTML学习案例-仿慕课网网页制作(二)

    制作部分:网页footer部分 制作效果: 涉及知识:link部分要复习: dl- definition list dt- definition title dd - definition descr ...

  5. 记录一次 Nginx 配置 proxy_pass 后 返回404问题

    一. Nginx 配置 proxy_pass 后 返回404问题 故障解决和定位 1.1. 问题 在一次生产涉及多次转发的配置中, 需求是下面的图: 在配置好了 proxy_pass 之后,请求 ww ...

  6. java之volatile

    一.谈谈对volatile的理解 volatile是java虚拟机提供的轻量级的同步机制 保证可见性.不保证原子性.禁止指令重排 1.可见性理解:所有线程存放都是主内存的副本(比如某个变量值为25), ...

  7. linq to entity不识别方法"System.String ToString()"

    将班级id以字符串形式输入如:"1111,1112,1113".数据库里的id为int型,在数据路里找到匹配的相应班级转换成列表.在这里爆出问题:不识别方法"System ...

  8. ASP.Net Core 3.1 使用实时应用SignalR入门

    参考文章:微软官方文档:https://docs.microsoft.com/zh-cn/aspnet/core/signalr/introduction?view=aspnetcore-3.1 和 ...

  9. PHPstorm 配置主题

    1.首先先去下载自己喜欢的主题:http://www.phpstorm-themes.com/ 但是在下载的时候会发现一个问题,在点击下载后,并没有下载,而是会打开这个文件(不同的浏览器不同)但是如果 ...

  10. Maven学习笔记之第一个Maven项目(Linux)

    Maven是Apache旗下的管理Java项目jar包的项目管理工具,有了它可以很方便构建和管理我们的Java项目,你不必在互联网上逐个查找你需要的第三方jar包,你只需在maven reposito ...