设为首页 - 加入收藏 焦点技术网
热搜:java
当前位置:首页 >

[转载]使用sendfile()让数据传输得到最优化,TCP_CORK、TCP_DEFER_ACCEPT和TCP_QUICKACK优化网络

2008-08-27 10:13:00.0 c/c++ tcp 优化 服务器 网络 存储 freebsd  
导读: 当今国互联网的飞速发展让人们获益匪浅,同时人们对于互联网的期望值也变得越来越高。这就形成了一个矛盾,虽然互联网的发展已经是相当迅猛的了,但是人们还是期望从服务器到客户终端的文件传输的速度能够比现在再快一些,这种要求(当然是合理的要求)好像从来也满足不了。在向人们询问“一种什么样的速度对于数据传输来说才是最理想的”问题时,几乎每一次你都会得到一种不同的答案:有的人认为数据传输的速率越快越好,有的人...。。。
 
当今国互联网的飞速发展让人们获益匪浅,同时人们对于互联网
的期望值也变得越来越高。这就形成了一个矛盾,虽然互联网的
发展已经是相当迅猛的了,但是人们还是期望从服务器到客户终
端的文件传输的速度能够比现在再快一些,这种要求(当然是合
理的要求)好像从来也满足不了。在向人们询问“一种什么样的
速度对于数据传输来说才是最理想的”问题时,几乎每一次你都
会得到一种不同的答案:有的人认为数据传输的速率越快越好,
有的人则认为数据传输的速率只要在能够容忍的限度之内就可以
了,而另一人则认为一种数据传输时不会有数据损失的最快速率
才是他们真正需要的,当然,这里还有许多其它的回答,我就不
一一赘述了。
在现实中,对于这个有关数据传输的问题是没有一个统一的答案
的。绝大多数的人在评价数据传输的快慢时,还是会使用“每秒
钟传输的兆字节数”来作为一种衡量的标准。但是,数据传输快
慢的真正衡量标准却是CPU对于每一个传输的兆字节所花费占用
的时间。对于实时应用软件,尤其是那些传输视频或者音频数据
流的软件,最不想出现的一种状况就是所谓的“延迟”。CPU执
行任务的时候如果没有任何的效率,那么,要实现对协议层
(protocol-level)的负载平衡(load balancing)以及将主机
的IP名私人化的支持(一种叫做Virtuozzo的操作系统虚拟化技
术)都是不太可能的。一个加装了Virtuozzo的主机内能够装得
下数以千计的网络站点,所以,尽可能的减少用来处理数据传输
占据的CPU时间是非常重要的。
Sendfile()是一种崭新的操作系统核心,这种新核心能够帮助人
们解决上边所描述的那些问题。而且,这种新内核对于UNIX,
Linux, Solaris 8操作系统来说都是适用的。从技术角度来看,
sendfile()是磁盘和传输控制协议(TCP)之间的一种系统呼叫
,但是sendfile()还能够用来在两个文件夹之间移动数据。在各
种不同的操作系统上实现sendfile()都会有所不同,当然这种不
同只是极为细微的差别。通常来说,我们会假定所使用的操作系
统是Linux核心2.4版本。
系统呼叫的原型有如下几种:
ssize_t sendfile(int out_fd, int in_fd, off_t *offset,
size_t count)
in_fd是一种用来读文件的文件描述符。
out_fd是一种用来写文件的描述符。
Offset是一种指向被输入文件变量位置的指针,sendfile()将会
从它所指向的位置开始数据的读取。
Count表示的是两个文件描述符之间数据拷贝的字节数。
sendfile()的威力在于,它为大家提供了一种访问当前不断膨胀
的Linux网络堆栈的机制。这种机制叫做“零拷贝(zero-copy)”
,这种机制可以把“传输控制协议(TCP)”框架直接的从主机存
储器中传送到网卡的缓存块(network card buffers)中去。为
了更好的理解“零拷贝(zero-copy)”以及sendfile(),让我
们回忆一下以前我们在传送文件时所需要执行的那些步骤。首先
,一块在用户机器存储器内用于数据缓冲的位置先被确定了下来
。然后,我们必须使用read()这条系统呼叫来把数据从文件中拷
贝到前边已经准备好的那个缓冲区中去。(在通常的情况下,这
个操做会把数据从磁盘上拷贝到操作系统的高速缓冲存储器中去
,然后才会把数据从高速缓冲存储器中拷贝至用户空间中去,这
种过程就是所谓的“上下文切换”。)在完成了上述的那些步骤
之后,我们得使用write()系统呼叫来将缓冲区中的内容发送到
网络上去,程序段如下所示:
intout_fd, intin_fd;
char buffer[BUFLEN];

