内容简介:作者:不论宣称如何完美的解决方案,都会引入另一个更复杂的问题。我负责的缓存系统有一个版本号模块,专门用来对数据生成唯一的版本号seq来保证数据的唯一性,从而做到数据数据实时更新以及避免旧数据覆盖新数据的问题。
作者: tiankonguse | 更新日期:
不论宣称如何完美的解决方案,都会引入另一个更复杂的问题。
一、背景
我负责的缓存系统有一个版本号模块,专门用来对数据生成唯一的版本号seq来保证数据的唯一性,从而做到数据数据实时更新以及避免旧数据覆盖新数据的问题。
这个模块是其他人交接给我的,之前服务一直都正常,也就没去细看。
最近访问量越来越大了,服务出现一些失败,所以需要先梳理整个模块的情况,然后在从整体上来优化这个模块。
二、高延时
版本号模块一梳理不要紧,发现一大堆问题,如将来处理数据存在瓶颈、模块不可扩容、存在同步逻辑等等。
其中一个问题就是拉取版本号时,平均延时比较高。
看上图,可以发现,测试环境平均耗时只有1毫秒,而正式环境是20多毫秒。这个不应该这么高的。
那版本号服务的延时为什么这么高呢?
目前我只能说不知道。
上面那个监控也是那个服务交接过来后,在我给那个服务增加功能时增加的。
而对于版本号模块交接过来后发现没监控,但是加监控这种优先级最低的事情是不会单独去做的,除非出了问题,比如现在,不得不加了。
现在能做的是先tcpdump抓个包看看,结果发现一个奇怪的现象,是的,就是这篇文章的标题标题,某些ACK延迟了40ms才发出来。
三、延迟ACK
如上图,可以看到某些时候,服务端回数据包了,但是客户端却迟迟没有回复ACK,直到40毫秒之后才发出ACK。
为什么会这样呢?
查了TCP相关的资料,了解到TCP的 Nagel算法算法在某些时候,会进入这样一个延迟回复ACK的逻辑,然后等待40毫秒,触发超时逻辑,最终回复了ACK。
这对应了我的其中一个座右铭:不论宣称如何完美的解决方案,都会引入另一个更复杂的问题。
为什么延迟
对于后台服务,一般都是长连接,而且是一发一收的模式。
场景就像下面的样子。
CLIENT -> SERVER:发送请求数据 SERVER -> CLIENT:回应收到数据了 SERVER -> CLIENT:返回处理后的数据 CLIENT -> SERVER:回应收到数据了
是不是发现服务器连续想客户端发了两次数据,一次是会请求数据的ACK,一次是请求数据的结果。
这两次回包如果能够合并为一次,网络上的包是不是一下就少了四分之一。
说干就干,TCP的Nagel加了这样一个功能,先探测通信模型是不是一发一收的,符合条件了收到请求数据包时就先不回ACK,等一会,然后带着处理后的数据一起回ACK,俗称延迟ACK。
那自然就会面临一个问题:如果没有下个请求了,这个ACK就迟迟的发不会去了吗?
所以这个延迟功能就需要加个兜底时间,超过了兜底时间就补上迟迟没发的ACK。
那怎么手动关闭这个功能呢?
root权限下把/proc/sys/net/ipv4/tcp_no_delay_ack文件的值修改成1即可。
这样的问题就是每个TCP数据包都会有一个ACK包,增加了网络的包量。
本文首发于公众号:天空的代码世界,微信号:tiankonguse-code。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- RabbitMQ延迟消息的延迟极限是多少?
- RabbitMQ延迟消息的延迟极限是多少?
- 延迟静态绑定——static
- RabbitMQ实现延迟队列
- mybatis 延迟加载
- mybatis教程--延迟加载详解
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Writing Apache Modules with Perl and C
Lincoln Stein、Doug MacEachern / O'Reilly Media, Inc. / 1999-03 / USD 39.95
Apache is the most popular Web server on the Internet because it is free, reliable, and extensible. The availability of the source code and the modular design of Apache makes it possible to extend Web......一起来看看 《Writing Apache Modules with Perl and C》 这本书的介绍吧!