先說一下結論。
那麼
默認 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;