/* unsubstantial code skipped for clarity */

read(in_fd, buffer, BUFLEN); /* syscall, make context
switch */
write(out_fd, buffer, BUFLEN); /* syscall, make context
switch */
操作系统核心不得不把所有的数据至少都拷贝两次:先是从核心
空间到用户空间的拷贝,然后还得再从用户空间拷贝回核心空间
。每一次操做都需要上下文切换(context-switch)的这个步骤
,其中包含了许多复杂的高度占用CPU的操作。系统自带的工具
vmstat能够用来在绝大多数UNIX以及与其类似的操作系统上显示
当前的“上下文切换(context-switch)”速率。请看叫做“CS
”的那一栏,有相当一部分的上下文切换是发生在取样期间的。
用不同类型的方式进行装载可以让使用者清楚的看到使用这些参
数进行装载时的不同效果。
关于切换过程的一些具体细节
让我们向着有关上下文切换过程的更深层次挖掘,这样做能够让
我们更好的理解有关切换的一些问题。这里有许多种有关从用户
空间呼叫系统的操作的方法。举个例子来说,将虚拟内存页面从
用户空间中切换到核心,然后再切换回去的这种操作是必不可少
的。这种操作过程需要的系统花销是相当大的(尤其是在CPU周
期的占用方面)。这种操做是通过使用叫做全局描述符台面
(Global Descriptor Table)以及局部描述符台面(Local
Descriptor Table)的存储器控制台来实现的。另外的一种结构
被称之为TSS (Task Status Segment任务状态段)的工具也需要
大家给予足够的重视。
此外,还有一些隐藏的非常“昂贵”的操作没有被上下文切换程
序呼叫出来。我们能够通过虚拟内存需要虚拟物理地址翻译操作
的支持才能实现的例子来说明这些隐藏操作的存在。这种翻译所
需要的数据也是存储于存储器中的,所以,CPU每一次对这些数
据存储位置的请求都需要对主存储器进行一次或多次的访问(这
是为了读取翻译台入口),这是除了需要获取的那些数据外还要
进行的一些操作。现在的CPU通常都包含了一个翻译缓存,其缩
写为TLB。TLB是作为页面入口来工作的,其中存储了最近访问过
的对象。(这是对TLB最为简单的解释,其具体的解释应为:OLE
库文件,其中存放了OLE自动化对象的数据类型、模块和接口定
义,自动化服务器通过TLB文件就能了解自动化对象的使用方法
。)TLB高速缓冲存储器拥有巨大的潜在花费,其中包括了几个
存储器的访问操作以及页面错误处理器的实行操作。在拷贝大量
数据的时候,会对TLB高速缓冲存储器产生大量的消耗。在这个
时候,TLB高速缓冲存储器里边会被要拷贝的页面数据占据的容
不下任何别的其它数据。
在有了sendfile()零拷贝(zero-copy)之后,如果可能的话,
通过使用直接存储器访问(Direct Memory Access)的硬件设备
,数据从磁盘读取到操作系统高速缓冲存储器中会变得非常之迅
速。而TLB高速缓冲存储器则被完整无缺的放在那里,没有充斥
任何有关数据传输的文件。应用软件在使用sendfile()
primitive的时候会有很高的性能表现,这是因为系统呼叫没有
直接的指向存储器,因此,就提高了传输数据的性能。通常来说
,要被传输的数据都是从系统缓冲存储器中直接读取的,其间并
没有进行上下文切换的操作,也没有垃圾数据占据高速缓冲存储
器。因此,在服务器应用程序中使用sendfile()能够显著的减少
对CPU的占用。
在我们的这个例子中取代带有mmap() 的read()不会让事情有什
么显著的变化。然而,mmap系统呼叫的请求是从文件中(或者从
其它的一些对象中)生成一些连接信息,这些都是从在虚拟内存
中的文件描述符中指定的。试图从虚拟内存中读取数据会产生一
些磁盘操作。因为系统会把含有映射内容的存储器直接的写入而
不会调用read()以及缓存定位,所以我们能够消除磁盘读取操作
。然而,这种操作会导致TLB高速缓冲存储器的过热,所以CPU在
装载每个字节的传输时的负荷会稍微加大一些。
零拷贝的方法以及应用软件的开发
只要有可能,在任何时候,对性能要求非常苛刻的客户服务器应
用程序的开发都会使用到零拷贝方法(The zero-copy approach
)。设想一下,当我们需要在一个单独的服务器上运行超过一千
个分散的拥有私人IP地址的Apache网络服务器时,就可以使用到
Virtuozzo技术了。为了达到这个目的,我们每一秒钟都不得不
在传输控制协议的层面上处理数以千计的请求来列出客户的请求
并且把主机名页开列出来。如果没有经过最优化的处理和零拷贝
(zero-copy)支持的话,这对于处理器来说将是一项繁重而且
复杂的任务,甚至都超过了网络对它的负荷。零拷贝sendfile()
的实现是基于9K-http-requests-per-second速率的,甚至在速
度相对较慢的Pentium II350 MHz的处理器上也是一样。
然而,零拷贝(zero-copy) sendfile()并不是能解决所有问题
的“万能药”。部分的,减少网络操作的数量,sendfile()系统
呼叫应该和TCP/IP中的TCP_CORK选项在一起共同的使用。在我们
以后的文章中将会讨论应用软件从此选项中获得的好处,以及讨
论其它的一些相关问题。
下面再附上两篇文章供参考。。。
促进高效数据传输的TCP/IP选项
作者: ZDNET CHINA 特稿
2002-07-22 04:11 PM
在前一篇文章里,我们讨论了以下问题:如何采用sendfile()系
统函数降低从磁盘到网络的数据传输负载。接下来我们继续讨论
涉及网络连接控制的另一问题,同时希望通过对这一问题的讨论
能有助于在实际环境下把sendfile()的功能最大化,这就是如何
设置TCP/IP选项来控制套接字的行为。
TCP/IP数据传输


