成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

服務器性能優化之網絡性能優化

系統 Linux
今天分享一篇后臺服務器性能優化之網絡性能優化,希望大家對Linux網絡有更深的理解。

hi ,大家好,今天分享一篇后臺服務器性能優化之網絡性能優化,希望大家對Linux網絡有更深的理解。

曾幾何時,一切都是那么簡單。網卡很慢,只有一個隊列。當數據包到達時,網卡通過DMA復制數據包并發送中斷,Linux內核收集這些數據包并完成中斷處理。隨著網卡越來越快,基于中斷的模型可能會因大量傳入數據包而導致 IRQ 風暴。這將消耗大部分 CPU 功率并凍結系統。

為了解決這個問題,NAPI(中斷+輪詢)被提議。當內核收到來自網卡的中斷時,它開始輪詢設備并盡快收集隊列中的數據包。NAPI 可以很好地與現在常見的 1 Gbps 網卡配合使用。但是,對于10Gbps、20Gbps甚至40Gbps的網卡,NAPI可能還不夠。如果我們仍然使用一個 CPU 和一個隊列來接收數據包,這些卡將需要更快的 CPU。

幸運的是,現在多核 CPU 很流行,那么為什么不并行處理數據包呢?

RSS:接收端縮放


Receive Side Scaling(RSS)是所述機構具有多個RX / TX隊列過程的數據包。當帶有RSS 的網卡接收到數據包時,它會對數據包應用過濾器并將數據包分發到RX 隊列。過濾器通常是一個哈希函數,可以通過“ethtool -X”進行配置。如果你想在前 3 個隊列中均勻分布流量:

# ethtool -X eth0 equal 3

或者,如果你發現一個特別有用的魔法哈希鍵:  

# ethtool -X eth0 hkey <magic hash key>

對于低延遲網絡,除了過濾器之外,CPU 親和性也很重要。最佳設置是分配一個 CPU 專用于一個隊列。首先通過檢查/proc/interrupt找出IRQ號,然后將CPU位掩碼設置為/proc/irq/<IRQ_NUMBER>/smp_affinity來分配專用CPU。為避免設置被覆蓋,必須禁用守護進程irqbalance。請注意,根據內核文檔,超線程對中斷處理沒有任何好處,因此最好將隊列數與物理 CPU 內核數相匹配。

RPS:接收數據包控制

RSS提供硬件隊列,一個稱為軟件隊列機制Receive Packet Steering (RPS)在Linux內核實現。

當驅動程序接收到數據包時,它會將數據包包裝在套接字緩沖區 ( sk_buff ) 中,其中包含數據包的u32哈希值。散列是所謂的第 4 層散列(l4 散列),它基于源 IP、源端口、目的 IP 和目的端口,由網卡或__skb_set_sw_hash() 計算。由于相同 TCP/UDP 連接(流)的每個數據包共享相同的哈希值,因此使用相同的 CPU 處理它們是合理的。

RPS 的基本思想是根據每個隊列的 rps_map 將同一流的數據包發送到特定的 CPU。這是 rps_map 的結構:映射根據 CPU 位掩碼動態更改為/sys/class/net/<dev>/queues/rx-<n>/rps_cpus。比如我們要讓隊列使用前3個CPU,在8個CPU的系統中,我們先構造位掩碼,0 0 0 0 0 1 1 1,到0x7,然后    

#echo 7 > /sys/class/net /eth0/queues/rx-0/rps_cpus

這將保證從 eth0 中隊列 0 接收的數據包進入 CPU 1~3。驅動程序在 sk_buff 中包裝一個數據包后,它將到達netif_rx_internal()或netif_receive_skb_internal(),然后到達 get_rps_cpu()

struct rps_map {
unsigned int len;
struct rcu_head rcu;
u16 cpus[0];
};

將被調用以將哈希映射到 rps_map 中的條目,即 CPU id。得到CPU id后,enqueue_to_backlog()將sk_buff放到特定的CPU隊列中進行進一步處理。每個 CPU 的隊列在 per-cpu 變量softnet_data 中分配。

使用RPS的好處是可以在 CPU 之間分擔數據包處理的負載。但是,如果RSS 可用,則可能沒有必要,因為網卡已經對每個隊列/CPU 的數據包進行了排序。但是,如果隊列中的CPU數更多,RPS 仍然可以發揮作用。在這種情況下,每個隊列可以與多個 CPU相關聯并在它們之間分發數據包。

RFS: Receive Flow Steering

盡管 RPS 基于流分發數據包,但它沒有考慮用戶空間應用程序。應用程序可能在 CPU A 上運行,而內核將數據包放入 CPU B 的隊列中。由于 CPU A 只能使用自己的緩存,因此 CPU B 中緩存的數據包變得無用。Receive Flow Steering(RFS)進一步延伸為RPS的應用程序。

