lesismal / nbio

Pure Go 1000k+ connections solution, support tls/http1.x/websocket and basically compatible with net/http, with high-performance and low memory cost, non-blocking, event-driven, easy-to-use.
MIT License
2.11k stars 151 forks source link

请教大佬,在很短的时间里,向同一个conn推送多次数据 #414

Closed ericjing83 closed 1 month ago

ericjing83 commented 3 months ago

您好,大佬,

请教一个问题,通过以下这行代码,在很短的时间里(比如100毫秒),向同一个conn推送多次数据 conn.WriteMessage(websocket.TextMessage, message) 这种情况下,nbio会通过一些内置的优化,把短时间内多次的推送,合并为一次推送吗?在大并发的时候,这可能会提升一些性能。(虽然会造成一些延时,但是延时不会很长,可能是几百毫秒,对一般的企业用户而言影响不大)。

lesismal commented 3 months ago

感谢关注nbio!

具体点的数据有吗?比如推送频率、buffer size。 nbio ws这一层没有做自动合并多个Message、因为单个ws conn交互场景通常没有那么高的频率、并且在tcp发送缓冲区满之前write基本都是立刻成功返回的、框架自己的发送队列这一层可能来不及合并、所以ws frame合并逻辑可能反倒浪费更多性能,所以ws这一层没加合并的逻辑。

如果频率非常高,可以考虑:

  1. SetNodelay(false), 交给tcp自己的延迟发送、nagle去合并发送的多个包
  2. 应用层自己加个简单的头、并处理合并多个包的逻辑,例如发10个json段头部各自带上varint lenth、然后只使用一个ws frame进行发送,这样能省去9个ws frame header、不需要依赖ws这一层的合并。arpc里的批次发送就是这样、arpc里的conn可以是ws conn、ws conn只是作为传输层、arpc对于ws conn相当于应用层、由arpc自己处理批次合并: https://github.com/lesismal/arpc/blob/master/client.go#L929

另外,如果tcp发送缓冲区满,处于四层TCP的nbio.Conn自己会缓存上一层(例如ws)写的数据,但这只适合短暂流量过大的场景、不适合持续高频高流量、因为流量过载单个TCP信道不够用就得考虑更多优化了比如参数、多连接、专线之类的信道质量保证手段

guonaihong commented 3 months ago

以前测试过。开启tcp的delay(延迟合并)功能,比应用层自己合并效率高些。

ericjing83 commented 3 months ago

大佬您好, 主要是基于这样的场景的: 比如一个集团公司,里面有很多公司,每个分公司里面有很多员工,每个员工通过websocket发送数据到服务器的频率是比较低的(如果频率高了服务器应该会视为是攻击),但是每个员工接收服务器推送的websocket消息的频率是相对比较高的,比如,集团里的很多分公司里的不同的人都分别在短时间里发送消息给同一个人,这种情况下,可能会导致单个conn接收服务器推送的websocket消息的频率比较高(可能每秒有几次,多的大概会有10多次,比如,下午2点办公的高峰时段,办公的低峰时段估计不会频率很高,我觉得不合并问题不大) 我知道nbio不是基于rpc优化的,如果为每个conn分别进行消息合并反而会浪费性能(比如每个conn合并消息是分别需要一个缓冲区的,缓冲区的维护可能也会有性能损耗),我感觉就不用合并了。

lesismal commented 3 months ago

可能每秒有几次,多的大概会有10多次

这种没太大必要优化, 应该足够用了. 如果是群组那种多人活跃聊天消息非常频繁, 才需要考虑广播风暴的优化, 比如一个群组定时器合并多个应用层消息再发送, 但这也是应用层自己优化更好, 省掉多一点的ws frame header. 但群组聊天, 人的手速一般, 除非你们是大群很多人活跃, 否则其实也基本没有瓶颈所以没太大必要优化 你们是这块送到瓶颈了吗?

ericjing83 commented 3 months ago

大佬您好,

目前还没遇到瓶颈。如果遇到了,按照您的建议,我觉得还是应用层优化比较好。重要性程度高的数据,就及时推送给每一个conn,重要性程度不高的数据,在高峰的时候就用定时器合并发送。 我自己在应用层优化的话,这可能涉及到内存池的概念,nbio的内存池我没法用。毕竟我不想在大并发请求高峰的时候影响nbio的稳定性,我要自己用第三方内存池缓存每个conn需要合并发送的消息是伐?

lesismal commented 3 months ago

我自己在应用层优化的话,这可能涉及到内存池的概念,nbio的内存池我没法用。毕竟我不想在大并发请求高峰的时候影响nbio的稳定性,我要自己用第三方内存池缓存每个conn需要合并发送的消息是伐?

与nbio共用是可以的, nbio也支持用户自己定制使用, 要看实际场景的需要, 有瓶颈的时候根据实际情况再优化就行了

github-actions[bot] commented 2 months ago

This issue is stale because it has been open for 30 days with no activity.

github-actions[bot] commented 1 month ago

This issue was closed because it has been inactive for 14 days since being marked as stale.