自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Linux高性能網(wǎng)絡編程十談 | 性能優(yōu)化(網(wǎng)絡)

系統(tǒng) Linux
上一篇文章講了《性能優(yōu)化(CPU和內存)》,這一節(jié)我們主要是聊聊網(wǎng)絡優(yōu)化。

上一篇文章講了《性能優(yōu)化(CPU和內存)》,這一節(jié)我們主要是聊聊網(wǎng)絡優(yōu)化。

第一部分:網(wǎng)絡性能度量

1、設備度量

設備主要是指塊設備,由于我們在開發(fā)過程中,需要磁盤操作,比如寫日志等,所以對于塊設備的I/O對于我們需要度量性能的一個重要指標。

(1)I/O等待

CPU等待I/O操作發(fā)生的時間,較高和持續(xù)的值很多時候表明IO有瓶頸,一般通過iostat -x命令查看:

[root@VM-0-11-centos ~]# iostat -x
Linux 3.10.0-1127.19.1.el7.x86_64 (VM-0-11-centos)  2023年09月23日  _x86_64_ (2 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.40    0.00    0.41    0.25    0.00   98.93

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda               0.00    10.12    0.08   10.13     1.82    85.81    17.16     0.02    2.03    9.06    1.97   0.36   0.37
scd0              0.00     0.00    0.00    0.00     0.00     0.00     7.14     0.00    0.27    0.27    0.00   0.27   0.00

其中avgqu-sz,avgrq-sz,await,iowait,svctm等這些都需要關注,其含義如下:

  • avgqu-sz是平均每次IO操作的數(shù)據(jù)量(扇區(qū)數(shù)為單位)
  • avgrq-sz是平均等待處理的IO請求隊列長度
  • await是平均每次IO請求等待時間(包括等待時間和處理時間,毫秒為單位)
  • svctm平均每次IO請求的處理時間(毫秒為單位)
  • iowait等待磁盤io所消耗的cpu比例

(2)平均隊列長度

未完成的I/O請求數(shù)量,一般情況下,小于3個是合理的,如果超過表示I/O存儲瓶頸,具體可以通過上面的iostat -x命令查看。

(3)平均等待時間

服務I/O請求所測量的平均時間,等待時間不能過長,如果平均等待過長,說明I/O繁忙,具體可以通過上面的iostat -x命令查看。

(4)每秒傳輸

描述每秒讀寫的性能,塊設備的讀寫性能隨著型號或者調度算法的不同存在比較大的差異,比如使用iostat -x可以看到rkB/s,wkB/s,rrqm/s,r/s和w/s,對于I/0滿載的情況下,這些值越大越好。

  • rrqm/s是每秒對該設備的讀請求被合并次數(shù),文件系統(tǒng)會對讀取同塊(block)的請求進行合并
  • wrqm/s是每秒對該設備的寫請求被合并次數(shù)
  • r/s是每秒完成的讀次數(shù)
  • w/s是每秒完成的寫次數(shù)
  • rkB/s是每秒讀數(shù)據(jù)量(kB為單位)
  • wkB/s是每秒寫數(shù)據(jù)量(kB為單位)

2、網(wǎng)絡度量

高性能編程一般都離不開網(wǎng)絡收發(fā),對于RPC Server的開發(fā),我們希望的收發(fā)和處理越快越好,那具體指標有哪些?

(1)接收和發(fā)送的數(shù)據(jù)包和字節(jié)

網(wǎng)絡接口性能可以按照數(shù)據(jù)包或者字節(jié)大小來決定, TODO:

(2)丟包

丟包是指被內核丟棄的數(shù)據(jù)包,丟棄的原因如下:

  • 連接隊列滿了
  • 收發(fā)緩沖區(qū)滿了
  • TCP底層重傳次數(shù)超過設置
  • 開啟了sync cookie等配置,阻止了一些攻擊包
  • 防火墻設置等

查看丟包是否增長可以通過netstat -s|grep drop命令查看:

[root@VM-0-11-centos ~]# netstat -s|grep drop
    40 dropped because of missing route
    10 SYNs to LISTEN sockets dropped

(3)連接隊列

這里連接隊列是指TCP的三次握手連接隊列(SYN半連接隊列和ACCEPT連接隊列),網(wǎng)絡接收隊列和網(wǎng)路發(fā)送隊列。

我們通過netstat -s | grep "SYNs to LISTEN"查看:

[root@VM-0-11-centos ~]# netstat -s | grep "SYNs to LISTEN"
    11 SYNs to LISTEN sockets dropped

或者通過ss -lt查看:

[root@VM-0-11-centos ~]# ss -lt
State      Recv-Q Send-Q                    Local Address:Port                                     Peer Address:Port
LISTEN     0      128                                   *:ssh
  • Recv-Q:表示收到的數(shù)據(jù)在接收隊列中,但是還有多少沒有被進程取走(非LISTEN的句柄),如果接收隊列一直處于阻塞狀態(tài)(這個值很高),可能緩存區(qū)太小了或者發(fā)包太快;
  • Send-Q:表示發(fā)送的數(shù)據(jù)在發(fā)送隊列中未確認的字節(jié)數(shù)(非LISTEN的句柄),如果發(fā)送隊列Send-Q不能很快的清零,可能是有應用向外發(fā)送數(shù)據(jù)包過快,或者是對方接收數(shù)據(jù)包不夠快;

(4)其他異常

除了上述度量還有其他一些異常度量,比如大量reset包,大量重傳包錯誤,或者能發(fā)包,但是不能收包等,網(wǎng)絡相關的度量和排查其實相對復雜,如果大家有興趣可以讀讀《Wireshark網(wǎng)絡分析就這么簡單》,可以通過自己抓包具體分析。

第二部分:網(wǎng)絡層優(yōu)化

1、零拷貝

在《Linux高性能網(wǎng)絡編程十談|系統(tǒng)調用》一文中,當時介紹了網(wǎng)絡收發(fā)包需要經(jīng)過多次系統(tǒng)調用和內存拷貝:

sendfilesendfile

為了高性能,Linux底層提供了一些零拷貝的系統(tǒng)調用如sendfile,以減少用戶態(tài)和內核態(tài)的切換,原理是什么呢?

如果內核在讀取文件后,直接把PageCache中的內容拷貝到socket緩沖區(qū),待到網(wǎng)卡發(fā)送完畢后,再通知進程,這樣就只有2次上下文切換,和3次內存拷貝;

如果網(wǎng)卡支持SG-DMA(The Scatter-Gather Direct Memory Access)技術,還可以再去除socket緩沖區(qū)的拷貝,這樣一共只有2次內存拷貝;

除了上述說的sendfile這種零拷貝可以減少用戶態(tài)到內核態(tài)切換和拷貝(因為網(wǎng)絡調用),還有一種DirectIO,這種常用于大文件讀寫(比如FTP Server或者其他CDN下載服務器),原因是由于大文件拷貝難以命中PageCache,導致額外的內存拷貝,如果用DirectIO就可以直接操作磁盤,開發(fā)者自己控制緩存。

2、解決C1000K

在早期的服務器開發(fā),從C10K(服務器同時處理1萬個TCP連接),C100K(服務器同時處理10萬個TCP連接)到C1000K(服務器同時處理100萬TCP連接),其實原理上還是使用前面說的方式:事件驅動,異步IO或者協(xié)程等,具體的原理在《IO復用和模式》《協(xié)程》這兩篇文章已經(jīng)介紹了,如果有興趣可以再回顧一下。而這里我們討論一下可能面臨的幾個場景如何解決:

遇到計算任務,雖然內存、CPU 的速度很快,然而循環(huán)執(zhí)行也可能耗時達到秒級,所以,如果一定要引入需要密集計算才能完成的請求,為了不阻礙其他事件的處理,要么把這樣的請求放在獨立的線程中完成,要么把請求的處理過程拆分成多段,確保每段能夠快速執(zhí)行完,同時每段執(zhí)行完都要均等地處理其他事件,這樣通過放慢該請求的處理時間,就保障了其他請求的及時處理,比如像Nginx;

讀寫文件,充分利用PageCache,小文件通過mmap加載到內存,而大文件拆分多個小文件處理;

所有socket操作全部都改為非阻塞,通過epoll或者kqueue來監(jiān)聽讀寫事件,并將事件拆分給對應的線程處理;

3、提升TCP握手和揮手性能

我們在前面網(wǎng)絡篇中已經(jīng)清楚了講解了三次握手和四次揮手的流程,但是實際由于TCP的握手協(xié)議和揮手協(xié)議交互流程過多,會導致一些性能問題,該如何解決?

(1)優(yōu)化握手參數(shù)

正常情況下,握手環(huán)節(jié)客戶端發(fā)送SYN開啟握手,服務器會在幾毫秒內返回ACK,但如果客戶端遲遲沒有收到ACK會怎么樣呢?客戶端會重發(fā)SYN,重試的次數(shù)由tcp_syn_retries參數(shù)控制,默認是6次:

net.ipv4.tcp_syn_retries = 6

同時每次傳輸時間是按照倍數(shù)遞增(1,2,4,8,32,64 ... 秒),所以在網(wǎng)絡繁忙情況下或者在業(yè)務明確不能太多超時情況下,調整這個時間到net.ipv4.tcp_syn_retries = 3,這樣能減少服務端在網(wǎng)絡繁忙情況下的連鎖反應。

上述是客戶端側調整,而服務端可能會出現(xiàn)半連接隊列滿了的場景,控制半連接隊列是net.ipv4.tcp_max_syn_backlog = 1024內核參數(shù),可以適當?shù)恼{大取值;同樣服務端在從半連接隊列轉換到ESTABLISHED,也需要確認客戶端回復的確認ACK,如果沒有收到也會重發(fā)SYN+ACK,所以這里Linux也提供調整的參數(shù)net.ipv4.tcp_synack_retries = 5,減少重傳次數(shù),降低加劇的風險;

除了以上的調整,減少握手的RTT也是一種優(yōu)化手段 —— TOF(TCP fast open),TFO到底怎樣達成這一目的呢?它把通訊分為兩個階段,第一階段為首次建立連接,這時走正常的三次握手,但在客戶端的SYN報文會明確地告訴服務器它想使用TFO功能,這樣服務器會把客戶端IP地址用只有自己知道的密鑰加密,作為Cookie攜帶在返回的SYN+ACK報文中,客戶端收到后會將Cookie緩存在本地;

第二階段就是每次TCP底層的報文都會帶上Cookie,只要帶上了Cookie的請求,服務端不需要收到客戶端的確認包,就可以直接傳輸數(shù)據(jù)了,這樣就減少了RTT;設置參數(shù)可以通過net.ipv4.tcp_fastopen = 3;

(2)優(yōu)化揮手參數(shù)

握手優(yōu)化有一些相應的方法,那揮手階段是否也可以優(yōu)化呢?我們應該在開發(fā)中經(jīng)常遇到是TIME_WAIT狀態(tài),估計踩過坑的應該不少,TIME_WAIT過多會消耗系統(tǒng)資源,端口耗盡導致想新建連接失敗,觸發(fā)Linux內核查找可用端口導致循環(huán)問題等。如何解決?設置tcp_max_tw_buckets參數(shù),當TIME_WAIT的連接數(shù)量超過該參數(shù)時,新關閉的連接就不再經(jīng)歷TIME_WAIT而直接關閉;或者快速復用端口tcp_tw_reuse,在安全條件下使用TIME_WAIT狀態(tài)下的端口。

在回顧一下TCP揮手的圖,被調方會有CLOSE_WAIT,如果在我們服務中有大量的CLOSE_WAIT時候,我們就得注意:

  • 是否在處理完調用方的時候后,忘記關閉連接
  • 服務負載太高,導致close調用被延時
  • 處理進程處于Pending狀態(tài),導致不能及時關閉連接

4、一些網(wǎng)絡內核參數(shù)

"提升TCP握手和揮手性能"已經(jīng)提到了一些優(yōu)化參數(shù),除了這些參數(shù)外還有一些對性能有幫助的參數(shù):

  • net.ipv4.tcp_syncookies = 1減少SYN泛洪攻擊
  • net.ipv4.tcp_abort_on_overflow = 1快速回復RST包,減緩accept隊列滿的情況
  • net.ipv4.tcp_orphan_retries = 5如果FIN_WAIT1狀態(tài)連接有很多,考慮調小該值
  • net.ipv4.tcp_fin_timeout = 60調整該值可以減少FIN的確認時間
  • net.ipv4.tcp_window_scaling = 1調整滑動窗口的指數(shù)
  • net.ipv4.tcp_wmem = 4096 16384 4194304調整寫緩沖區(qū)大小
  • net.ipv4.tcp_rmem = 4096 87380 6291456調整讀緩沖區(qū)大小
  • net.ipv4.tcp_congestion_control = cubic調整擁塞控制的算法,可以分析具體網(wǎng)絡場景,通過設置擁塞控制算法提升發(fā)包的效率

5、DPDK

在C1000K問題中,各種軟件、硬件的優(yōu)化很可能都已經(jīng)做到頭了,無論怎么調試參數(shù),提升性能能力已經(jīng)有限,根本的問題是,LINUX網(wǎng)絡協(xié)議棧做了太多太繁重的工作。

于是英特爾公司的網(wǎng)絡通信部門2008年提出DPDK,提供豐富、完整的框架,讓CPU快速實現(xiàn)數(shù)據(jù)平面應用的數(shù)據(jù)包處理,高效完成網(wǎng)絡轉發(fā)等工作,具體細節(jié)大家可以查閱資料,這里我整理了DPDK高性能的大概原理:

跳過內核協(xié)議棧,直接由用戶態(tài)進程通過輪詢的方式,來處理網(wǎng)絡接收,在PPS非常高的場景中,查詢時間比實際工作時間少了很多,絕大部分時間都在處理網(wǎng)絡包,而跳過內核協(xié)議棧后,就省去了繁雜的硬中斷、軟中斷再到 Linux 網(wǎng)絡協(xié)議棧逐層處理的過程,應用程序可以針對應用的實際場景,有針對性地優(yōu)化網(wǎng)絡包的處理邏輯,而不需要關注所有的細節(jié);

通過大頁、CPU 綁定、內存對齊、流水線并發(fā)等多種機制,優(yōu)化網(wǎng)絡包的處理效率;

DPDK網(wǎng)絡圖DPDK網(wǎng)絡圖

第三部分:應用層協(xié)議優(yōu)化

網(wǎng)絡編程中除了設計一個好的底層server和調整內核參數(shù)外,其實應用層的協(xié)議選型和設計也很重要,那本小節(jié)討論一下當前的優(yōu)化方案。

1、HTTP/1.1

從互聯(lián)網(wǎng)發(fā)展到現(xiàn)在,HTTP/1.1一直是最廣泛使用的應用層協(xié)議,主要是使用簡單,方便,但是缺點也很明顯:HTTP頭部使用 ASCII編碼,信息冗余,協(xié)議濫用等,導致對其的優(yōu)化都集中在業(yè)務層。那有哪些優(yōu)化,我這里總結一些:

1.充分利用緩存

  • 客戶端緩存:利用Cache-control,Expires,etags等HTTP/1.1特性,減少重復請求的次數(shù);
  • CDN緩存:靜態(tài)資源優(yōu)先考慮使用CDN服務,本身CDN是邊緣節(jié)點,同時已經(jīng)充分考慮HTTP/1.1一些性能加速策略;
  • 3XX狀態(tài)碼:返回3XX狀態(tài)碼,讓客戶端根據(jù)狀態(tài)碼使用緩存策略

2.合并請求

  • 當多個訪問小文件的請求被合并為一個訪問大文件的請求時,這樣雖然傳輸?shù)目傎Y源體積未變,但減少請求就意味著減少了重復發(fā)送的HTTP頭部,同時也減少了TCP連接的數(shù)量,因而省去了TCP握手和慢啟動過程消耗的時間
  • 由于瀏覽器限制同一個域名下并發(fā)請求數(shù)(如Chrome是6個),所以我們優(yōu)先加載客戶端急需的數(shù)據(jù),其他數(shù)據(jù)可以懶加載