代替每個隊列的哈希至CPU地圖,RFS維護全局flow-to-CPU的表,rps_sock_flow_table:該掩模用于將散列值映射成所述表的索引。由于表大小將四舍五入到 2 的冪,因此掩碼設置為table_size - 1。

struct rps_sock_flow_table {
u32 mask;
u32 ents[0];
};

并且很容易找到索引:a sk_buff與hash & scok_table->mask。

該條目由 rps_cpu_mask劃分為流 id 和 CPU id。低位用于CPU id,而高位用于流id。當應用程序對套接字進行操作時(inet_recvmsg()、inet_sendmsg()、inet_sendpage()、tcp_splice_read()),將調用sock_rps_record_flow()來更新sock 流表。

當數據包到來時,將調用get_rps_cpu()來決定使用哪個 CPU 隊列。下面是get_rps_cpu()如何決定數據包的 CPU

ident = sock_flow_table->ents[hash & sock_flow_table->mask];
if ((ident ^ hash) & ~rps_cpu_mask)
goto try_rps;
next_cpu = ident & rps_cpu_mask;

使用流表掩碼找到條目的索引,并檢查散列的高位是否與條目匹配。如果是,它會從條目中檢索 CPU id 并為數據包分配該 CPU。如果散列不匹配任何條目,它會回退到使用 RPS 映射。

可以通過rps_sock_flow_entries調整 sock 流表的大小。例如,如果我們要將表大小設置為 32768:

#echo 32768 > /proc/sys/net/core/rps_sock_flow_entries

sock流表雖然提高了應用的局部性,但也帶來了一個問題。當調度器將應用程序遷移到新 CPU 時,舊 CPU 隊列中剩余的數據包變得未完成,應用程序可能會得到亂序的數據包。為了解決這個問題,RFS 使用每個隊列的rps_dev_flow_table來跟蹤未完成的數據包。

下面是該結構rps_dev_flow_table:到襪子流表中,類似的rps_dev_flow_table也使用table_size - 1作為掩模而表的大小也必須被向上舍入到2的冪當流量分組被入隊,last_qtail被更新

struct rps_dev_flow {
u16 cpu;
u16 filter; /* For aRFS */
unsigned int last_qtail;
};
struct rps_dev_flow_table {
unsigned int mask;
struct rcu_head rcu;
struct rps_dev_flow flows[0];
};

到 CPU 隊列的尾部。如果應用程序遷移到新 CPU,則 sock 流表將反映更改,并且get_rps_cpu()將為流設置新 CPU。在設置新 CPU 之前,get_rps_cpu() 會檢查當前隊列的頭部是否已經通過 last_qtail。如果是這樣,這意味著隊列中沒有更多未完成的數據包,并且可以安全地更改 CPU。否則,get_rps_cpu()仍將使用rps_dev_flow->cpu 中記錄的舊 CPU 。

每個隊列的流表(rps_dev_flow_table)的大小可以通過 sysfs 接口進行配置:

/sys/class/net/<dev>/queues/rx-<n>/rps_flow_cnt

建議將rps_flow_cnt設置為 ( rps_sock_flow_entries / N) 而 N 是 RX 隊列的數量(假設流在隊列中均勻分布)。

ARFS:加速接收流量轉向

Accelerated Receive Flow Steering(aRFS)進一步延伸RFS為RX隊列硬件過濾。要啟用 aRFS,它需要具有可編程元組過濾器和驅動程序支持的網卡。要啟用ntuple 過濾器。

# ethtool -K eth0 ntuple on

要使驅動程序支持aRFS,它必須實現ndo_rx_flow_steer以幫助set_rps_cpu()配置硬件過濾器。當get_rps_cpu()決定為流分配一個新 CPU 時,它會調用set_rps_cpu()。set_rps_cpu()首先檢查網卡是否支持 ntuple 過濾器。如果是,它將查詢rx_cpu_rmap為流找到合適的 RX 隊列。

rx_cpu_rmap是驅動維護的特殊映射。該映射用于查找哪個 RX 隊列適合 CPU。它可以是與給定 CPU 直接關聯的隊列,也可以是處理 CPU 在緩存位置最接近的隊列。獲取 RX 隊列索引后,set_rps_cpu()調用ndo_rx_flow_steer()以通知驅動程序為給定的流創建新過濾器。ndo_rx_flow_steer()將返回過濾器 id,過濾器 id 將存儲在每個隊列的流表中。

除了實現ndo_rx_flow_steer() 外,驅動程序還必須調用rps_may_expire_flow() 定期檢查過濾器是否仍然有效并刪除過期的過濾器。

SO_REUSEPORT

linux man文檔中一段文字描述其作用:

