最近QA对线上单模块进行压测(非全链路压测),http客户端 与 thrift服务端的tcp连接总在一段时间被close。
查看服务端日志显示 i/o timeout.
最后的结果是: qps过小, 长时间不发送请求, server主动关闭socketredis
thrift框架处理请求伪代码以下:服务器
//服务端listen for { // 服务端接收一个tcp链接请求 client := server.accept() // 独立启动一个goroutine处理client后续请求 go fun () { inputTrans := xxx(client) outputTrans := xxx(client) if inputTrans != nil { //return 时, 关闭读 defer inputTrans.close() } if outputTrans != nil { defer outputTrans.close() //return时, 关闭写 } //独立goroutine处理写结果 (使用channel同步) go func( for { //超时,或者其余错误, return } ) () //for循环: 服务读取请求 (两个for循环使用channel同步) for { //超时,或者其余错误, return } }() }
能够看出,框架
压测工具,只负责发送请求,通常不读取请求。
若是使用socket直接连服务器thrift端口,只send数据,不recv数据。可能使得server发送缓冲区满,发送数据超时。socket
client qps过小,发送请求时间间隔大于server设置的读超时时间。tcp
这里不是长链接、短链接的问题,是server服务器端的一种自我保护机制。
服务器用于接收大量的client请求,若是存在大量的无用链接不只会占用服务器资源,更严重的状况会使得其余client没法链接服务器的状况。
能够使用其余方法解决:工具
- client和server自定义心跳协议。如secret的发送no-op命令
- 好比redis client, 若是链接断开能够进行重发一次(先链接,再发)