3.使用壓縮算法

  • 利用HTTP的Accept-Encoding頭部字段,讓服務端知道客戶端的壓縮算法然后返回壓縮后的數(shù)據(jù)給客戶端
  • 對于圖片請求,可以考慮使用webp,svg等格式,這些圖片壓縮后的數(shù)據(jù)較小

4.優(yōu)化HTTPS

  • 優(yōu)先使用TLS1.3,減少RTT次數(shù)
  • 明確某些靜態(tài)資源不需要加密,或者可以自己通過預埋加密協(xié)議的,改為HTTP請求,減少握手次數(shù)
  • 使用長連接,緩解每次請求都需要走TLS的握手協(xié)議

2、HTTP/2


現(xiàn)在使用HTTP/2的服務越來越多了,包括gRPC框架的默認協(xié)議就是HTTP/2,對比HTTP/1,HTTP/2性能非常大的提升,可以從上圖看出:

  • 圖1 中HTTP/2使用的流式傳輸,在一條連接上可以有多個數(shù)據(jù)幀,這樣就不需要再像HTTP/1一個請求需要新建一個連接了;
  • 圖2 中HTTP/2使用HTTP Header靜態(tài)和動態(tài)編碼表的方式,這樣每次請求不需要傳遞重復或者通用的一些Header信息,減少了包體的大小;

