cloudwego / kitex-benchmark

49 stars 30 forks source link

服务端性能测试增加不同连接数 #9

Closed lesismal closed 3 years ago

lesismal commented 3 years ago

现在的测试脚本,默认都是 -pool=10,实际的场景可能连接数要大一些,内部集群之间 RPC 可能连接数确实也不会太大,大点的集群也就几百到几千的范围,但默认10个连接仍然太小了,希望可以增加 100-5000 连接数范围的 benchmark 数据。

另外,刚申请 PR 了 arpc_nbio,可承载 10k-1000k 多种业务场景,如果可以,还是希望大佬们能跑个测试 10k 连接数起步的数据。

YangruiEmma commented 3 years ago

感谢提供压测pr,但如果是连接多路复用的话,理论上不需要这么多连接?我们的常规压测也是单实例压测。 @lesismal 老师可以提性能最优的配置哈,前提是各框架测试场景要对齐,在鸟窝老师的issue我有回复哈,如果要对齐常规rpc测试场景,按照arpc的实现需要在handler中起goroutine,否则arpc在handler mock sleep后劣化很多,但echo表现很好。这个 @lesismal 老师可以验证下。

YangruiEmma commented 3 years ago

按照arpc的实现需要在handler中起goroutine

没这回事啊,大佬你是不是只看了 arpc nbio 的版本。

如果要对齐常规rpc测试场景,按照arpc的实现需要在handler中起goroutine 鸟窝老师 issue 里我已经说过了,arpc 的每个 handler ,用户可以自由选择是同步响应还是异步响应、是否需要考虑线头阻塞,而且 arpc 默认使用标准库、每个连接读写各一个协程,单个连接不会阻其他的连接。 而且任何一个框架的 handler 增加 sleep,单次 Call 的这个响应都大于 sleep 的时间,这跟 arpc 无关。 另外,如果框架自己默认每个 message 都起一个协程去处理,高并发场景协程数量也较大。当然你们面对的 RPC 场景可能不会有那么高,但是我考虑的不只是 RPC,还有海量并发场景,1000K 连接数以及 1000K qps 级别的场景,所以 arpc 才像现在这样提供更自由的可选策略。

昨天的压测pr哈,你在handler里 sleep 1ms试试?多个框架都增加sleep,可以发现arpc劣化明显,或者是我们测试有误?

YangruiEmma commented 3 years ago

今天有些忙,我晚些回复哈

lesismal commented 3 years ago

新提交了 PR,全局开启异步响应、避免线头阻塞、跟各框架看齐:https://github.com/cloudwego/kitex-benchmark/pull/10

YangruiEmma commented 3 years ago

@lesismal 老师,不好意思哈,白天比较忙,没来得及回复,加 sleep 不是目的只是确认是否串行处理,arpc默认的方式是有适用场景的,因为这里看的是rpc场景,rpc的handler通常需要做业务逻辑处理,串行处理不适用,你测试过应该注意到性能出现了劣化,当然轻handler的场景优势是明显的,缓存场景Netpoll做过这样的支持。 如你回复新的arpc测试加了异步配置,避免了handler耗时高劣化的问题,比较符合rpc场景,从你发的单核压测对比看,的确arpc和rpcx都表现不错,和我们的测试有些差异,我们也会加上arpc在机器上测试看看后续给出答复,感谢,其他框架优秀的地方我们也会学习~

另外,Kitex对Thrift支持做了性能优化,Protobuf的优化还未展开,开源后大家对Protobuf的关注较多,我们也会作为优化的TODO。 (Netpoll的压测和Example public后给给你同步的)

YangruiEmma commented 3 years ago

比如实际业务场景里有30%轻接口,那么这部分轻接口我配置同步响应,整体的响应性能还是相比于全局一刀切的异步响应要来得更优

@lesismal 这里是一个选择的问题,每个框架要先有定位,明确定位后要考虑普适的场景,除了普适性还要考虑稳定性,默认串行对30%轻接口来说性能极好,但对另外70%的服务影响巨大(sleep 1ms测试中不调整并发数直观看各框架性能都劣化-cpu未打满还有其他一些原因,但串行是急剧劣化)尤其是延迟指标,直接影响了sla。 从我们的角度来看,不会为少部分服务的极致性能而影响大部分服务,串行应该作为一种策略的选择提供给对性能有更高要求又符合该场景的用户。