The new socket option allows multiple sockets on the same host to bind to the same port, and is intended to improve the performance of multithreaded network server applications running on top of multicore systems.

簡單說,SO_REUSEPORT支持多個進程或者線程綁定到同一端口,用以提高服務器程序的性能。我們想了解為什么這個特性這么火(經常被大廠面試官問到),到底是解決什么問題。

Linux系統上后臺應用程序,為了利用多核的優勢,一般使用以下比較典型的多進程/多線程服務器模型:

  • 單線程listen/accept,多個工作線程接收任務分發,雖CPU的工作負載不再是問題,但會存在:

      1. 單線程listener,在處理高速率海量連接時,一樣會成為瓶頸;

      2. CPU緩存行失效(丟失套接字結構socket structure)現象嚴重;

  • 所有工作線程都accept()在同一個服務器套接字上呢,一樣存在問題:

      1. 多線程訪問server socket鎖競爭嚴重;

      2. 高負載下,線程之間處理不均衡,有時高達3:1不均衡比例;

      3. 導致CPU緩存行跳躍(cache line bouncing);

      4. 在繁忙CPU上存在較大延遲;

上面模型雖然可以做到線程和CPU核綁定,但都會存在以下問題:

  • 單一listener工作線程在高速的連接接入處理時會成為瓶頸
  • 緩存行跳躍
  • 很難做到CPU之間的負載均衡
  • 隨著核數的擴展,性能并沒有隨著提升

SO_REUSEPORT支持多個進程或者線程綁定到同一端口:

  • 允許多個套接字 bind()/listen() 同一個TCP/UDP端口

       1.每一個線程擁有自己的服務器套接字。

       2.在服務器套接字上沒有了鎖的競爭。

  • 內核層面實現負載均衡。
  • 安全層面,監聽同一個端口的套接字只能位于同一個用戶下面。

其核心的實現主要有三點:

  • 擴展socket option,增加
  • SO_REUSEPORT選項,用來設置 reuseport。
  • 修改 bind 系統調用實現,以便支持可以綁定到相同的 IP 和端口。
  • 修改處理新建連接的實現,查找 listener 的時候,能夠支持在監聽相同 IP 和端口的多個 sock 之間均衡選擇

帶來意義

  • CPU之間平衡處理,水平擴展,模型簡單,維護方便了,進程的管理和應用邏輯解耦,進程的管理水平擴展權限下放給程序員/管理員,可以根據實際進行控制進程啟動/關閉,增加了靈活性。這帶來了一個較為微觀的水平擴展思路,線程多少是否合適,狀態是否存在共享,降低單個進程的資源依賴,針對無狀態的服務器架構最為適合。
  • 針對對客戶端而言,表面上感受不到其變動,因為這些工作完全在服務器端進行。
  • 服務器無縫重啟/切換,熱更新,提供新的可能性。我們迭代了一版本,需要部署到線上,為之啟動一個新的進程后,稍后關閉舊版本進程程序,服務一直在運行中不間斷,需要平衡過度。這就像Erlang語言層面所提供的熱更新一樣。

SO_REUSEPORT已知問題

  • SO_REUSEPORT分為兩種模式,即熱備份模式和負載均衡模式,在早期的內核版本中,即便是加入對reuseport選項的支持,也僅僅為熱備份模式,而在3.9內核之后,則全部改為了負載均衡模式,兩種模式沒有共存,雖然我一直都希望它們可以共存。
  • SO_REUSEPORT根據數據包的四元組{src ip, src port, dst ip, dst port}和當前綁定同一個端口的服務器套接字數量進行數據包分發。若服務器套接字數量產生變化,內核會把本該上一個服務器套接字所處理的客戶端連接所發送的數據包(比如三次握手期間的半連接,以及已經完成握手但在隊列中排隊的連接)分發到其它的服務器套接字上面,可能會導致客戶端請求失敗。

如何預防以上已知問題,一般解決思路:

1.使用固定的服務器套接字數量,不要在負載繁忙期間輕易變化。

2.允許多個服務器套接字共享TCP請求表(Tcp request table)。

3.不使用四元組作為Hash值進行選擇本地套接字處理,比如選擇 會話ID或者進程ID,挑選隸屬于同一個CPU的套接字。

4. 使用一致性hash算法。

與其他特性關系

1. SO_REUSEADDR:主要是地址復用

  1.1 讓處于time_wait狀態的socket可以快速復用原ip+port

  1.2 使得0.0.0.0(ipv4通配符地址)與其他地址(127.0.0.1和10.0.0.x)不沖突

  1.3 SO_REUSEADDR 的缺點在于,沒有安全限制,而且無法保證所有連接均勻分配。

