antlabs / httparser

高性能http 1.1解析器,为你的异步io库插上http解析的翅膀, 每秒可以处理630.15MB/s流量[从零实现]
Apache License 2.0
41 stars 9 forks source link

Execute形参讨论 #5

Open guonaihong opened 3 years ago

lesismal commented 3 years ago

优化状态机,可以考虑支持 [][]byte 二维数组做参数,这样上次未解析完的buf,和下次来的buf,就不用合并到同一个buf了,免去了拷贝过程和可能造成多余的内存分配

guonaihong commented 3 years ago

这个方法不错,我考虑下

---原始邮件--- 发件人: "lesismal"<notifications@github.com> 发送时间: 2021年2月2日(周二) 晚上8:16 收件人: "antlabs/httparser"<httparser@noreply.github.com>; 抄送: "guonaihong"<guonaihong@qq.com>;"Author"<author@noreply.github.com>; 主题: Re: [antlabs/httparser] 优化内部状态机 (#5)

优化状态机,可以考虑支持 [][]byte 二维数组做参数,这样上次未解析完的buf,和下次来的buf,就不用合并到同一个buf了,免去了拷贝过程和可能造成多余的内存分配

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.

lesismal commented 3 years ago

如果想让应用层更方便的话,parser自带个字段把上次未解析完的存上、下次来数据了一块处理就可以了

guonaihong commented 3 years ago

讨论:数据是入参是用[][]byte,还是[]byte?

问题:

lesismal commented 3 years ago

讨论:数据是入参是用[][]byte,还是[]byte?

  • 一开始我挺赞成[][]byte的形式。

问题:

  • 后面考虑到处理http header。现有[]byte形式,可以保证一个回调是一个完整的http header field或者value。使用[][]byte必然带来分割,这种情况如何处理?

[][]byte 这个我在#2里有提到,真实场景未必能带来提升,而且代码也不如append一下清爽,所以可以先不改

但是 half 重复解析的应该是可以优化些的

guonaihong commented 3 years ago

我在httparser设计了一种TwoBuf的数据结构,相比直接append拼接未解析数据。拷贝的字节数据会更少,也不需要重新malloc新的buf。

    tb := NewTwoBuf()
         // 取右边buffer
    buf := tb.Right()

    //模拟从异步io里面填充一块buffer
    n, err := r.Read(buf)
    if err == io.EOF {
        break
    }

    // 把溢出数据包含进来
    // 左边放需要重新解析数据,右边放新塞的buffer
    currSentData := tb.All(n)

    //解析
    success, err := p.Execute(&setting, currSentData)
    if err != nil {
        //panic(err.Error() + fmt.Sprintf(" size:%d", size))
    }

    if success != len(currSentData) {
        // 测试用, 把送入解析器的buffer累加起来,最后验证下数据送得对不对
        totalSentBuf = append(totalSentBuf, currSentData[:success]...)

        tb.MoveLeft(currSentData[success:])
    } else {
        // 测试用
        totalSentBuf = append(totalSentBuf, currSentData...)

        tb.Reset()

    }
guonaihong commented 3 years ago

后面打算写个类型wrk的工具,新的工具命名ak47(哈哈),实战下httparser库。

guonaihong commented 3 years ago

行啊,你优化好了放到master分支。我现在还在设计ak47如何写。

lesismal commented 3 years ago

guonaihong commented 3 years ago

我有点懂你的意思了,解析websocket的时候如果用定长读取frame,其中conn每次都几字节字节的发,流量没有打满,这种垃圾连接会影响后面的连接处理。这块要解决要深度配合epoll写解析器。

---原始邮件--- 发件人: @.> 发送时间: 2021年7月9日(周五) 晚上11:22 收件人: @.>; 抄送: @.**@.>; 主题: Re: [antlabs/httparser] Execute形参讨论 (#5)

哎,好累,golang websocket 1000k的问题,几年前有个帖子,还有个gobwas/ws的框架配合easygo/netpoll来做,就是poller的方式避免每个连接一个协程的方案。 但是他们这个方案有问题,我已经在几个地方给他们说了好几轮,能get到的人好少,多数人都看不懂,数千star,随便几个慢连接就能把他服务搞慢甚至业务协程池耗尽导致服务不可用 甚至这种几千star的作者自己都搞不懂问题到底在哪、需要怎么解决 真无奈

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.

guonaihong commented 3 years ago

上次看完rfc6455, 写了个websocket库, 加测试代码都不到1k行代码, 超级迷你. 现在比较头疼写大量测试代码, 可有好的测试case, 我移值下

lesismal commented 3 years ago

这个比较全面: https://github.com/crossbario/autobahn-testsuite

nbio的websocket已经通过测试: https://lesismal.github.io/nbio/websocket/

guonaihong commented 3 years ago

优秀青年.

guonaihong commented 3 years ago

恩, 已发送.

guonaihong commented 3 years ago

高手寂寞?我最近太忙了,天天调试流式识别,不然可以把你现在玩rpc和异步io库的撸出火花来。

---原始邮件--- 发件人: @.> 发送时间: 2021年8月19日(周四) 下午4:19 收件人: @.>; 抄送: @.**@.>; 主题: Re: [antlabs/httparser] Execute形参讨论 (#5)

哎,太寂寞了。

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android.

lesismal commented 3 years ago

流式识别?是做什么业务?

lesismal commented 3 years ago

高手寂寞?我最近太忙了,天天调试流式识别,不然可以把你现在玩rpc和异步io库的撸出火花来。 ---原始邮件--- 发件人: @.> 发送时间: 2021年8月19日(周四) 下午4:19 收件人: @.>; 抄送: @.**@.>; 主题: Re: [antlabs/httparser] Execute形参讨论 (#5) 哎,太寂寞了。 — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android.

你跑下 kitex-benchmark 的数据和 go-net-benchmark 的数据,如果我机器环境差异不大的话,跟其他几个都没有可比性了,benchmark 这一波,我可以停下来歇歇了。

guonaihong commented 3 years ago

高手寂寞?我最近太忙了,天天调试流式识别,不然可以把你现在玩rpc和异步io库的撸出火花来。 ---原始邮件--- 发件人: @.**> 发送时间: 2021年8月19日(周四) 下午4:19 收件人: @.**>; 抄送: @.**@.**>; 主题: Re: [antlabs/httparser] Execute形参讨论 (#5) 哎,太寂寞了。 — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android.

你跑下 kitex-benchmark 的数据和 go-net-benchmark 的数据,如果我机器环境差异不大的话,跟其他几个都没有可比性了,benchmark 这一波,我可以停下来歇歇了。

周六跑下,最近忙到github快长草了。

guonaihong commented 3 years ago

流式识别?是做什么业务?

这个邮件聊吧。

guonaihong commented 3 years ago

哎,太寂寞了。

在poller方案中, 如果http客户端发的body 用慢速发, nbio套标准库ServeHTTP接口的方式,也会挂住一个协程。相比之下好处没有想象中的大,不知道我的理解可对?

后面我想了下, go的标准库的协程能提供 获取id, 中断, 恢复,解决1g连接真是轻轻松松, 协议层再定义streamID。直接关联协程id。就可以优化得更细致一点。

更新下: 刚扫了下代码, 原来先放到内存,处理大文件可能要优化下。

lesismal commented 3 years ago

在poller方案中, 如果http客户端发的body 用慢速发, nbio套标准库ServeHTTP接口的方式,也会挂住一个协程。相比之下好处没有想象中的大,不知道我的理解可对?

理解的不对。http parser是异步流解析的,每次解析半包不会阻塞,解析到完整body后才会调用业务层的ServeHTTP,业务协程池根据业务类型定制合理的pool size就行了。比如:

  1. cpu消耗,比如做网关/代理,则pool size不需要太大
  2. 有较多io/阻塞操作,比如用户接口、web后台,都涉及数据库、缓存相关的慢操作,可以设置得大一些,因为数据库、缓存本身也是连接池的,所以即使nbio http server执行单个ServeHTTP暂时占用一个协程,有不太影响其他连接响应速度因为即使每个连接都一个协程,还是都会卡在数据库、缓存的连接池上,这个我在gev那个issue里有解释过
guonaihong commented 3 years ago

@lesismal 都堆内存, 如果是单连接大body,参考标准库放到tempfile里面比较好。

lesismal commented 3 years ago

后面我想了下, go的标准库的协程能提供 获取id, 中断, 恢复,解决1g连接真是轻轻松松, 协议层再定义streamID。直接关联协程id。就可以优化得更细致一点。

runtime不可能提供这种机制,你把事情想得太简单了。并发的场景,每一瞬间都可能发生数据状态的变化,你恢复之前的,可是上下游依赖可能发生了其他故障,你无法去靠这种机制去处理实际业务面对的复杂度。 正确的处理就是分层的思想。语言层只处理语言层自己的问题。

lesismal commented 3 years ago

刚扫了下代码, 原来先放到内存,处理大文件可能要优化下。

nbio针对的是海量并发的接口类服务。 资源文件,不论大小,功能是比较固定的、不需要太多业务逻辑相关的开发件,用nginx那些c/c++/rust的就好了,go做这些主要是面向业务、提高业务开发的效率。go不是万能的,不应该期望用它去替代c/c++/rust更适合并且成熟的场景。

guonaihong commented 3 years ago

后面我想了下, go的标准库的协程能提供 获取id, 中断, 恢复,解决1g连接真是轻轻松松, 协议层再定义streamID。直接关联协程id。就可以优化得更细致一点。

runtime不可能提供这种机制,你把事情想得太简单了。并发的场景,每一瞬间都可能发生数据状态的变化,你恢复之前的,可是上下游依赖可能发生了其他故障,你无法去靠这种机制去处理实际业务面对的复杂度。 正确的处理就是分层的思想。语言层只处理语言层自己的问题。

你说的复杂的状态管理, 其实是变量的生命周期的管理。中断和恢复,必然要考虑把变量的生命周期管控起来, 刚刚只是聊个思路。

lesismal commented 3 years ago

@lesismal 都堆内存, 如果是单连接大body,参考标准库放到tempfile里面比较好。

文件传输类的,内核是有 zero copy 的 syscall 的,sendfile,MSG_ZEROCOPY 那些。 nbio 支持了 linux 的 sendfile,但是通常不建议使用。

guonaihong commented 3 years ago

nbio 支持了 linux 的 sendfile,但是通常不建议使用。

zerocopy, 还是要少用, 上次grep接了一个mmap 找文件, 直接把内核整挂了。

lesismal commented 3 years ago

后面我想了下, go的标准库的协程能提供 获取id, 中断, 恢复,解决1g连接真是轻轻松松, 协议层再定义streamID。直接关联协程id。就可以优化得更细致一点。

runtime不可能提供这种机制,你把事情想得太简单了。并发的场景,每一瞬间都可能发生数据状态的变化,你恢复之前的,可是上下游依赖可能发生了其他故障,你无法去靠这种机制去处理实际业务面对的复杂度。 正确的处理就是分层的思想。语言层只处理语言层自己的问题。

你说的复杂的状态管理, 其实是变量的生命周期的管理。中断和恢复,必然要考虑把变量的生命周期管控起来, 刚刚只是聊个思路。

正确的处理就是分层的思想。语言层只处理语言层自己的问题。

分层的思想,你可以深入理解下,从硬件存储层次(多级缓存、内存、磁盘),到操作系统比如协议栈(4层/7层),到框架设计、架构设计各种,很多人缺少这个意识。

这句名言很对:“计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决”。

lesismal commented 3 years ago

还是要少用, 上次grep接了一个mmap 找文件, 直接

mmap是应该少用。 mmap 跟其他的 zero copy syscall 是两码事,用法、处理的业务都不一样,其他的正常用没问题。

guonaihong commented 3 years ago

后面我想了下, go的标准库的协程能提供 获取id, 中断, 恢复,解决1g连接真是轻轻松松, 协议层再定义streamID。直接关联协程id。就可以优化得更细致一点。

runtime不可能提供这种机制,你把事情想得太简单了。并发的场景,每一瞬间都可能发生数据状态的变化,你恢复之前的,可是上下游依赖可能发生了其他故障,你无法去靠这种机制去处理实际业务面对的复杂度。 正确的处理就是分层的思想。语言层只处理语言层自己的问题。

你说的复杂的状态管理, 其实是变量的生命周期的管理。中断和恢复,必然要考虑把变量的生命周期管控起来, 刚刚只是聊个思路。

正确的处理就是分层的思想。语言层只处理语言层自己的问题。

分层的思想,你可以深入理解下,从硬件存储层次(多级缓存、内存、磁盘),到操作系统比如协议栈(4层/7层),到框架设计、架构设计各种,很多人缺少这个意识。

这句名言很对:“计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决”。

犹豫不决,分层解决, 哈哈。容我先吃个饭,再讨论。

guonaihong commented 3 years ago

恭喜恭喜。这波秀恩爱可以😊

---原始邮件--- 发件人: @.> 发送时间: 2021年8月19日(周四) 晚上8:57 收件人: @.>; 抄送: @.**@.>; 主题: Re: [antlabs/httparser] Execute形参讨论 (#5)

七夕我老婆送了个新笔记本给我,5800H 8c16t 32G,终于解放一些生产力了。之前写代码经常被卡成狗

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android.

lesismal commented 3 years ago

得休息一下缓缓了,之前用的低配笔记本,消耗了我很多不必要的体力

guonaihong commented 3 years ago

@lesismal websocket写完了。https://github.com/guonaihong/tinyws 工作换档, 浪费了一些时间。本来计划5月份写完的。

后面把我的httparser架在epoll上玩玩, 找点乐子。这主题 应该可以把以前用c语言时期积累的apue的知识都发挥出来。

lesismal commented 3 years ago

又是一个同步的库啊,gorilla已经足够了

guonaihong commented 3 years ago

又是一个同步的库啊,gorilla已经足够了

gorilla以前的作者不维护了, 代码没有啥迭代。我上次加个limit callback的pr 都不敢合进去, 感觉用用可以,想改进就不行。

先出个同步库,好处接受度高,有一帮用的童鞋帮助检验下rfc规范。后面要实现个poller+callback, 也挺简单的。

我现在已经不在意同步, 异步。难度没啥区别。

lesismal commented 3 years ago

又是一个同步的库啊,gorilla已经足够了

gorilla以前的作者不维护了, 代码没有啥迭代。我上次加个limit callback的pr 都不敢合进去, 感觉用用可以,想改进就不行。

先出个同步库,好处接受度高,有一帮用的童鞋帮助检验下rfc规范。后面要实现个poller+callback, 也挺简单的。

我现在已经不在意同步, 异步。难度没啥区别。

异步全套的还是有些坑要踩,包括tls

lesismal commented 3 years ago

项目长期维护也是个问题,melody的作者也是好几年没动静了,那个有个并发的bug低概率会导致panic,我PR了个也没动静。

lesismal commented 2 years ago

nbio 的 http client、websocket client也支持上了,暂时没发布新版本,但是master最新代码基本ok了,再跑跑测试就准备发布了

lesismal commented 2 years ago

nbio 的 http client、websocket client也支持上了,暂时没发布新版本,但是master最新代码基本ok了,再跑跑测试就准备发布了

发布了,加了个websocket proxy的示例

guonaihong commented 2 years ago

@lesismal 有时间我看下, 最近工作最忙了.