2021年欧冠哪些平台直播

admin · 2008-11-01

  

  

本文转载自微信民众号「极客新生」,作家极客新生。转载本文请闭系极客新生民众号。

  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-Xeth0equal3

 

  或许,假如你出现一个尤其有效的妖术哈希键:

  

#ethtool-Xeth0hkey<magichashkey>

 

  对付低耽误收集,除了过滤器以外,CPU 亲和性也很紧要。最佳扶植是分拨一个 CPU 公用于一个行列。起首经由过程检讨/proc/interrupt寻找IRQ号,而后将CPU位掩码扶植为/proc/irq//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//queues/rx-/rps_cpus。好比咱们要让行列操纵前3个CPU,正在8个CPU的体例中,咱们先构制位掩码,0 0 0 0 0 1 1 1,到0x7,而后

  

#echo7>/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()

  

structrps_map{unsignedintlen;structrcu_headrcu;u16cpus[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。

  

structrps_sock_flow_table{u32mask;u32ents[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)gototry_rps;next_cpu=ident&rps_cpu_mask;

 

  操纵流外掩码找到条款的索引,并检讨散列的高位能否与条款成婚。假如是,它会从条款中检索 CPU id 并为数据包分拨该 CPU。假如散列不行婚任何条款,它会回退到操纵 RPS 照射。

  能够经由过程rps_sock_flow_entries调解 sock 流外的巨细。比如,假如咱们要将外巨细扶植为 32768:

  

#echo32768>/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被更新

  

structrps_dev_flow{u16cpu;u16filter;/*ForaRFS*/unsignedintlast_qtail;};structrps_dev_flow_table{unsignedintmask;structrcu_headrcu;structrps_dev_flowflows[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-Keth0ntupleon

 

  要使驱动次第支撑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被引入内核,因而公共半刊行版曾经包括并启用了它们。深远清晰它们,以便为咱们的供职器体例找到最佳机能设置装备摆设。

  机能优化无极限,咱们下期再络续分享!

   扩大与参考

  https://garycplin.blogspot.com/2017/06/linux-network-scaling-receives-packets.html?m=1

  https://jamal-jiang.github.io/2017/02/03/TCP-SO-REUSEPORT/

  http://www.blogjava.net/yongboy/archive/2015/02/05/422760.html

文章推荐:

nba2k18传奇版

cba2k巨星时刻

nba2k11没声音

大赢家篮球比分