Linux性能优化----网络性能

1.网络的数据转发流程 

    网络的本质跨计算机的进程通信,说是进程间的通信,其实数据交互的流程非常复杂。数据从机器A流向到机器B,首先从机器A的应用层到数据链路层,层层封装,然后数据再到网卡,从网卡发出,经过复杂的网络到达机器B,机器B和A正好是相反的操作,如下示意图:

 这里要说明一下,当数据到达B网卡的时候,会通过DMA的方式(网卡直接从主内存之间读写它们的I/O数据,CPU不参与)把数据写进DMA环形队列,然后网卡通过中断的方式,让网卡驱动程序从DMA环形队列里读走数据,拷贝到sk_buff(内核数据接口)缓冲区,并通过软中断的方式通知内核有新的数据到了。接下来就是网络协议栈的事情了,首先从缓冲区取出数据,层层剥离、校验等操作,最终到达应用层。

2.网络性能指标

  • 带宽:链路的最大传输速率,单位b/s(比特/秒)。
  • 吞吐率:单位时间传输成功的数据量,单位b/s(比特/秒)或B/s(字节/秒)。
  • 延时:一个网络请求包发出后到响应所需要的时间延迟。
  • PPS:Pocket Per Second(包/秒)的简写,网络以包为单位的传输速率。

除了以上的指标还有并发连接数、丢包率、重传率等指标。

3.查看网络工具

  • ifconfig/ip

    ifconfig属于软件包net-tools,ip属于iproute2软件包,ip命令要比ifconfig更丰富。

peter@peter-virtual-machine:~$ ifconfig ens33
ens33     Link encap:以太网  硬件地址 00:0c:29:f0:0a:3c
          inet 地址:192.168.2.203  广播:192.168.2.255  掩码:255.255.255.0
          inet6 地址: fe80::1aa9:207a:f3fb:8837/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  跃点数:1
          接收数据包:3438018 错误:0 丢弃:0 过载:0 帧数:0
          发送数据包:553380 错误:0 丢弃:0 过载:0 载波:0
          碰撞:0 发送队列长度:1000
          接收字节:626319762 (626.3 MB)  发送字节:65276146 (65.2 MB)

peter@peter-virtual-machine:~$ ip -s addr show dev ens33
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:f0:0a:3c brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.203/24 brd 192.168.2.255 scope global dynamic ens33
       valid_lft 58559sec preferred_lft 58559sec
    inet6 fe80::1aa9:207a:f3fb:8837/64 scope link
       valid_lft forever preferred_lft forever
    RX: bytes  packets  errors  dropped overrun mcast
    626323750  3438057  0       0       0       0
    TX: bytes  packets  errors  dropped carrier collsns
    65277074   553388   0       0       0       0

从上可以看到MTU,IP地址,物理地址 ,网络包的收发统计。这里要注意几个状态标识:

ifconfig里的RUNNING和ip的LOWER_UP表示网络是连通的,如果没有发现这个标识,说明网络断开。还有下面几个标识的详细解释:

  1. errors:表示收发数据发生的错误包。
  2. dropped:表示丢弃的数据包。
  3. overrun:表示超限数据包。
  4. carrier:表示发生 carrirer 错误的数据包数,比如双工模式不匹配、物理电缆出现问题等。
  5. collsns:表示碰撞数据包数。
  • netstat/ss
netstat/ss
# -l 表示只显示监听套接字
# -n 表示显示数字地址和端口
# -p 表示进程信息
# -t 表示只显示TCP套接字

Recv-Q:表示套接字缓冲还没有被应用程序取走的字节数(即接收队列长度)。

Send-Q:表示还没有被远端主机确认的字节数(即发送队列长度)。

全栈统计:

netstat -s

  •  sar

查看吞吐率和PPS

 sar -n DEV 1

 

rxpck/s 和 txpck/s 分别是接收和发送的 PPS,单位为包 / 秒。

rxkB/s 和 txkB/s 分别是接收和发送的吞吐量,单位是 KB/ 秒。

 rxcmp/s 和 txcmp/s 分别是接收和发送的压缩数据包数,单位是包 / 秒。