TCP/IP网络的数据传输通常建立在数据块的基础之上。从程序员
的观点来看,发送数据意味着发出(或者提交)一系列“发送数
据块”的请求。在系统级,发送单个数据块可以通过调用系统函
数write() 或者sendfile() 来完成。在网络级可以看到更多的
数据块,通常把它们叫做帧,帧再被包装上一定字节长度的报头
然后通过线路在网络上传输。帧及其报头内部的信息是由若干协
议层定义的,从OSI参考模型的物理层到应用层都可能会牵扯到
因为在网络连接中是由程序员来选择最适当的应用协议,所以网
络包的长度和顺序都在程序员的控制之下。同样的,程序员还必
须选择这个协议在软件中得以实现的方式。TCP/IP协议自身已经
有了多种可互操作的实现,所以在双方通信时,每一方都有它自
身的低级行为,这也是程序员所应该知道的情况。
通常情况下,程序员不必关心操作系统和网络协议栈发送和接收
网络数据的方法。系统内置算法定义了低级的数据组织和传输方
式;然而,影响这些算法的行为以及对网络连接施加更大强度控
制能力的方法也是有的。例如,如果某个应用协议使用了超时和
重发机制,程序员就可以采取一定措施设定或者获取超时参数。
他或她还可能需要增加发送和接收缓冲区的大小来保证网络上的
信息流动不会中断。改变TCP/IP协议栈行为的一般的方法是采用
所谓的TCP/IP选项。下面就让我们来看一看你该如何使用这些选
项来优化数据传输。
TCP/IP选项
有好几种选项都能改变TCP/IP协议栈的行为。使用这些选择能对
在同一计算机上运行的其他应用程序产生不利的影响,因此普通
用户通常是不能使用这些选项的(除了root用户以外)。我们在
这里主要讨论能改变单个连接操作(用TCP/IP的术语来说就是套
接字)的选项。
ioctl风格的getsockopt()和setsockopt()系统函数都提供了控
制套接字行为的方式。比方说,为了在Linux上设置TCP_NODELAY
选项,你可以如下编写代码:
intfd, on = 1;
/* 此处是创建套接字等操作,出于篇幅的考虑省略*/

