zoukankan      html  css  js  c++  java
  • 问题追查:QA压测工具http长连接总是被服务端close情况

    1. 背景

    最近QA对线上单模块进行压测(非全链路压测),http客户端 与 thrift服务端的tcp链接总在一段时间被close。
    查看服务端日志显示 i/o timeout.
    最后的结果是: qps太小, 长时间不发送请求, server主动关闭socket

    2. 查看thrift框架原代码

    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
    		}
    	}()
    }
    

    可以看出,

    • thrift框架并没有使用像epollo那样的io多路复用,而是为每个client单独启一个goroutine进行处理
    • tcp时双通道, 上面代码中读、写分别处理,使用channel进行同步
    • 遇到client 超时或者错误,server会主动关闭tcp连接 (使用SetDeadline,SetReadDeadline,SetWriteDeadline设置超时时间)

    3. 可能的两种超时情况

    3.1 server写超时

    压测工具,只负责发送请求,一般不读取请求。
    如果使用socket直接连服务器thrift端口,只send数据,不recv数据。可能使得server发送缓冲区满,发送数据超时。

    3.2 server 读超时

    client qps太小,发送请求时间间隔大于server设置的读超时时间。

    4. 总结

    这里不是长连接、短连接的问题,是server服务器端的一种自我保护机制。
    服务器用于接收大量的client请求,如果存在大量的无用连接不仅会占用服务器资源,更严重的情况会使得其他client无法连接服务器的情况。
    可以使用其他方法解决:

    • client和server自定义心跳协议。如secret的发送no-op命令
    • 比如redis client, 如果连接断开可以进行重发一次(先连接,再发)
  • 相关阅读:
    CMMI学习系列(1)CMMI简介及证书介绍
    Lync 2010 系统架构 学习笔记(2)
    Lync 2010 标准版 AD控制器搭建 学习笔记(3)
    云计算 学习笔记(4) HDFS 简介及体系结构
    云计算 学习笔记(1) Hadoop简介
    Lync 2010 Lync客户端测试 学习笔记(7)
    Lync 2010 监控服务器配置 学习笔记(8)
    CMMI学习系列(7)组织过程库,预评估,正式评估。
    CMMI学习系列(5)CMMI3过程规范制定
    CMMI学习系列(6)项目试点
  • 原文地址:https://www.cnblogs.com/xudong-bupt/p/11334282.html
Copyright © 2011-2022 走看看