YangruiEmma commented 3 years ago

默认串行对30%轻接口来说性能极好,但对另外70%的服务影响巨大

大佬你好像还是没看懂我说的 arpc 定制的啊。。。 arpc 是可以根据不同的路由设置不同的响应方式的,比如 "/slow" 设置异步响应,"/fast"设置同步响应,并不是必须所有路由全同步或者全异步的。。。

我知道arpc可以定制哈,按照方法来配置的确提供了很好的弹性支持,很灵活。我说的默认方式的选择问题,是默认异步,让30%用户配置同步达到更好的性能,还是默认同步,让70%的用户配置异步避免延迟高的问题,这个取决于不同框架的选择。

lesismal commented 3 years ago

这个issue我先清理留言、关掉了,后续有新思路继续交流

cch123 commented 3 years ago

补充一下。。内网 RPC 走长连接的话, 5w -10w 连接也是有可能的吧(某公司内的实际场景

YangruiEmma commented 3 years ago

@cch123 老师,关了没注意到这里的评论,连接数量压力主要是服务端,服务端要承载很多上游流量,每个上游还有大量实例,尤其是长连接池下万级别的连接数是正常的;连接多路复用的话连接数量会大大减少,服务端连接数量基本可以减少到多上游实例数(具体还要看连接数配置,空闲连接关闭策略,通常一个就够了)。 我前面回应的是压测场景哈,压测我们是1:1机器测试,连接多路复用常规单实例压测用不到那么多连接

lesismal commented 3 years ago

@cch123 老师,关了没注意到这里的评论,连接数量压力只要是服务端,服务端要承载很多上游流量,每个上游还有大量实例,尤其是长连接池下万级别的连接数是正常的;连接多路复用的话连接数量会大大减少,服务端连接数量基本可以减少到多上游实例数(具体还要看连接数配置,空闲连接关闭策略,通常一个就够了)。 我前面回应的是压测场景哈,压测我们是1:1机器测试,连接多路复用常规单实例压测用不到那么多连接

可能各位大佬所说的项目架构类型有区别吧。 比如海量接口服务中间件/网关/代理的业务,http转RPC调用内部服务,http那里的用户数量大、节点数就可能非常大。 如果只是不涉及中间件/网关/代理的内部业务服务之间的调用,集群规模通常不大,那是没问题。

但是对于更通用的场景考量,做更大连接数的测试还是有必要的。尤其是抛开 RPC 只考虑通用网络库的话,netpoll 也是应该对更加通用场景进行考量的,包括我之前提到的 netpoll 阻塞读的问题,处理公网业务会有风险。

YangruiEmma commented 3 years ago

@cch123 老师,关了没注意到这里的评论,连接数量压力只要是服务端,服务端要承载很多上游流量,每个上游还有大量实例,尤其是长连接池下万级别的连接数是正常的;连接多路复用的话连接数量会大大减少,服务端连接数量基本可以减少到多上游实例数(具体还要看连接数配置,空闲连接关闭策略,通常一个就够了)。 我前面回应的是压测场景哈,压测我们是1:1机器测试,连接多路复用常规单实例压测用不到那么多连接

可能各位大佬所说的项目架构类型有区别吧。 比如海量接口服务中间件/网关/代理的业务,http转RPC调用内部服务,http那里的用户数量大、节点数就可能非常大。 如果只是不涉及中间件/网关/代理的内部业务服务之间的调用,集群规模通常不大,那是没问题。

但是对于更通用的场景考量,做更大连接数的测试还是有必要的。尤其是抛开 RPC 只考虑通用网络库的话,netpoll 也是应该对更加通用场景进行考量的,包括我之前提到的 netpoll 阻塞读的问题,处理公网业务会有风险。

「包括我之前提到的 netpoll 阻塞读的问题」 这个问题之前从代码层面解释过,不存在这个问题。 相比arpc/nbio默认串行处理方式,Netpoll的默认支持对rpc服务更加友好,这个前面也讨论过

lesismal commented 3 years ago

这个问题之前从代码层面解释过,不存在这个问题

大佬啊,我之前针对你的解释也是又说过一次的:我在issue中提供了代码示例以及日志

func handler(ctx context.Context, connection netpoll.Connection) error {
    total := 2
    t := time.Now()
    reader := connection.Reader()
    data, err := reader.Peek(reader.Len())
    log.Printf("before Next, len: %v, data: %v", reader.Len(), string(data))
    data, err = reader.Next(total)
    if err != nil {
        log.Printf("Next failed, total: %v, reader.Len: %v, block time: %v, error: %v", total, reader.Len(), int(time.Since(t)), err)
        return err
    }

    log.Printf("after  Next, len: %v, data: %v, timeused: %v", len(data), string(data), int(time.Since(t).Seconds()))

    n, err := connection.Write(data)
    if err != nil {
        return err
    }
    if n != len(data) {
        return fmt.Errorf("write failed: %v < %v", n, len(data))
    }

    return nil
}
2021/07/18 07:25:22 before Next, len: 1, data: a
2021/07/18 07:25:24 after  Next, len: 2, data: aa, timeused: 2
2021/07/18 07:25:25 before Next, len: 1, data: b
2021/07/18 07:25:30 Next failed, total: 2, reader.Len: 1, block time: 5005315692, error: connection read timeout 5s
2021/07/18 07:25:30 before Next, len: 1, data: b
2021/07/18 07:25:35 Next failed, total: 2, reader.Len: 1, block time: 5017124559, error: connection read timeout 5s
2021/07/18 07:25:35 before Next, len: 1, data: b
2021/07/18 07:25:40 Next failed, total: 2, reader.Len: 1, block time: 5009562038, error: connection read timeout 5s
2021/07/18 07:25:40 before Next, len: 1, data: b
2021/07/18 07:25:45 Next failed, total: 2, reader.Len: 1, block time: 5008370180, error: connection read timeout 5s
...

同步解析的方式,日志里已经打印出来阻塞了几秒了,如果您仍然觉得这ok,或者说,针对你们的 RPC 业务这样 ok,那我就不再纠结这个问题了。

lesismal commented 3 years ago

相比arpc/nbio默认串行处理方式,Netpoll的默认支持对rpc服务更加友好

如果都是这样对比的话,那我没办法多说什么了。您可以自己想一想,如果用唯一选项只跟别人的默认选项进行对比,那干脆不要对比算了。 或者我去把默认选项改成异步响应?就一个变量初始化的事情:joy:: https://github.com/lesismal/arpc/blob/master/handler.go#L701

但是我实在不想改,因为海量业务的情况,go创建协程太容易了,很多人不考虑后果随便go一个协程,一步小心就炸了。所以我通常是能用协程池的地方尽量都会用池限制数量、避免爆炸。 我个人觉得海量并发场景的理想架构应该包括防止爆炸,比如系统设计的纵向不同层次、横向不同模块,都有良好的协程使用规范和协程数量限制,就像以前写 c/c++ 那样,但是业务逻辑的协程池 size 仍可以足够大,比如1w甚至几w,这个数量级别的协程 runtime 完全 cover 得住,并且相比于 c/c++ 那种线程数量有限必须异步的情况,go这个size的业务协程池仍然可以让业务层规避掉大部分异步。

YangruiEmma commented 3 years ago

相比arpc/nbio默认串行处理方式,Netpoll的默认支持对rpc服务更加友好

如果都是这样对比的话,那我没办法多说什么了。您可以自己想一想,如果用唯一选项只跟别人的默认选项进行对比,那干脆不要对比算了。 或者我去把默认选项改成异步响应?就一个变量初始化的事情😂: https://github.com/lesismal/arpc/blob/master/handler.go#L701

但是我实在不想改,因为海量业务的情况,go创建协程太容易了,很多人不考虑后果随便go一个协程,一步小心就炸了。所以我通常是能用协程池的地方尽量都会用池限制数量、避免爆炸。 我个人觉得海量并发场景的理想架构应该包括防止爆炸,比如系统设计的纵向不同层次、横向不同模块,都有良好的协程使用规范和协程数量限制,就像以前写 c/c++ 那样,但是业务逻辑的协程池 size 仍可以足够大,比如1w甚至几w,这个数量级别的协程 runtime 完全 cover 得住,并且相比于 c/c++ 那种线程数量有限必须异步的情况,go这个size的业务协程池仍然可以让业务层规避掉大部分异步。

抱歉没有及时关注这里的回复。 我或许没有说明白,我的意思是不同的框架压测应该是在同场景情况对比,对比才有意义,不同的场景各框架也都有优劣势,arpc有比kitex的优势场景,给开发者明确的场景也便于开发者自己选择。

lesismal commented 3 years ago

抱歉没有及时关注这里的回复。 我或许没有说明白,我的意思是不同的框架压测应该是在同场景情况对比,对比才有意义,不同的场景各框架也都有优劣势,arpc有比kitex的优势场景,给开发者明确的场景也便于开发者自己选择。

也还没休息呀,:smile:

可能你们的场景主要是内部集群RPC。但有些团队比如其他某些厂确实有大量连接数的需要。

不过都没关系了,各自够用就好,arpc 本来也是我去年随手写着玩的,写完放那一年多也没怎么管,今年鸟窝老师发帖子有朋友看到了告诉我我才来跟各位交流了一波。rpc 相对来说还是比较简单的,我最近也都没再关注 rpc 相关的。后面要是来兴致了倒是可以考虑支持下多语言,但是每种语言都得耗费我一波体力,有点不想动 :joy:

golang 异步库支持多点得功能难度要大得多,最近给 nbio 又完善了一波,也加上了 http client 和 websocket client 的支持,刚刚又添加了同一个 Server/Engine 同时处理 tls-server/non-tls-server/tls-client/non-tls-client 的代码,再测测发布了然后应该可以又休息一阵子了 😄

晚安了先 🌙

YangruiEmma commented 3 years ago

抱歉没有及时关注这里的回复。 我或许没有说明白,我的意思是不同的框架压测应该是在同场景情况对比,对比才有意义,不同的场景各框架也都有优劣势,arpc有比kitex的优势场景,给开发者明确的场景也便于开发者自己选择。

也还没休息呀,😄

可能你们的场景主要是内部集群RPC。但有些团队比如其他某些厂确实有大量连接数的需要。

不过都没关系了,各自够用就好,arpc 本来也是我去年随手写着玩的,写完放那一年多也没怎么管,今年鸟窝老师发帖子有朋友看到了告诉我我才来跟各位交流了一波。rpc 相对来说还是比较简单的,我最近也都没再关注 rpc 相关的。后面要是来兴致了倒是可以考虑支持下多语言,但是每种语言都得耗费我一波体力,有点不想动 😂

golang 异步库支持多点得功能难度要大得多,最近给 nbio 又完善了一波,也加上了 http client 和 websocket client 的支持,刚刚又添加了同一个 Server/Engine 同时处理 tls-server/non-tls-server/tls-client/non-tls-client 的代码,再测测发布了然后应该可以又休息一阵子了 😄

晚安了先 🌙

哈哈哈,github关联的邮箱不常用不及时看到消息,晚上的时候翻一翻issue,@lesismal 老师自己做这些支持说明对技术极度的热爱,值得尊敬。

lesismal commented 3 years ago

哈哈哈,github关联的邮箱不常用不及时看到消息,晚上的时候翻一翻issue,@lesismal 老师自己做这些支持说明对技术极度的热爱,值得尊敬。

大佬太客气了,大家都一样热情,有需要的时候咱们多多交流 😄

YangruiEmma commented 3 years ago

哈哈哈,github关联的邮箱不常用不及时看到消息,晚上的时候翻一翻issue,@lesismal 老师自己做这些支持说明对技术极度的热爱,值得尊敬。

大佬太客气了,大家都一样热情,有需要的时候咱们多多交流 😄

🤝🤝🤝