2.與RFS/RPS/XPS-mq協作,可以獲得進一步的性能

  2.1.服務器線程綁定到CPUs

  2.2.RPS分發TCP SYN包到對應CPU核上

  2.3.TCP連接被已綁定到CPU上的線程accept()

  2.4. XPS-mq(Transmit Packet Steering for multiqueue),傳輸隊列和CPU綁定,發送   數據

  2.5. RFS/RPS保證同一個連接后續數據包都會被分發到同一個CPU上,網卡接收隊列 已經綁定到CPU,則RFS/RPS則無須設置,需要注意硬件支持與否,目的是數據包的軟硬中斷、接收、處理等在一個CPU核上,并行化處理,盡可能做到資源利用最大化。

SO_REUSEPORT的演進

  • 3.9之前內核,能夠讓多個socket同時綁定完全相同的ip+port,但不能實現負載均衡,實現是熱備。
  • Linux 3.9之后,能夠讓多個socket同時綁定完全相同的ip+port,可以實現負載均衡。
  • Linux4.5版本后,內核引入了reuseport groups,它將綁定到同一個IP和Port,并且設置了SO_REUSEPORT選項的socket組織到一個group內部。目的是加快socket查詢。

總結

Linux網絡堆棧所存在問題

  • TCP處理&多核
  • 一個完整的TCP連接,中斷發生在一個CPU核上,但應用數據處理可能會在另外一個核上
  • 不同CPU核心處理,帶來了鎖競爭和CPU Cache Miss(波動不平衡)
  • 多個進程監聽一個TCP套接字,共享一個listen queue隊列
  • 用于連接管理全局哈希表格,存在資源競爭
  • epoll IO模型多進程的驚群現象
  • Linux VFS的同步損耗嚴重
  • Socket被VFS管理
  • VFS對文件節點Inode和目錄Dentry有同步需求
  • SOCKET只需要在內存中存在即可,非嚴格意義上文件系統,不需要Inode和Dentry
  • 代碼層面略過不必須的常規鎖,但又保持了足夠的兼容性

RSS、RPS、RFS 和 aRFS,這些機制是在 Linux 3.0 之前引入的,SO_REUSEPORT選項在Linux 3.9被引入內核,因此大多數發行版已經包含并啟用了它們。深入了解它們,以便為我們的服務器系統找到最佳性能配置。

性能優化無極限,我們下期再繼續分享!

責任編輯:龐桂玉 來源: Linux學習
相關推薦

2021-11-29 11:13:45

服務器網絡性能

2023-07-04 07:19:17

物理服務器網絡

2011-03-11 15:52:59

LAMP優化

2011-03-11 15:53:02

LAMP優化

2011-03-11 15:52:57

LAMP優化

2022-05-05 09:27:31

Linux服務器優化

2022-09-26 09:19:38

服務器優化

2021-07-29 14:20:34

網絡優化移動互聯網數據存儲

2024-05-08 16:47:24

PostgreSQL數據庫

2011-08-01 10:49:12

服務器

2013-07-23 09:51:32

Tomcat性能優化服務器性能優化

2011-03-11 15:53:00

LAMP優化

2019-08-12 14:46:56

Web服務器性能

2009-01-08 17:43:17

服務器性能磁盤

2018-06-13 10:27:04

服務器性能優化

2010-05-19 10:31:07

IIS服務器

2010-05-19 10:40:59

IIS服務器

2017-03-29 14:44:20

網絡性能優化

2019-07-30 10:51:22

數據庫MySQL固態硬盤

2011-07-29 11:17:28

服務器WAN性能安全
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲欧洲日韩精品 中文字幕 | 日韩中文字幕免费在线观看 | 欧美成人手机视频 | 亚洲精品www | 在线免费观看黄色av | 怡红院免费的全部视频 | 午夜看片网站 | 97精品国产97久久久久久免费 | 亚洲bt 欧美bt 日本bt | 亚洲第一在线视频 | 青娱乐自拍 | 蜜臀av日日欢夜夜爽一区 | 久久男女视频 | 欧美在线综合 | 久久天天综合 | 午夜视频免费在线观看 | 午夜激情在线 | 亚洲第一福利视频 | 亚洲国产午夜 | 国产一区二区 | 亚洲午夜精品 | 一本色道精品久久一区二区三区 | 成人免费久久 | 国产精品黄 | 精品久久久久久18免费网站 | 久久久久久天堂 | 精品无码久久久久久国产 | 免费国产一区 | 久久久久久久成人 | 伊人春色在线 | 国产成人91视频 | www国产成人免费观看视频,深夜成人网 | 成人欧美一区二区三区色青冈 | 精品一区二区三区日本 | 日日夜夜精品免费视频 | 久久国产精品视频 | 亚洲欧美一区二区三区在线 | 国产偷录视频叫床高潮对白 | 免费黄色大片 | 国产美女一区二区 | 成年人黄色小视频 |