提高 Linux上socket 性能的技巧 为 Bandwidth Delay Product 调节 TCP 窗口

运维 系统运维
如何提高Linux上socket的性能,从而加速网络应用程序,你可以通过使用API来开发客户机和服务器之间的应用程序。本文分节介绍了Linux上提高socket性能的技巧。

  本文内容包括Linux下对于 Sockets API 的使用、两个可以提高性能的 socket 选项以及 GNU/Linux 优化。为了能够开发性能卓越的应用程序,请遵循以下技巧:最小化报文传输的延时;最小化系统调用的负载;为 Bandwidth Delay Product 调节 TCP 窗口;动态优化 GNU/Linux TCP/IP 栈。

  为 Bandwidth Delay Product 调节 TCP 窗口:

  TCP 的性能取决于几个方面的因素。两个最重要的因素是链接带宽(link bandwidth)(报文在网络上传输的速率)和 往返时间(round-trip time) 或 RTT(发送报文与接收到另一端的响应之间的延时)。这两个值确定了称为 Bandwidth Delay Product(BDP)的内容。

  给定链接带宽和 RTT 之后,您就可以计算出 BDP 的值了,不过这代表什么意义呢?BDP 给出了一种简单的方法来计算理论上最优的 TCP socket 缓冲区大小(其中保存了排队等待传输和等待应用程序接收的数据)。如果缓冲区太小,那么 TCP 窗口就不能完全打开,这会对性能造成限制。如果缓冲区太大,那么宝贵的内存资源就会造成浪费。如果您设置的缓冲区大小正好合适,那么就可以完全利用可用的带宽。下面我们来看一个例子:

  BDP = link_bandwidth * RTT

  如果应用程序是通过一个 100Mbps 的局域网进行通信,其 RRT 为 50 ms,那么 BDP 就是:

  100MBps * 0.050 sec / 8 = 0.625MB = 625KB

  注意:此处除以 8 是将位转换成通信使用的字节。

  因此,我们可以将 TCP 窗口设置为 BDP 或 1.25MB。但是在 Linux 2.6 上默认的 TCP 窗口大小是 110KB,这会将连接的带宽限制为 2.2MBps,计算方法如下:

  throughput = window_size / RTT

  110KB / 0.050 = 2.2MBps

  如果使用上面计算的窗口大小,我们得到的带宽就是 12.5MBps,计算方法如下:

  625KB / 0.050 = 12.5MBps

  差别的确很大,并且可以为 socket 提供更大的吞吐量。因此现在您就知道如何为您的 socket 计算最优的缓冲区大小了。但是又该如何来改变呢?

  解决方案

  Sockets API 提供了几个 socket 选项,其中两个可以用于修改 socket 的发送和接收缓冲区的大小。清单 2 展示了如何使用 SO_SNDBUF 和 SO_RCVBUF 选项来调整发送和接收缓冲区的大小。

  注意:尽管 socket 缓冲区的大小确定了通告 TCP 窗口的大小,但是 TCP 还在通告窗口内维护了一个拥塞窗口。因此,由于这个拥塞窗口的存在,给定的 socket 可能永远都不会利用最大的通告窗口。

  清单 2. 手动设置发送和接收 socket 缓冲区大小

  int ret, sock, sock_buf_size;

  sock = socket( AF_INET, SOCK_STREAM, 0 );

  sock_buf_size = BDP;

  ret = setsockopt( sock, SOL_SOCKET, SO_SNDBUF,

  (char *)&sock_buf_size, sizeof(sock_buf_size) );

  ret = setsockopt( sock, SOL_SOCKET, SO_RCVBUF,

  (char *)&sock_buf_size, sizeof(sock_buf_size) );

  在 Linux 2.6 内核中,发送缓冲区的大小是由调用用户来定义的,但是接收缓冲区会自动加倍。您可以进行 getsockopt 调用来验证每个缓冲区的大小。

  巨帧(jumbo frame)

  我们还可以考虑将包的大小从 1,500 字节修改为 9,000 字节(称为巨帧)。在本地网络中可以通过设置最大传输单元(Maximum Transmit Unit,MTU)来设置巨帧,这可以极大地提高性能。

  就 window scaling 来说,TCP 最初可以支持最大为 64KB 的窗口(使用 16 位的值来定义窗口的大小)。采用 window scaling(RFC 1323)扩展之后,您就可以使用 32 位的值来表示窗口的大小了。GNU/Linux 中提供的 TCP/IP 栈可以支持这个选项(以及其他一些选项)。

  提示:Linux 内核还包括了自动对这些 socket 缓冲区进行优化的能力(请参阅下面 表 1 中的 tcp_rmem 和 tcp_wmem),不过这些选项会对整个栈造成影响。如果您只需要为一个连接或一类连接调节窗口的大小,那么这种机制也许不能满足您的需要了。

  使用 Sockets API,我们可以开发客户机和服务器应用程序,它们可以在本地网络上进行通信,也可以通过 Internet 在全球范围内进行通信。与其他 API 一样,您可以通过一些方法使用 Sockets API,从而提高 Socket 性能,或者限制 Socket 的性能。

【编辑推荐】

  1. 2.1.3 Socket服务器
  2. TCP Socket之linux实现
  3. Linux操作系统下Socket编程地址结构介绍
  4. 16.5.4 socket编程实例(2)
  5. 16.5.4 socket编程实例(1)

 

责任编辑:zhaolei 来源: 网络转载
相关推荐

2011-01-18 13:42:18

Linuxsocket性能

2011-01-18 11:37:59

Linuxsocket性能

2011-01-18 10:35:02

Linuxsocket性能

2009-12-23 17:07:37

WPF性能

2017-11-06 13:25:25

MySQL数据库技巧

2010-01-21 11:19:44

TCP Socketlinux

2013-05-15 22:30:49

DebianDebian LinuUbuntu

2021-06-10 09:52:33

LinuxTCPAccept

2020-10-10 07:00:16

LinuxSocketTCP

2009-06-17 10:13:03

提高EJB性能

2022-01-09 23:06:39

JavaScript

2023-02-21 14:55:40

React开发技巧

2011-01-13 09:44:19

Linuxsudo技巧

2015-05-28 10:34:16

TCPsocket

2013-01-08 16:05:23

Android开发布局ViewStub

2020-09-23 09:20:58

代码Java字符串

2017-02-05 17:33:59

前端优化Web性能

2021-05-12 09:00:00

WebReactJavaScript

2021-03-18 07:52:42

代码性能技巧开发

2012-03-19 11:41:30

JavaSocket
点赞
收藏

51CTO技术栈公众号