tcp_nodelay memcached java_TCP_NODELAY 和 TCP_NOPUSH
TCP_NODELAY 和 TCP_NOPUSH
一、問題的來源
今天看到 huoding 大哥分享的 lamp 面試題,其中一點提到了:
Nginx 有兩個配置項: TCP_NODELAY 和 TCP_NOPUSH ,請說明它們的用途及注意事項。
初看到這個題目時,感覺有點印象:
1、在nginx.conf 中確實有這兩項,記得就是配置on或者off,跟性能有關(guān),但具體如何影響性能不太清楚
2、在之前看過的huoding另一篇將memcache的文章中,有提到過tcp DELAY算法,記得說是當tcp傳輸小于mss的包時不會立即發(fā)生,會緩沖一段時間,當之前發(fā)生的包被ack后才繼續(xù)發(fā)生緩沖中的小包。
二、問題的研究
1、從nginx模塊中來查看:
語法:tcp_nodelay on | off;
默認值:
tcp_nodelay on;
上下文:http, server, location
開啟或關(guān)閉nginx使用TCP_NODELAY選項的功能。 這個選項僅在將連接轉(zhuǎn)變?yōu)殚L連接的時候才被啟用。(譯者注,在upstream發(fā)送響應(yīng)到客戶端時也會啟用)。
語法:tcp_nopush on | off;
默認值:
tcp_nopush off;
上下文:http, server, location
開啟或者關(guān)閉nginx在FreeBSD上使用TCP_NOPUSH套接字選項, 在Linux上使用TCP_CORK套接字選項。 選項僅在使用sendfile的時候才開啟。 開啟此選項允許
在Linux和FreeBSD 4.*上將響應(yīng)頭和正文的開始部分一起發(fā)送;
一次性發(fā)送整個文件。
從模塊指令的解釋中帶出來幾個問題:
(1)tcp_nodelay的功能是什么?為什么只有在長連接的時候才啟用?Only included in keep-alive connections.
(2)tcp_nopush在unix上影響TCP_NOPUSH,在linux上影響TCP_CORK,但估計這只是不同系統(tǒng)上的命名區(qū)別,但作用是什么?為什么只在sendfile中才啟用?This option is only available when using sendfile.
這些問題我們需要逐一解決...
2、tcp_nodelay的功能是什么
Nagle和DelayedAcknowledgment的延遲問題
老實說,這個問題和Memcached沒有半毛錢關(guān)系,任何網(wǎng)絡(luò)應(yīng)用都有可能會碰到這個問題,但是鑒于很多人在寫Memcached程序的時候會遇到這個問題,所以還是拿出來聊一聊,
在這之前我們先來看看Nagle和DelayedAcknowledgment的含義:
先看看Nagle:
假如需要頻繁的發(fā)送一些小包數(shù)據(jù),比如說1個字節(jié),以IPv4為例的話,則每個包都要附帶40字節(jié)的頭,也就是說,總計41個字節(jié)的數(shù)據(jù)里,其中只有1個字節(jié)是我們需要的數(shù)據(jù)。
為了解決這個問題,出現(xiàn)了Nagle算法。它規(guī)定:如果包的大小滿足MSS,那么可以立即發(fā)送,否則數(shù)據(jù)會被放到緩沖區(qū),等到已經(jīng)發(fā)送的包被確認了之后才能繼續(xù)發(fā)送。
通過這樣的規(guī)定,可以降低網(wǎng)絡(luò)里小包的數(shù)量,從而提升網(wǎng)絡(luò)性能。
再看看DelayedAcknowledgment:
假如需要單獨確認每一個包的話,那么網(wǎng)絡(luò)中將會充斥著無數(shù)的ACK,從而降低了網(wǎng)絡(luò)性能。
為了解決這個問題,DelayedAcknowledgment規(guī)定:不再針對單個包發(fā)送ACK,而是一次確認兩個包,或者在發(fā)送響應(yīng)數(shù)據(jù)的同時捎帶著發(fā)送ACK,又或者觸發(fā)超時時間后再發(fā)送ACK。
通過這樣的規(guī)定,可以降低網(wǎng)絡(luò)里ACK的數(shù)量,從而提升網(wǎng)絡(luò)性能。
3、Nagle和DelayedAcknowledgment是如何影響性能的
Nagle和DelayedAcknowledgment雖然都是好心,但是它們在一起的時候卻會辦壞事。
如果一個 TCP 連接的一端啟用了 Nagle‘s Algorithm,而另一端啟用了 TCP Delayed Ack,而發(fā)送的數(shù)據(jù)包又比較小,則可能會出現(xiàn)這樣的情況:
發(fā)送端在等待接收端對上一個packet 的 Ack 才發(fā)送當前的 packet,而接收端則正好延遲了此 Ack 的發(fā)送,那么這個正要被發(fā)送的 packet 就會同樣被延遲。
當然 Delayed Ack 是有個超時機制的,而默認的超時正好就是 40ms。
現(xiàn)代的 TCP/IP 協(xié)議棧實現(xiàn),默認幾乎都啟用了這兩個功能,你可能會想,按我上面的說法,當協(xié)議報文很小的時候,豈不每次都會觸發(fā)這個延遲問題?
事實不是那樣的。僅當協(xié)議的交互是發(fā)送端連續(xù)發(fā)送兩個 packet,然后立刻 read 的 時候才會出現(xiàn)問題。
現(xiàn)在讓我們假設(shè)某個應(yīng)用程序發(fā)出了一個請求,希望發(fā)送小塊數(shù)據(jù)。我們可以選擇立即發(fā)送數(shù)據(jù)或者等待產(chǎn)生更多的數(shù)據(jù)然后再一次發(fā)送兩種策略。
如果我們馬上發(fā)送數(shù)據(jù),那么交互性的以及客戶/服務(wù)器型的應(yīng)用程序?qū)O大地受益。
例如,當我們正在發(fā)送一個較短的請求并且等候較大的響應(yīng)時,相關(guān)過載與傳輸?shù)臄?shù)據(jù)總量相比就會比較低,而且,如果請求立即發(fā)出那么響應(yīng)時間也會快一些。
以上操作可以通過設(shè)置套接字的TCP_NODELAY選項來完成,這樣就禁用了Nagle 算法。
另外一種情況則需要我們等到數(shù)據(jù)量達到最大時才通過網(wǎng)絡(luò)一次發(fā)送全部數(shù)據(jù),這種數(shù)據(jù)傳輸方式有益于大量數(shù)據(jù)的通信性能,典型的應(yīng)用就是文件服務(wù)器。
應(yīng)用Nagle算法在這種情況下就會產(chǎn)生問題。但是,如果你正在發(fā)送大量數(shù)據(jù),你可以設(shè)置TCP_CORK選項禁用Nagle化,其方式正好同 TCP_NODELAY相反(TCP_CORK 和 TCP_NODELAY 是互相排斥的)。
假設(shè)客戶端的請求發(fā)生需要等待服務(wù)端的應(yīng)答后才能繼續(xù)發(fā)生下一包,即串行執(zhí)行,
好比在用ab性能測試時只有一個并發(fā)做10k的壓力測試,測試地址返回的內(nèi)容只有Hello world;ab發(fā)出的request需要等待服務(wù)器返回response時,才能發(fā)生下一個request;
此時ab只會發(fā)生一個get請求,請求的相關(guān)內(nèi)容包含在header中;而服務(wù)器需要返回兩個數(shù)據(jù),一個是response頭,另一個是html body;
服務(wù)器發(fā)送端發(fā)送的第一個 write 是不會被緩沖起來,而是立刻發(fā)送的(response header),
這時ab接收端收到對應(yīng)的數(shù)據(jù),但它還期待更多數(shù)據(jù)(html)才進行處理,所以不會往回發(fā)送數(shù)據(jù),因此也沒機會把 Ack 給帶回去,根據(jù)Delayed Ack 機制, 這個 Ack 會被 Hold 住。
這時服務(wù)器發(fā)送端發(fā)送第二個包,而隊列里還有未確認的數(shù)據(jù)包(response header),這個 packet(html) 會被緩沖起來。
此時,服務(wù)器發(fā)送端在等待ab接收端的 Ack;ab接收端則在 Delay 這個 Ack,所以都在等待,
直到ab接收端 Deplayed Ack 超時(40ms),此 Ack 被發(fā)送回去,發(fā)送端緩沖的這個 packet(html) 才會被真正送到接收端,
此時ab才接受到完整的數(shù)據(jù),進行對應(yīng)的應(yīng)用層處理,處理完成后才繼續(xù)發(fā)生下一個request,因此服務(wù)器端才會在read時出現(xiàn)40ms的阻塞。
4、tcp_nodelay為什么只在keep-alive才啟作用
TCP中的Nagle算法默認是啟用的,但是它并不是適合任何情況,對于telnet或rlogin這樣的遠程登錄應(yīng)用的確比較適合(原本就是為此而設(shè)計),但是在某些應(yīng)用場景下我們卻又需要關(guān)閉它。
在Apache對HTTP持久連接(Keep-Alive,Prsistent-Connection)處理時凸現(xiàn)的奇數(shù)包&結(jié)束小包問題(The Odd/Short-Final-Segment Problem),
這是一個并的關(guān)系,即問題是由于已有奇數(shù)個包發(fā)出,并且還有一個結(jié)束小包(在這里,結(jié)束小包并不是指帶FIN旗標的包,而是指一個HTTP請求或響應(yīng)的結(jié)束包)等待發(fā)出而導致的。
我們來看看具體的問題詳情,以3個包+1個結(jié)束小包為例,可能發(fā)生的發(fā)包情況:
服務(wù)器向客戶端發(fā)出兩個大包;客戶端在接受到兩個大包時,必須回復ack;
接著服務(wù)器向客戶端發(fā)送一個中包或小包,但服務(wù)器由于Delayed Acknowledgment并沒有馬上ack;
由于發(fā)生隊列中有未被ack的包,因此最后一個結(jié)束的小包被阻塞等待。
最后一個小包包含了整個響應(yīng)數(shù)據(jù)的最后一些數(shù)據(jù),所以它是結(jié)束小包,如果當前HTTP是非持久連接,那么在連接關(guān)閉時,最后這個小包會立即發(fā)送出去,這不會出現(xiàn)問題;
但是,如果當前HTTP是持久連接(非pipelining處理,pipelining僅HTTP 1.1支持,nginx目前對pipelining的支持很弱,它必須是前一個請求完全處理完后才能處理后一個請求),
即進行連續(xù)的Request/Response、Request/Response、…,處理,那么由于最后這個小包受到Nagle算法影響無法及時的發(fā)送出去
(具體是由于客戶端在未結(jié)束上一個請求前不會發(fā)出新的request數(shù)據(jù),導致無法攜帶ACK而延遲確認,進而導致服務(wù)器沒收到客戶端對上一個小包的的確認導致最后一個小包無法發(fā)送出來),
導致第n次請求/響應(yīng)未能結(jié)束,從而客戶端第n+1次的Request請求數(shù)據(jù)無法發(fā)出。
在http長連接中,服務(wù)器的發(fā)生類似于:Write-Write-Read,即返回response header、返回html、讀取下一個request
而在http短連接中,服務(wù)器的發(fā)生類似于:write-read-write-read,即返回處理結(jié)果后,就主動關(guān)閉連接,短連接中的close之前的小包會立即發(fā)生,不會阻塞
我的理解是這樣的:因為第一個 write 不會被緩沖,會立刻到達接收端,如果是 write-read-write-read 模式,此時接收端應(yīng)該已經(jīng)得到所有需要的數(shù)據(jù)以進行下一步處理。
接收端此時處理完后發(fā)送結(jié)果,同時也就可以把上一個packet 的 Ack 可以和數(shù)據(jù)一起發(fā)送回去,不需要 delay,從而不會導致任何問題。
我做了一個簡單的試驗,注釋掉了 HTTP Body 的發(fā)送,僅僅發(fā)送 Headers, Content-Length 指定為 0。
這樣就不會有第二個 write,變成了 write-read-write-read 模式。此時再用 ab 測試,果然沒有 40ms 的延遲了。
因此在短連接中并不存在小包阻塞的問題,而在長連接中需要做tcp_nodelay開啟。
5、那tcp_nopush又是什么?
TCP_CORK選項的功能類似于在發(fā)送數(shù)據(jù)管道出口處插入一個“塞子”,使得發(fā)送數(shù)據(jù)全部被阻塞,直到取消TCP_CORK選項(即拔去塞子)或被阻塞數(shù)據(jù)長度已超過MSS才將其發(fā)送出去。
選項TCP_NODELAY是禁用Nagle算法,即數(shù)據(jù)包立即發(fā)送出去,而選項TCP_CORK與此相反,可以認為它是Nagle算法的進一步增強,即阻塞數(shù)據(jù)包發(fā)送,
具體點說就是:TCP_CORK選項的功能類似于在發(fā)送數(shù)據(jù)管道出口處插入一個“塞子”,使得發(fā)送數(shù)據(jù)全部被阻塞,
直到取消TCP_CORK選項(即拔去塞子)或被阻塞數(shù)據(jù)長度已超過MSS才將其發(fā)送出去。
舉個對比示例,比如收到接收端的ACK確認后,Nagle算法可以讓當前待發(fā)送數(shù)據(jù)包發(fā)送出去,即便它的當前長度仍然不夠一個MSS,
但選項TCP_CORK則會要求繼續(xù)等待,這在前面的tcp_nagle_check()函數(shù)分析時已提到這一點,即如果包數(shù)據(jù)長度小于當前MSS &&((加塞 || …)|| …),那么緩存數(shù)據(jù)而不立即發(fā)送:
在TCP_NODELAY模式下,假設(shè)有3個小包要發(fā)送,第一個小包發(fā)出后,接下來的小包需要等待之前的小包被ack,在這期間小包會合并,直到接收到之前包的ack后才會發(fā)生;
而在TCP_CORK模式下,第一個小包都不會發(fā)生成功,因為包太小,發(fā)生管道被阻塞,同一目的地的小包彼此合并后組成一個大于mss的包后,才會被發(fā)生
TCP_CORK選項“堵塞”特性的最終目的無法是為了提高網(wǎng)絡(luò)利用率,既然反正是要發(fā)一個數(shù)據(jù)包(零窗口探測包),
如果有實際數(shù)據(jù)等待發(fā)送,那么干脆就直接發(fā)送一個負載等待發(fā)送數(shù)據(jù)的數(shù)據(jù)包豈不是更好?
我們已經(jīng)知道,TCP_CORK選項的作用主要是阻塞小數(shù)據(jù)發(fā)送,所以在nginx內(nèi)的用處就在對響應(yīng)頭的發(fā)送處理上。
一般而言,處理一個客戶端請求之后的響應(yīng)數(shù)據(jù)包括有響應(yīng)頭和響應(yīng)體兩部分,那么利用TCP_CORK選項就能讓這兩部分數(shù)據(jù)一起發(fā)送:
假設(shè)我們需要等到數(shù)據(jù)量達到最大時才通過網(wǎng)絡(luò)一次發(fā)送全部數(shù)據(jù),這種數(shù)據(jù)傳輸方式有益于大量數(shù)據(jù)的通信性能,典型的應(yīng)用就是文件服務(wù)器。
應(yīng)用Nagle算法在這種情況下就會產(chǎn)生問題。因為TCP_NODELAY在發(fā)生小包時不再等待之前的包有沒有ack,網(wǎng)絡(luò)中會存在較多的小包,但這會影響網(wǎng)絡(luò)的傳輸能力;
但是,如果你正在發(fā)送大量數(shù)據(jù),你可以設(shè)置TCP_CORK選項禁用Nagle化,其方式正好同 TCP_NODELAY相反(TCP_CORK 和 TCP_NODELAY 是互相排斥的)。
下面就讓我們仔細分析下其工作原理。
假設(shè)應(yīng)用程序使用sendfile()函數(shù)來轉(zhuǎn)移大量數(shù)據(jù)。應(yīng)用協(xié)議通常要求發(fā)送某些信息來預先解釋數(shù)據(jù),這些信息其實就是報頭內(nèi)容。
典型情況下報頭很小,而且套接字上設(shè)置了TCP_NODELAY。有報頭的包將被立即傳輸,在某些情況下(取決于內(nèi)部的包計數(shù)器),因為這個包成功地被對方收到后需要請求對方確認。
這樣,大量數(shù)據(jù)的傳輸就會被推遲而且產(chǎn)生了不必要的網(wǎng)絡(luò)流量交換。
但是,如果我們在套接字上設(shè)置了TCP_CORK(可以比喻為在管道上插入“塞子”)選項,具有報頭的包就會填補大量的數(shù)據(jù),所有的數(shù)據(jù)都根據(jù)大小自動地通過包傳輸出去。
當數(shù)據(jù)傳輸完成時,最好取消TCP_CORK 選項設(shè)置給連接“拔去塞子”以便任一部分的幀都能發(fā)送出去。這同“塞住”網(wǎng)絡(luò)連接同等重要。
總而言之,如果你肯定能一起發(fā)送多個數(shù)據(jù)集合(例如HTTP響應(yīng)的頭和正文),那么我們建議你設(shè)置TCP_CORK選項,這樣在這些數(shù)據(jù)之間不存在延遲。
能極大地有益于WWW、FTP以及文件服務(wù)器的性能,同時也簡化了你的工作。
6、sendfile
從技術(shù)角度來看,sendfile()是磁盤和傳輸控制協(xié)議(TCP)之間的一種系統(tǒng)呼叫,但是sendfile()還能夠用來在兩個文件夾之間移動數(shù)據(jù)。
在各種不同的操作系統(tǒng)上實現(xiàn)sendfile()都會有所不同,當然這種不同只是極為細微的差別。通常來說,我們會假定所使用的操作系統(tǒng)是Linux核心2.4版本。
系統(tǒng)呼叫的原型有如下幾種:
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
in_fd是一種用來讀文件的文件描述符。
out_fd是一種用來寫文件的描述符。
Offset是一種指向被輸入文件變量位置的指針,sendfile()將會從它所指向的位置開始數(shù)據(jù)的讀取。
Count表示的是兩個文件描述符之間數(shù)據(jù)拷貝的字節(jié)數(shù)。
sendfile()的威力在于,它為大家提供了一種訪問當前不斷膨脹的Linux網(wǎng)絡(luò)堆棧的機制。
這種機制叫做“零拷貝(zero-copy)”,這種機制可以把“傳輸控制協(xié)議(TCP)”框架直接的從主機存儲器中傳送到網(wǎng)卡的緩存塊(network card buffers)中去。
為了更好的理解“零拷貝(zero-copy)”以及sendfile(),讓我們回憶一下以前我們在傳送文件時所需要執(zhí)行的那些步驟。
首先,一塊在用戶機器存儲器內(nèi)用于數(shù)據(jù)緩沖的位置先被確定了下來。
然后,我們必須使用read()這條系統(tǒng)呼叫來把數(shù)據(jù)從文件中拷貝到前邊已經(jīng)準備好的那個緩沖區(qū)中去。
(在通常的情況下,這個操做會把數(shù)據(jù)從磁盤上拷貝到操作系統(tǒng)的高速緩沖存儲器中去,然后才會把數(shù)據(jù)從高速緩沖存儲器中拷貝至用戶空間中去,這種過程就是所謂的“上下文切換”。)
在完成了上述的那些步驟之后,我們得使用write()系統(tǒng)呼叫來將緩沖區(qū)中的內(nèi)容發(fā)送到網(wǎng)絡(luò)上去,程序段如下所示:
intout_fd, intin_fd;
char buffer[BUFLEN];
…
/* unsubstantial code skipped for clarity */
…
read(in_fd, buffer, BUFLEN); /* syscall, make context switch */
write(out_fd, buffer, BUFLEN); /* syscall, make context switch */
操作系統(tǒng)核心不得不把所有的數(shù)據(jù)至少都拷貝兩次:先是從核心空間到用戶空間的拷貝,然后還得再從用戶空間拷貝回核心空間。
每一次操做都需要上下文切換(context-switch)的這個步驟,其中包含了許多復雜的高度占用CPU的操作。
系統(tǒng)自帶的工具vmstat能夠用來在絕大多數(shù)UNIX以及與其類似的操作系統(tǒng)上顯示當前的“上下文切換(context-switch)”速率。
請看叫做“CS”的那一欄,有相當一部分的上下文切換是發(fā)生在取樣期間的。用不同類型的方式進行裝載可以讓使用者清楚的看到使用這些參數(shù)進行裝載時的不同效果。
在有了sendfile()零拷貝(zero-copy)之后,如果可能的話,通過使用直接存儲器訪問(Direct Memory Access)的硬件設(shè)備,數(shù)據(jù)從磁盤讀取到操作系統(tǒng)高速緩沖存儲器中會變得非常之迅速。
而TLB高速緩沖存儲器則被完整無缺的放在那里,沒有充斥任何有關(guān)數(shù)據(jù)傳輸?shù)奈募?/p>
應(yīng)用軟件在使用sendfile() primitive的時候會有很高的性能表現(xiàn),這是因為系統(tǒng)呼叫沒有直接的指向存儲器,因此,就提高了傳輸數(shù)據(jù)的性能。
通常來說,要被傳輸?shù)臄?shù)據(jù)都是從系統(tǒng)緩沖存儲器中直接讀取的,其間并沒有進行上下文切換的操作,也沒有垃圾數(shù)據(jù)占據(jù)高速緩沖存儲器。
因此,在服務(wù)器應(yīng)用程序中使用sendfile()能夠顯著的減少對CPU的占用。
TCP/IP網(wǎng)絡(luò)的數(shù)據(jù)傳輸通常建立在數(shù)據(jù)塊的基礎(chǔ)之上。從程序員的觀點來看,發(fā)送數(shù)據(jù)意味著發(fā)出(或者提交)一系列“發(fā)送數(shù)據(jù)塊”的請求。
在系統(tǒng)級,發(fā)送單個數(shù)據(jù)塊可以通過調(diào)用系統(tǒng)函數(shù)write() 或者sendfile() 來完成。
因為在網(wǎng)絡(luò)連接中是由程序員來選擇最適當?shù)膽?yīng)用協(xié)議,所以網(wǎng)絡(luò)包的長度和順序都在程序員的控制之下。同樣的,程序員還必須選擇這個協(xié)議在軟件中得以實現(xiàn)的方式。
TCP/IP協(xié)議自身已經(jīng)有了多種可互操作的實現(xiàn),所以在雙方通信時,每一方都有它自身的低級行為,這也是程序員所應(yīng)該知道的情況。
盡管有許多TCP選項可供程序員操作,而我們卻最關(guān)注如何處置其中的兩個選項,它們是TCP_NODELAY 和 TCP_CORK,這兩個選項都對網(wǎng)絡(luò)連接的行為具有重要的作用。
許多UNIX系統(tǒng)都實現(xiàn)了TCP_NODELAY選項,但是,TCP_CORK則是Linux系統(tǒng)所獨有的而且相對較新;它首先在內(nèi)核版本2.4上得以實現(xiàn)。
此外,其他UNIX系統(tǒng)版本也有功能類似的選項,值得注意的是,在某種由BSD派生的系統(tǒng)上的TCP_NOPUSH選項其實就是TCP_CORK的一部分具體實現(xiàn)。
三、總結(jié)
你的數(shù)據(jù)傳輸并不需要總是準確地遵守某一選項或者其它選擇。在那種情況下,你可能想要采取更為靈活的措施來控制網(wǎng)絡(luò)連接:
在發(fā)送一系列當作單一消息的數(shù)據(jù)之前設(shè)置TCP_CORK,而且在發(fā)送應(yīng)立即發(fā)出的短消息之前設(shè)置TCP_NODELAY。
如果需要提供網(wǎng)絡(luò)的傳輸效率,應(yīng)該減少小包的傳輸,使用TCP_CORK來做匯總傳輸,在利用sendfile來提高效率;
但如果是交互性的業(yè)務(wù),那應(yīng)該讓任意小包可以快速傳輸,關(guān)閉Nagle算法,提高包的傳輸效率。
TCP_CORK優(yōu)化了傳輸?shù)腷its效率,tcp_nodelay優(yōu)化了傳輸?shù)膒acket效率。
語法:tcp_nodelay on | off;
默認值:
tcp_nodelay on;
上下文:http, server, location
開啟或關(guān)閉nginx使用TCP_NODELAY選項的功能。 這個選項僅在將連接轉(zhuǎn)變?yōu)殚L連接的時候才被啟用。(譯者注,在upstream發(fā)送響應(yīng)到客戶端時也會啟用)。
語法:tcp_nopush on | off;
默認值:
tcp_nopush off;
上下文:http, server, location
開啟或者關(guān)閉nginx在FreeBSD上使用TCP_NOPUSH套接字選項, 在Linux上使用TCP_CORK套接字選項。 選項僅在使用sendfile的時候才開啟。
總結(jié)
以上是生活随笔為你收集整理的tcp_nodelay memcached java_TCP_NODELAY 和 TCP_NOPUSH的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java中批次号_在一个批次中插入多笔记
- 下一篇: docker java 不兼容_Appl