HTTP/1.1 不支持服務器主動推送消息,因此當客戶端需要獲取通知時,只能通過定時器不斷地拉取消息,而HTTP/2的消息可以主動推送,可以節(jié)省大量帶寬和服務器資源;

3、HTTP/3

HTTP3圖3 HTTP3圖3

上面介紹的HTTP/2雖然已經(jīng)提升很多性能,減少了網(wǎng)絡請求,但是底層使用TCP,避免不了握手,慢啟動和擁塞控制等問題,于是HTTP/3通過使用UDP繞過這些限制來優(yōu)化性能。

  • HTTP/3可以實現(xiàn)0 RTT建立連接,HTTP/2的連接建立需要3 RTT,如果考慮會話復用,即把第一次握手計算出來的對稱密鑰緩存起來,那也需要2 RTT,更進一步的,如果TLS升級到1.3,那么HTTP/2連接需要2 RTT,考慮會話復用需要1 RTT。而HTTP/3首次連接只需要1 RTT, 后面的鏈接只需要0 RTT,其原理和cookie類似,維持conntion id,實現(xiàn)連接遷移。
  • 解決隊頭阻塞,在HTTP/2中雖然是TCP多路復用,但是TCP的包確是順序的,所以如果一個連接上的包在TCP層沒有被確認,這個連接上HTTP/2請求都會被卡住,但是HTTP/3基于UDP就可以不存在這個問題,Packet可以發(fā)送給服務端,服務端根據(jù)需要自己組裝包順序,即使Packet丟了,可以重傳當前Packet即可;

