高性能網(wǎng)絡編程系列

本系列轉(zhuǎn)自陶輝大牛的博客。

高性能網(wǎng)絡編程(一)----accept建立連接

高性能網(wǎng)絡編程2----TCP消息的發(fā)送

  1. SO_SNDTIMEO
    發(fā)送超時時間,可以簡單的認為是把用戶態(tài)數(shù)據(jù)copy到TCP發(fā)送緩沖區(qū)的超時時間。
    JVM中該參數(shù)就是0。

3. 高性能網(wǎng)絡編程3----TCP消息的接收

3.1 四種隊列

為了功能區(qū)分和減小并發(fā)加鎖競爭,所以組織了多種隊列
1.1 receive(數(shù)據(jù)是已去除TCP協(xié)議之后的可以直接被copy到用戶態(tài)的數(shù)據(jù))
1.2 out-of-order
1.3 prequeue
1.4 backlog(socket被加鎖時放入)

3.2 prequeue與tcp_low_latency

當有socket正在睡眠以等待更多的數(shù)據(jù)時,新到的包根據(jù)tcp_low_latency的配置可能到prequeue隊列,也可能到receive或者out-of-order隊列。
tcp_low_latency默認為0,即關閉,此時新到的包進入tcp_low_latency

3.2.1 prequeue

  1. tcp_low_latency打開時
    在TCP中斷時需要處理ACK響應等TCP協(xié)議,去除TCP頭等信息(放入receive隊列的需要去除),甚至還可能把數(shù)據(jù)直接copy到用戶態(tài)buffer。
    所以,這種模式下用戶進程能快速的得到數(shù)據(jù),但是軟中斷的時間長,造成TCP吞吐量下降。
  2. tcp_low_latency關閉時
    與普通機制的主要區(qū)別在于,在進程沒有收取到足夠的數(shù)據(jù)而睡眠等待時,prequeue機制會將skb放入prequeue隊列中再喚醒進程,再由進程對skb進行TCP協(xié)議處理,再copy數(shù)據(jù);而普通模式下skb會在軟中斷上下文處理,在放入sk->sk_receive_queue隊列中后再喚醒進程,進程被喚醒后只是copy數(shù)據(jù)。對比普通模式,prequeue機制下使得skb的TCP協(xié)議處理延遲,延遲的時間為從skb被放入prequeue隊列并喚醒進程開始,到進程被調(diào)度到時調(diào)用tcp_prequeue_process函數(shù)處理skb時截止。對于收數(shù)據(jù)的進程而言在一次數(shù)據(jù)接收過程中其實并沒有延遲,因為普通模式下進程也會經(jīng)歷睡眠-喚醒的過程。但由于TCP協(xié)議處理被延遲,導致ACK的發(fā)送延遲,從而使數(shù)據(jù)發(fā)送端的數(shù)據(jù)發(fā)送延遲,最終會使得整個通信過程延遲增大?,F(xiàn)在我們知道prequeue機制延遲大的原因了:skb的TCP協(xié)議處理不是在軟中斷中進行,而是推遲到應用進程調(diào)用收包系統(tǒng)調(diào)用時。

3.2.2 為什么有用戶進程因等待數(shù)據(jù)睡眠時才有tcp_low_latency機制

因為有進程在等待,所以可以讓新到的包的TCP協(xié)議完成由等待的進程完成。

3.3 一些參數(shù)

  1. SO_RCVTIMEO
    JAVA不不支持設置該參數(shù),該參數(shù)JVM設的為0
  2. SO_RCVLOWAT
    《UNIX網(wǎng)絡編程中》描述該參數(shù)用于select/epoll,和本位描述不符。
  3. TP_LOW_LATENCY

4. 網(wǎng)絡編程4--TCP連接的關閉

4.1 監(jiān)聽句柄的關閉

半連接直接發(fā)RST

4.2 關閉ESTABLISH狀態(tài)的連接

  1. 如果還有數(shù)據(jù)未讀取
    發(fā)RST
  2. 如果還有待發(fā)送的數(shù)據(jù)
    發(fā)送,在最后一個報文加上FIN
  3. so_linger
    so_linger是close(無論socket是否工作在阻塞模式,都是阻塞的)的超時時間,用來盡量保證對方收到了close時發(fā)出的消息,即,至少需要對方通過發(fā)送ACK且到達本機。

5. 高性能網(wǎng)絡編程5--IO復用與并發(fā)編程

  1. select和epoll
    select每次調(diào)用都需要把所有欲監(jiān)控的socket傳入內(nèi)核態(tài)
  2. epoll提供的2種玩法ET和LT
    LT是每次滿足期待狀態(tài)的連接,都得在epoll_wait中返回,所以它一視同仁,都在一條水平線上。ET則不然,它傾向更精確的返回連接。在上面的例子中,連接第一次變?yōu)榭蓪懞?,若是程序未向連接上寫入任何數(shù)據(jù),那么下一次epoll_wait是不會返回這個連接的。ET叫做 邊緣觸發(fā),就是指,只有連接從一個狀態(tài)轉(zhuǎn)到另一個狀態(tài)時,才會觸發(fā)epoll_wait返回它??梢姡珽T的編程要復雜不少,至少應用程序要小心的防止epoll_wait的返回的連接出現(xiàn):可寫時未寫數(shù)據(jù)后卻期待下一次“可寫”、可讀時未讀盡數(shù)據(jù)卻期待下一次“可讀”。

