Jekin Leung

Results 17 comments of Jekin Leung

now server detect closed websocket by matching message "^ws closed:" which return from websocketUtil.ReadClientData is there has a better way to do this?

> 压测场景是什么?出现disconnect应该是客户端client关闭了 服务A维护了大量长连接,想观察关闭大量长连接的资源消耗,日志统计所有长连接关闭耗时10分钟,但是进程一直无法退出,一直在输出nacos sdk的log,是关闭的时序有问题?

> > 压测场景是什么?出现disconnect应该是客户端client关闭了 > > 服务A维护了大量长连接,想观察关闭大量长连接的资源消耗,日志统计所有长连接关闭耗时10分钟,但是进程一直无法退出,一直在输出nacos sdk的log,是关闭的时序有问题? 补充一点。在第一个log的第一行就是关闭进程之后第一条输出的日志,在四分钟后才有关闭长连接成功的日志,中间CPU一直是打满的

> 维护了大量长链接,长链接是和nacos server的吗? 上面两条回复有冲突,要确认一下是先关闭了长链接,然后关闭进程。还是直接就关闭了进程。 长连接是业务方的,是直接关闭进程,进程里面有多个协程,一个长连接一个协程,单独一个协程维护nacos的配置,进程关闭的时候,按照框架的逻辑应该是先关闭长连接再关闭nacos协程,有可能因为同时关闭多个协程CPU打满导致nacos的request超时了,才引发后面的报错,因为第一条日志写的是请求超时而不是client not connect

这个问题是client的状态在running和unhealthy反复切换导致的,状态切换我简化成两个地方,一个是r.reconnect store running,一个是Request失败的时候从running到unhealthy。Request的调用链是asyncUpdateService->QueryInstanceOfService->requestToServer->Request,其中asyncUpdateService是单独一个协程,定时创建n个发起Request的协程。r.reconnect则是client其中一个主循环通过心跳或者处理channel的数据触发。 正常的情况下:某次Request超时->状态从running切换到unhealthy调用switchServerAsync->r.reconnect store running 但是在CPU压力大的时候,asyncUpdateService持续创建协程,但是reconnect将状态改成running的速度,跟不上创建Request的速度,刚把状态改成running,某个协程由于重试失败又将状态改回unhealthy,接着导致别的协程判断状态的时候直接报错,报错的协程又在某个时刻将状态改成unhealthy,在下一秒创建n个发起Request的协程,不断循环这个过程。理论上只要程序开的够久,所有请求都能慢慢消化,因为总有某次重试的时候状态是Running的。另一方面reconnectionChan缓冲区只有1,很快就被打满了,多个协程容易卡在switchServerAsync,卡住的时候asyncUpdateService的循环也卡住了,CPU使用率就高了。不知道我这样说能不能理解,有问题及时补充。

> reconnectionChan 缓冲区1是reconnect 的动作只需要一个request goroutine 去完成。 缓冲区是1的话,当主循环执行reconnect动作的时候,缓冲区还能放一个请求,某个goroutine把请求丢进去之后就继续往下执行了,并不会等待。如果没有缓冲区,这样每个需要reconnect操作的goroutine都必须阻塞等待上一个reconnect操作执行完成。上面说的优化如果完成了,就直接close issue吧

我打算特异化改造了,创建的协程数和重试的频率对于我们业务来说压力太大了。

这个running和unhealthy的状态切换有点太复杂了,有点改不太动。race condition同样发生在reconnect中sendHealthCheck失败的时候,connectToServer成功时store running和旧grpcConn执行bindBiRequestStream报错时将状态改成unhealthy,这两个时序是没办法控制的,应该要等旧的退出之后再改成running,这个状态管理可能要重新梳理一下,是不是可以在一个goroutine或者主循环里面处理状态变化? ``` 2022-03-17T11:15:57.132+0800 INFO rpc/rpc_client.go:321 config-0-3c2b22b9-e4a5-4098-abc7-08ec8271aaf7 success to connect a server {serverIp:172.16.0.79 serverPort:8848}, connectionId=1647486951315_172.16.0.79_41606 2022-03-17T11:15:57.132+0800 INFO rpc/rpc_client.go:325 config-0-3c2b22b9-e4a5-4098-abc7-08ec8271aaf7 abandon prev connection, server is {serverIp:172.16.0.79 serverPort:8848}, connectionId is 1647486929153_172.16.0.79_41598...

测试下来,降低频率的效果是最好的,资源都消耗在反复重连的逻辑上了。

> > > > 降低什么频率?反复重连? 还是说的压测条件下吗,我觉得你可以贴一下pprof 抓取的cpu和goroutine指标。 现在除了我上面说的可优化的内容,还有其他明确的问题吗? 降低updateServiceNow的频率,pprof的CPU消耗主要体现在回收业务资源的逻辑上,别的暂时没发现问题