%ifutil 是网络接口的使用率,即半双工模式下为 (rxkB/s+txkB/s)/Bandwidth,而全双工模式下为max(rxkB/s, txkB/s)/Bandwidth

  • ping

连通性和延时性的检测。

peter@peter-virtual-machine:~$ ping -c3 192.168.2.10
PING 192.168.2.10 (192.168.2.10) 56(84) bytes of data.
64 bytes from 192.168.2.10: icmp_seq=1 ttl=255 time=1.55 ms
64 bytes from 192.168.2.10: icmp_seq=2 ttl=255 time=0.780 ms
64 bytes from 192.168.2.10: icmp_seq=3 ttl=255 time=1.30 ms

 -c3表示发送三次ICMP报文就结束。 time表示往返时延。

4.C10K和C10M问题

C10K问题是Dan Kegel 在 1999 年提出。即2GB内存和千兆网卡,单机怎么实现10000并发请求。

这个问题的主要瓶颈在I/O模型,为什么?假设每个连接使用一个线程去管理,那么就需要10000个线程,而线程的所需的资源在于线程的切换、调度占的内存。Linux可以通过下面命令查看线程的栈大小:

ulimit -s

 单位是KB,也就是说默认是8M。

那么可以算一下10000个线程需要10000*8M=80GB,刚内存就不够用,还不算线程的调度所消耗的资源。

所以,必须在同一线程能够处理多个请求,这就是I/O复用技术。

但是,同一个线程处理多个请求出现另外一个问题,那就是一个请求处理完了,下一个请求才能处理,在I/O等待的过程中浪费了大量资源,所以异步处理请求,解决这一问题。

I/O复用的方式有很多种:

  • select/poll

select/poll需要从文件描述符的集合里找出就绪(可读/可写)的fd,由于I/O是异步的,因此一个线程就可以通过轮询的方式管理多个文件描述符的事件。

select和poll的共同点都是每次都需要将文件描述符的集合从用户态拷贝到内核态,由内核态对就绪的文件描述符进行修改,然后把文件描述符的集合拷贝到用户态。这一来一回消耗了不少资源。

select和poll的区别在于:select存储文件描述符集合的数据结构是一个固定大小的相位量,一般最多能对应1024个文件描述符,而poll存储的结构进行了改进,使用动态的数组存储,这样就没有最大描述符数量的限制(当然还会受到系统文件描述符限制)。

  • epoll

epoll是对select/poll很大的改进,首先存储文件描述符的数据结构为红黑树(查询效率高了);不用在用户态和内核态来回拷贝;返回的fd都是就绪的。

C10M的问题不仅需要优化网络I/O模型,还需要各种软件硬件的改进,比如万兆网卡,多队列网卡,中断负载均衡,用户态协议栈、DPDK等。

  • 水平触发和边缘触发

水平触发:只要文件描述符可以非阻塞的执行I/O,就会一直通知

边缘触发:只有文件描述符状态发生变化时,通知一次

5.应用实例

nginx就是在处理高并发的利器,究其原因就是使用epoll的I/O复用技术。nginx的工作模式是一个主进程+多个worker子进程

主进程执行 bind() + listen() 后,创建多个子进程。然后,在每个子进程中,都通过 accept() 或epoll_wait() ,来处理相同的套接字。

这里会有惊群的问题出现,其中accept惊群的问题已经在linux2.6解决,而 epoll 的问题,到了 Linux 4.5 ,才通过EPOLLEXCLUSIVE 解决。

为了避免惊群问题, Nginx 在每个 worker 进程中,都增加一个了全局锁(accept_mutex)。这些 worker 进程需要首先竞争到锁,只有竞争到锁的进程,才会加入到 epoll 中,这样就确保只有一个 worker子进程被唤醒。

还有一种方式是,开启 SO_REUSEPORT 选项。由内核来负责负载均衡,内核能确保同时只能由一个进程被唤醒,从而遏制了惊群问题的出现。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值