6. 高性能網(wǎng)絡編程6--reactor反應堆與定時器管理

7. 高性能網(wǎng)絡編程7--tcp連接的內(nèi)存使用

net.ipv4.tcp_rmem = 8192 87380 16777216  
net.ipv4.tcp_wmem = 8192 65536 16777216  
net.ipv4.tcp_mem = 8388608 12582912 16777216  
net.core.rmem_default = 262144  
net.core.wmem_default = 262144  
net.core.rmem_max = 16777216  
net.core.wmem_max = 16777216  

7.1 net.ipv4.tcp_adv_win_scale = 2

讀取緩沖包含兩部分:

  1. 于應用程序的延時報文讀取
  2. 接收窗口

tcp_adv_win_scale意味著,將要拿出1/(2^tcp_adv_win_scale)緩存出來做應用緩存。即,默認tcp_adv_win_scale配置為2時,就是拿出至少1/4的內(nèi)存用于應用讀緩存,那么,最大的接收滑動窗口的大小只能到達讀緩存的3/4。

7.2 初始的擁塞窗口

以廣為使用的linux2.6.18內(nèi)核為例,在以太網(wǎng)里,MSS大小為1460,此時初始窗口大小為4倍的MSS。有些網(wǎng)絡中,會在TCP的可選頭部里,使用12字節(jié)作為時間戳使用,這樣,有效數(shù)據(jù)就是MSS再減去12,初始窗口就是(1460-12)4=5792*,這與窗口想表達的含義是一致的,即:我能夠處理的有效數(shù)據(jù)長度。

在linux3以后的版本中,初始窗口調(diào)整到了10個MSS大小,這主要來自于GOOGLE的建議。原因是這樣的,接收窗口雖然常以指數(shù)方式來快速增加窗口大?。〒砣y值以下是指數(shù)增長的,閥值以上進入擁塞避免階段則為線性增長,而且,擁塞閥值自身在收到128以上數(shù)據(jù)報文時也有機會快速增加),若是傳輸視頻這樣的大數(shù)據(jù),那么隨著窗口增加到(接近)最大讀緩存后,就會“開足馬力”傳輸數(shù)據(jù),但若是通常都是幾十KB的網(wǎng)頁,那么過小的初始窗口還沒有增加到合適的窗口時,連接就結束了。這樣相比較大的初始窗口,就使得用戶需要更多的時間(RTT)才能傳輸完數(shù)據(jù),體驗不好。

7.3 接收窗口應該設置多大?

image.png

所以:接收buffer大小=BDP*4/3

7.4 內(nèi)存

7.4.1 TCP緩存上限自動調(diào)整策略關閉

  1. SO_SNDBUF和SO_RCVBUF
    應用程序可以為某個連接設置的參數(shù),分別代表寫緩沖和讀緩沖的最大值。
    在內(nèi)核中會把這個值翻一倍再作為寫緩存上限使用。
  2. net.core.wmem_max和net.core.rmem_max
    操作系統(tǒng)級別的定義的參數(shù)。當SO_SNDBUF和SO_RCVBUF大于系統(tǒng)級的參數(shù)時,以系統(tǒng)級的為準。
    在內(nèi)核中也會把這個值翻一倍再作為寫緩存上限使用。
  3. net.core.rmem_default和net.core.wmem_default
    定義了讀寫緩沖區(qū)大小的默認值

7.4.2 TCP緩存上限自動調(diào)整策略

在并發(fā)連接比較少時,把緩存限制放大一些,讓每一個TCP連接開足馬力工作;當并發(fā)連接很多時,此時系統(tǒng)內(nèi)存資源不足,那么就把緩存限制縮小一些,使每一個TCP連接的緩存盡量的小一些,以容納更多的連接。
net.ipv4.tcp_moderate_rcvbuf = 1
默認tcp_moderate_rcvbuf配置為1,表示打開了TCP內(nèi)存自動調(diào)整功能。若配置為0,這個功能將不會生效(慎用)。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 最近在部門內(nèi)做了個高性能網(wǎng)絡編程的培訓,近日整理了下PPT,欲寫成一系列文章從應用角度談談它。 編寫服務器時,許多...
    泥孩兒0107閱讀 280評論 0 1
  • 最近在看《UNIX網(wǎng)絡編程 卷1》和《FREEBSD操作系統(tǒng)設計與實現(xiàn)》這兩本書,我重點關注了TCP協(xié)議相關的內(nèi)容...
    腩啵兔子閱讀 1,279評論 0 7
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,540評論 19 139
  • 相逢不語,一朵芙蓉著秋雨。 小暈紅潮,斜溜鬟心只鳳翹。 待將低喚,直為凝情恐人見。 欲訴幽懷,轉(zhuǎn)...
    孤寂的貓生閱讀 321評論 0 1

友情鏈接更多精彩內(nèi)容