setsockopt (fd, SOL_TCP, TCP_NODELAY, &on, sizeof (on));
尽管有许多TCP选项可供程序员操作,而我们却最关注如何处置
其中的两个选项,它们是TCP_NODELAY 和 TCP_CORK,这两个选
项都对网络连接的行为具有重要的作用。许多UNIX系统都实现了
TCP_NODELAY选项,但是,TCP_CORK则是Linux系统所独有的而且
相对较新;它首先在内核版本2.4上得以实现。此外,其他UNIX
系统版本也有功能类似的选项,值得注意的是,在某种由BSD派
生的系统上的TCP_NOPUSH选项其实就是TCP_CORK的一部分具体实
现。
TCP_NODELAY和TCP_CORK基本上控制了包的“Nagle化”,Nagle
化在这里的含义是采用Nagle算法把较小的包组装为更大的帧。
John Nagle是Nagle算法的发明人,后者就是用他的名字来命名
的,他在1984年首次用这种方法来尝试解决福特汽车公司的网络
拥塞问题(欲了解详情请参看IETF RFC 896)。他解决的问题就
是所谓的silly window syndrome ,中文称“愚蠢窗口症候群”
,具体含义是,因为普遍终端应用程序每产生一次击键操作就会
发送一个包,而典型情况下一个包会拥有一个字节的数据载荷以
及40个字节长的包头,于是产生4000%的过载,很轻易地就能令
网络发生拥塞,。 Nagle化后来成了一种标准并且立即在因特网
上得以实现。它现在已经成为缺省配置了,但在我们看来,有些
场合下把这一选项关掉也是合乎需要的。
现在让我们假设某个应用程序发出了一个请求,希望发送小块数
据。我们可以选择立即发送数据或者等待产生更多的数据然后再
一次发送两种策略。如果我们马上发送数据,那么交互性的以及
客户/服务器型的应用程序将极大地受益。例如,当我们正在发
送一个较短的请求并且等候较大的响应时,相关过载与传输的数
据总量相比就会比较低,而且,如果请求立即发出那么响应时间
也会快一些。以上操作可以通过设置套接字的TCP_NODELAY选项
来完成,这样就禁用了Nagle算法。
另外一种情况则需要我们等到数据量达到最大时才通过网络一次
发送全部数据,这种数据传输方式有益于大量数据的通信性能,
典型的应用就是文件服务器。应用Nagle算法在这种情况下就会
产生问题。但是,如果你正在发送大量数据,你可以设置
TCP_CORK选项禁用Nagle化,其方式正好同TCP_NODELAY相反
(TCP_CORK 和 TCP_NODELAY 是互相排斥的)。下面就让我们仔
细分析下其工作原理。
假设应用程序使用sendfile()函数来转移大量数据。应用协议通
常要求发送某些信息来预先解释数据,这些信息其实就是报头内
容。典型情况下报头很小,而且套接字上设置了TCP_NODELAY。
有报头的包将被立即传输,在某些情况下(取决于内部的包计数
器),因为这个包成功地被对方收到后需要请求对方确认。这样
,大量数据的传输就会被推迟而且产生了不必要的网络流量交换
但是,如果我们在套接字上设置了TCP_CORK(可以比喻为在管道
上插入“塞子”)选项,具有报头的包就会填补大量的数据,所
有的数据都根据大小自动地通过包传输出去。当数据传输完成时
,最好取消TCP_CORK 选项设置给连接“拔去塞子”以便任一部
分的帧都能发送出去。这同“塞住”网络连接同等重要。
总而言之,如果你肯定能一起发送多个数据集合(例如HTTP响应
的头和正文),那么我们建议你设置TCP_CORK选项,这样在这些
数据之间不存在延迟。能极大地有益于WWW、FTP以及文件服务器
的性能,同时也简化了你的工作。示例代码如下:
intfd, on = 1;

/* 此处是创建套接字等操作,出于篇幅的考虑省略*/

setsockopt (fd, SOL_TCP, TCP_CORK, &on, sizeof (on)); /*
cork */
write (fd, …);
fprintf (fd, …);
sendfile (fd, …);
write (fd, …);
sendfile (fd, …);

