TCP Delay引起的性能问题 —— tengine request no buffering性能测试回顾

阅读更多

项目开发缘由:

tengine在接收client端post数据并转发给后端application server进行处理的时候,默认启用buffer模式,也就意味着,当client发送的数据较小时,tengine会将所有post数据保存在内存中之后再转发后端application server,而当client发送的数据较大时(根据配置中所设置的buffer大小来区分数据是否保存到文件),tengine会将post数据保存成临时文件写入磁盘,只有在全部接收完post数据后,才会将临时文件读取回内存并转发后端application server。因此,当访问压力较大且post数据超过buffer大小,那么tengine将会有大量的io操作,从而存在性能风险。
request no buffering的开发就是为了解决该性能问题,其设计思路是,通过client_body_postpone_sending配置项设置存储post数据的内存buffer大小,然后通过proxy_request_buffering 和 fastcgi_request_buffering开关来决定是否开启request no buffering功能。当request no buffering开启后,当tengine接收到的post数据大于所设置的buffer大小之后,马上向后端application server转发。这样就规避了之前提到的大量的io操作所带来的性能风险。
 
性能测试问题:
1. tcp delay所带来的性能瓶颈:
问题描述:
在性能测试的过程中发现,与传统的buffer模式相比,当请求文件大小稍大于no buffer size大小时(如请求文件大小为10K,no buffer size为8K),性能表现非常差,用户平均等待时间达到60ms左右,QPS下降100倍。
究其原因:
是因为tcp delay的问题。tcp delay准确的说是Nagle算法,其设计的初衷是为了保证网络性能,因为应用程序可以通过它将任意尺寸的数据放入TCP栈中——即使一次只放一个字节!但是,每个TCP段中都至少装载了40个字节的标记和首部,所以如果TCP发送大量包含少量数据的分组,网络的性能就会严重下降。而Nagle算法试图在发送一个分组之前,将大量TCP数据绑定在一起,鼓励发送全尺寸(LAN上最大尺寸的分组约为1500字节,Internet上是几百字节)的段。这将导致几种HTTP性能问题。首先,小的HTTP报文可能无法填满一个分组,可能会因为等待那些永远不会带来的额外数据而产生时延。其次,Nagle算法与延迟确认之间的交互存在问题——Nagle算法会阻止数据的发送,知道有确认分组抵达为止,但确认分组自身会被延迟确认算法延迟100~200毫秒。
最初方案:
在配置文件中加入tcp_nodelay on配置项,验证证明无效。原因是该配置项只对tengine的前端生效,不对后端生效。
真正的解决方案:
在代码中加入:
 
当配置文件中tcp_nodelay为on时,对后端也采用tcp_nodelay方式进行数据传输。
if (clcf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) {
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "upstream tcp_nodelay");

        tcp_nodelay = 1;

        if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
                           (const void *) &tcp_nodelay, sizeof(int)) == -1)
        {
            ngx_connection_error(c, ngx_socket_errno,
                                 "setsockopt(TCP_NODELAY) failed");
            ngx_http_upstream_finalize_request(r, u, 0);
            return;
        }

        c->tcp_nodelay = NGX_TCP_NODELAY_SET;
    }
 
2. 当tengine的前端与后端均有no delay时的性能问题:
问题描述:
上文讲过,Nagle算法的设计初衷是为了保证网络性能,当tcp nodelay开启后,Nagle算法的防护就失效,当 请求文件大小稍大于no buffer size大小时(如请求文件大小为10K,no buffer size为8K) 且访问压力大的情况下,tcp以大量小数据块的形式进行传输,导致网络利用率低,存在大量的小包传输。
解决方案:
应用方需要权衡线上上传数据的size范围,服务器硬件性能等指标,选择合理的buffer size配置,避免出现大量上传请求的数据size在buffer size范围左右。并启用监控策略,监控显示数据流量变化情况。
 
转发请备注转自:100continue.iteye.com。 

你可能感兴趣的:(tengine,request,no,buffer,tcp,性能调优)