上述都是HTTP/3對比HTTP/2改進的地方,但是從目前看全面使用還是有一些局限,比如:防火墻對UDP包限制,連接遷移特性使情況變得更加復雜等問題,有興趣的可以在客戶端嘗試,但是估計會要踩比較多的坑。

4、RPC協(xié)議

RPC協(xié)議包括很多(如HTTP JSON,XML,ProtoBuf等),框架也比較多(gRPC,Thrift,Brpc,Spring Cloud),隨著微服務的架構被大家熟知,內網(wǎng)的RPC協(xié)議設計往往是網(wǎng)絡框架的重要部分。當然RPC框架底層的架構還是前面介紹的異步,多路復用,多線程等設計,但是上層我們要考慮高性能,更多要解決如下問題:

  • 根據(jù)業(yè)務場景設計不同的協(xié)議,比如采用ProtoBuf能壓縮編碼,采用HTTP JSON協(xié)議方便支持各個客戶端對接;
  • 報文的格式設計,好的報文格式能提升編碼和解碼效率;
  • 降低開發(fā)成本,考慮注冊中心和負載均衡,讓框架和RPC緊密結合,減少業(yè)務層的開發(fā)負擔;
  • 充分考慮分布式場景,比如事務超時,消息冪等等等問題;

之前在業(yè)務中也開發(fā)了一些RPC框架,以上便是我對RPC協(xié)議的簡單總結,不過RPC框架對于性能的考慮可能不是那么重要,更多的是考慮便利性,我們只需要把底層網(wǎng)絡框架設計的足夠高性能,并且選擇與業(yè)務匹配的網(wǎng)絡協(xié)議,這樣基本能滿足大部分業(yè)務需求。

責任編輯:華軒 來源: 周末程序猿
相關推薦

2024-03-18 13:43:20

Linux架構

2023-11-01 10:38:46

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

2023-11-01 11:51:08

Linux性能優(yōu)化

2023-11-01 10:58:31

系統(tǒng)調用高性能網(wǎng)絡編程Linux

2023-11-01 11:40:46

Linux高性能網(wǎng)絡編程工具

2023-11-01 11:27:10

Linux協(xié)程

2023-11-01 11:07:05

Linux高性能網(wǎng)絡編程線程

2023-11-01 11:20:57

2023-11-01 11:13:58

Linux信號處理定時器

2023-11-01 10:43:31

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

2020-11-06 18:51:17

LinuxTCP服務器

2024-10-16 11:03:30

Linux高性能編程

2024-08-06 08:22:18

2024-10-06 14:37:52

2024-09-03 09:15:37

2017-03-29 14:44:20

網(wǎng)絡性能優(yōu)化

2010-12-20 10:56:32

Linux網(wǎng)絡性能優(yōu)化

2025-01-06 00:00:10

2022-02-16 14:10:51

服務器性能優(yōu)化Linux

2021-11-29 11:13:45

服務器網(wǎng)絡性能
點贊
收藏

51CTO技術棧公眾號