on = 0;
setsockopt (fd, SOL_TCP, TCP_CORK, &on, sizeof (on)); /*
拔去塞子 */
不幸的是,许多常用的程序并没有考虑到以上问题。例如,Eric
Allman编写的sendmail就没有对其套接字设置任何选项。
Apache HTTPD是因特网上最流行的Web服务器,它的所有套接字
就都设置了TCP_NODELAY选项,而且其性能也深受大多数用户的
满意。这是为什么呢?答案就在于实现的差别之上。由BSD衍生
的TCP/IP协议栈(值得注意的是FreeBSD)在这种状况下的操作
就不同。当在TCP_NODELAY 模式下提交大量小数据块传输时,大
量信息将按照一次write()函数调用发送一块数据的方式发送出
去。然而,因为负责请求交付确认的记数器是面向字节而非面向
包(在Linux上)的,所以引入延迟的概率就降低了很多。结果
仅仅和全部数据的大小有关系。而 Linux 在第一包到达之后就
要求确认,FreeBSD则在进行如此操作之前会等待好几百个包。
在Linux系统上,TCP_NODELAY的效果同习惯于BSD TCP/IP协议栈
的开发者所期望的效果有很大不同,而且在Linux上的Apache性
能表现也会更差些。其他在Linux上频繁采用TCP_NODELAY的应用
程序也有同样的问题。
相得益彰
你的数据传输并不需要总是准确地遵守某一选项或者其它选择。
在那种情况下,你可能想要采取更为灵活的措施来控制网络连接
:在发送一系列当作单一消息的数据之前设置TCP_CORK,而且在
发送应立即发出的短消息之前设置TCP_NODELAY。
把零拷贝和sendfile() 系统函数结合起来(前文有述)可以显
著地提升系统整体效率并且降低CPU负载。我们采用这一技术为
Swsoft’s Virtuozzo公司开发了基于名称的主机托管子系统,
实践经验表明,该技术可以在装备350-MHz Pentium II CPU的PC
上实现每秒9000个HTTP请求,这一成绩在以前几乎是不可能实现
的。性能上的提高显而易见。

利用TCP/IP选项优化数据传输(第2部分)
作者: BUILDER.COM
2002-07-22 04:15 PM
上回,我们对TCP_CORK选项如何减少网络传输包的数量做了一番
原理性的解释。减少网络流量当然是非常重要的优化举措之一,
不过这种手段也仅仅是实现高性能网络数据传输领域的一个方面
。其他TCP选项也可能显著提供传输性能同时在某些条件下减少
服务器的响应时间延迟。下面就让我们来了解一些此类选项。
TCP_DEFER_ACCEPT


