先说一下结论。
那么
默认 spymemcached 是不启用 Nagle 算法的。
因此默认状况下不会引起恨少在《
libmemcached的MEMCACHED_MAX_BUFFER问题》一文中说起的“
shell脚本set 1000次8KB的item,只要3s左右,平均须要3ms。而C++版本则须要39s左右,平均耗时39ms……发现8KB的数据须要发送两次,两次write都是很是快的,可是
等memcached返回时用了不少时间,主要的时间就耗费在这个地方”现象。我们业务中心能够排除这个嫌疑。
什么是 Nagle 算法?
『
TCP/IP 协议中,不管发送多少数据,老是要在数据前面加上协议头,同时,对方接收到数据,也须要发送ACK表示确认。为了尽量地利用网络带宽,TCP老是但愿尽 可能地发送足够大的数据。(一个链接会设置MSS参数,所以,TCP/IP但愿每次都可以以MSS尺寸的数据块来发送数据)。
Nagle算法就是为了尽量发送大块数据,避免网络中充斥着许多小数据块。
N
agle算法的基本定义是
任意时刻,最多只能有一个未被确认的小段。 所谓“小段”,指的是小于MSS尺寸的数据块,所谓“未被确认”,是指一个数据块发送出去后,没有收到对方发送的ACK确认该数据已收到
。
Nagle算法的规则(可参考tcp_output.c文件里tcp_nagle_check函数注释): html
(1)若是包长度达到MSS,则容许发送; 前端
(2)若是该包含有FIN,则容许发送; java
(3)设置了TCP_NODELAY选项,则容许发送; git
(4)未设置TCP_CORK选项时,若全部发出去的小数据包(包长度小于MSS)均被确认,则容许发送; github
(5)上述条件都未知足,但发生了超时(通常为200ms),则当即发送。
spymemcached 默认不启用 Nagle 算法
/net/spy/memcached/ConnectionFactoryBuilder.java 中定义以下:
/**
* Builder for more easily configuring a ConnectionFactory.
*/
public
class
ConnectionFactoryBuilder
{
protected boolean useNagle = false;
……
public ConnectionFactoryBuilder(ConnectionFactory cf) {
……
setUseNagleAlgorithm
(
cf
.
useNagleAlgorithm
());
}
/**
* Set to true if you'd like to enable the Nagle algorithm.
*/
public
ConnectionFactoryBuilder
setUseNagleAlgorithm
(
boolean
to
)
{
useNagle
=
to
;
return
this
;
}
而后,转到 MemcachedConnection.java,说到底仍是调用 socket 的 setTcpNoDelay 方法:
protected List<MemcachedNode> createConnections(
……
ch.socket().
setTcpNoDelay(!this.connectionFactory.useNagleAlgorithm());
经过 bean definition 可设置 useNagleAlgorithm
<beanid="memcachedClient"class="net.spy.memcached.spring.MemcachedClientFactoryBean">……
<propertyname="useNagleAlgorithm"value="false"/> </bean>
p.s.:
2)mongo-java-driver 默认也禁用 Nagle 算法(DBPort.java 63行)。 算法
参考资源:
3)2009,
Issue 88: Turn off TCP nagle can hugely improve performance;