我们首先考虑的第1个选项是TCP_DEFER_ACCEPT(这是Linux系统
上的叫法,其他一些操作系统上也有同样的选项但使用不同的名
字)。为了理解TCP_DEFER_ACCEPT选项的具体思想,我们有必要
大致阐述一下典型的HTTP客户/服务器交互过程。请回想下TCP是
如何与传输数据的目标建立连接的。在网络上,在分离的单元之
间传输的信息称为IP包(或IP 数据报)。一个包总有一个携带
服务信息的包头,包头用于内部协议的处理,并且它也可以携带
数据负载。服务信息的典型例子就是一套所谓的标志,它把包标
记代表TCP/IP协议栈内的特殊含义,例如收到包的成功确认等等
。通常,在经过“标记”的包里携带负载是完全可能的,但有时
,内部逻辑迫使TCP/IP协议栈发出只有包头的IP包。这些包经常
会引发讨厌的网络延迟而且还增加了系统的负载,结果导致网络
性能在整体上降低。
现在服务器创建了一个套接字同时等待连接。TCP/IP式的连接过
程就是所谓“3次握手”。首先,客户程序发送一个设置SYN标志
而且不带数据负载的TCP包(一个SYN包)。服务器则以发出带
SYN/ACK标志的数据包(一个SYN/ACK包)作为刚才收到包的确认
响应。客户随后发送一个ACK包确认收到了第2个包从而结束连接
过程。在收到客户发来的这个SYN/ACK包之后,服务器会唤醒一
个接收进程等待数据到达。当3次握手完成后,客户程序即开始
把“有用的”的数据发送给服务器。通常,一个HTTP请求的量是
很小的而且完全可以装到一个包里。但是,在以上的情况下,至
少有4个包将用来进行双向传输,这样就增加了可观的延迟时间
。此外,你还得注意到,在“有用的”数据被发送之前,接收方
已经开始在等待信息了。
为了减轻这些问题所带来的影响,Linux(以及其他的一些操作
系统)在其TCP实现中包括了TCP_DEFER_ACCEPT选项。它们设置
在侦听套接字的服务器方,该选项命令内核不等待最后的ACK包
而且在第1个真正有数据的包到达才初始化侦听进程。在发送
SYN/ACK包之后,服务器就会等待客户程序发送含数据的IP包。
现在,只需要在网络上传送3个包了,而且还显著降低了连接建
立的延迟,对HTTP通信而言尤其如此。
这一选项在好些操作系统上都有相应的对等物。例如,在
FreeBSD上,同样的行为可以用以下代码实现:
/* 为明晰起见,此处略去无关代码 */
struct accept_filter_arg af = { "dataready", "" };
setsockopt(s, SOL_SOCKET, SO_ACCEPTFILTER, &af, sizeof
(af));
这个特征在FreeBSD上叫做“接受过滤器”,而且具有多种用法
。不过,在几乎所有的情况下其效果与TCP_DEFER_ACCEPT是一样
的:服务器不等待最后的ACK包而仅仅等待携带数据负载的包。
要了解该选项及其对高性能Web服务器的重要意义的更多信息请
参考Apache文档上的有关内容。
就HTTP客户/服务器交互而言,有可能需要改变客户程序的行为
。客户程序为什么要发送这种“无用的”ACK包呢?这是因为,
TCP协议栈无法知道ACK包的状态。如果采用FTP而非HTTP,那么
客户程序直到接收了FTP服务器提示的数据包之后才发送数据。
在这种情况下,延迟的ACK将导致客户/服务器交互出现延迟。为
了确定ACK是否必要,客户程序必须知道应用程序协议及其当前
状态。这样,修改客户行为就成为必要了。
对Linux客户程序来说,我们还可以采用另一个选项,它也被叫
做TCP_DEFER_ACCEPT。我们知道,套接字分成两种类型,侦听套
接字和连接套接字,所以它们也各自具有相应的TCP选项集合。
因此,经常同时采用的这两类选项却具有同样的名字也是完全可
能的。在连接套接字上设置该选项以后,客户在收到一个
SYN/ACK包之后就不再发送ACK包,而是等待用户程序的下一个发
送数据请求;因此,服务器发送的包也就相应减少了。
TCP_QUICKACK
阻止因发送无用包而引发延迟的另一个方法是使用TCP_QUICKACK
选项。这一选项与 TCP_DEFER_ACCEPT不同,它不但能用作管理
连接建立过程而且在正常数据传输过程期间也可以使用。另外,
它能在客户/服务器连接的任何一方设置。如果知道数据不久即
将发送,那么推迟ACK包的发送就会派上用场,而且最好在那个
携带数据的数据包上设置ACK 标志以便把网络负载减到最小。当
发送方肯定数据将被立即发送(多个包)时,TCP_QUICKACK选项
可以设置为0。对处于“连接”状态下的套接字该选项的缺省值
是1,首次使用以后内核将把该选项立即复位为1(这是个一次性
的选项)。
在某些情形下,发出ACK包则非常有用。ACK包将确认数据块的接
收,而且,当下一块被处理时不至于引入延迟。这种数据传输模
式对交互过程是相当典型的,因为此类情况下用户的输入时刻无
法预测。在Linux系统上这就是缺省的套接字行为。
在上述情况下,客户程序在向服务器发送HTTP请求,而预先就知
道请求包很短所以在连接建立之后就应该立即发送,这可谓HTTP
的典型工作方式。既然没有必要发送一个纯粹的ACK包,所以设
置TCP_QUICKACK为0以提高性能是完全可能的。在服务器方,这
两种选项都只能在侦听套接字上设置一次。所有的套接字,也就
是被接受呼叫间接创建的套接字则会继承原有套接字的所有选项
通过TCP_CORK、TCP_DEFER_ACCEPT和TCP_QUICKACK选项的组合,
参与每一HTTP交互的数据包数量将被降低到最小的可接受水平(
根据TCP协议的要求和安全方面的考虑)。结果不仅是获得更快
的数据传输和请求处理速度而且还使客户/服务器双向延迟实现
了最小化。

小结
网络程序的性能优化显然是一项复杂的任务。优化技术包括:尽
可能使用零拷贝、用TCP_CORK及其等价选项组装适当的数据包、
把传输数据包的数量最小化以及延迟优化等。为了提升网络、系
统的性能和可伸缩性,有必要在程序代码中联合一致地采用以上
各种可用方法。当然,清楚了解TCP/IP协议栈和操作系统的内部
工作原理也是必要的。

(编辑: netpet)

网友评论
相关文章