网络安全 频道

通用TCP/IP协议栈与专用协议栈

  通用TCP协议栈:指的就是通用操作系统(linux或者windows或者其它的操作系统)中使用的TCP协议栈。通常这些协议栈都具有统一的实现标准和规范,它们适用于任何场景之下,可以随意兼容软件,一般也都能够很好的兼容硬件。一般情况下它们的实现与硬件软件架构关系不大。

  专用协议栈一般是指以通用TCP协议栈为基础,符合TCP协议规范,但是用来处理专门场景的协议栈。它们也遵循协议规范,但是它们仅适用于某些特殊场景,它们的实现都会或多或少的依赖于硬件环境和软件架构。

  专用协议栈与通用协议栈有哪些区别呢?我们可以从以下六个方面对专用协议栈和通用TCP协议栈进行一些对比:

  1、系统实现规模

  对于通用TCP协议栈而言,由于它无法预测上层的应用程序是什么,因此它无法估计出它实际需要支持的协议以及一些具体的应用层接口,所以通用TCP协议栈需要实现的是一个面向所有应用的功能全集。

  举个例子来说吧,对于linux内核而言,它的协议栈需要支持的是一个较为完整的协议族,其中包括人们熟知的TCP协议,UDP协议,还包含一些进程通信的域套接字等。也就是说对于通用协议栈来说,为了能够支持这些场景,它必须为上层应用提供足够多的接口,至少需要接口支持足够多的应用场景,这个规模是非常大的。

  而对于专用协议栈而言,由于它可以预测上层面对的应用是些什么,因此它可以很方便的估计出它需要处理的具体接口,相当于它只是通用TCP协议栈的一个功能子集。

  同样举个例子,对于网络设备而言,它通常不需要处理类似进程通信的工作,因此根本无需对这些东西进行实现,而且很多设备只需要处理某一种协议,因此只需要实现一个子集就足够用了。

  2、逻辑复杂程度

  通用TCP协议栈由于实现规模巨大,带来的效果就是处理逻辑复杂。举个最简单的例子:创建一个socket通用协议栈光是用来判断协议族的类型就有27个,地址类型也有27个,而对于专有协议栈来说,协议类型最多就两个,大多数应该支持一个就足够了,而地址类型基本上也就是一到两个。这还仅只是最简单最基础的一个功能,其他的功能我想已经不言而喻了。

  3、系统运行效率

  系统运行效率分为时间上的和空间上的,其中空间上的效率很明显,专有协议栈可以实现到仅需要几K的内存就可以运行协议栈全部功能,这对于通用TCP协议栈是不可想象的。

  对于一些高性能的网络设备而言,它们可能更加关注系统运行的时间效率,通用协议栈在处理上除去它的逻辑复杂性带来的开销以外至少还有三个地方是无法和专用协议栈相比的。

  一个是系统调用,由于通用协议栈一般是和操作系统在一起的,通常需要运行在内核空间,它要想和用户空间进行交互就必须通过系统调用来完成。有系统调用就必须有切换,系统从用户空间切换至内核空间或者反之都是需要一定的系统开销的。系统调用还会引起进程休眠和唤醒,这些性能损耗对于高性能网络设备来说几乎是不可容忍的。

  Nginx是一个常用的linux代理软件,很多对负载要求不高的用户,用服务器平台+Nginx实现简单的负载均衡。那么我们来看看采用通用协议栈的Nginx与采用专用协议栈的太一应用交付产品在TCP新建的性能上有多大差异。

通用TCP/IP协议栈与专用协议栈

  我们使用BPS测试仪作为客户端和服务器群,模拟上面的拓扑,中间使用Nginx作为负载均衡设备做了一次测试,测试每秒新建连接数。

通用TCP/IP协议栈与专用协议栈

  从硬件配置上来看,采用Nginx的服务器与T-FORCE3600配置相差不大,但是新建性能差异已经很明显了,使用专用协议栈的每秒新建数每个核大约是通用协议栈的十倍,这中间由于系统调用的性能损耗应该是其中重要的因素。

  再一个则是数据的传递,通用协议栈从接收到报文到把数据传递给用户程序的过程中不可避免的要进行四次内存拷贝。第一次是报文从网络驱动器收到内核空间;第二次是从内核空间到协议栈;第三次是从协议栈到socket;第四次是用户取走数据。这些内存拷贝都是需要消耗性能的。

  我们在开发中具体对协议栈实现中的拷贝产生的性能损耗做过评估。同样是使用每秒新建连接的模型针对协议栈中存在的三次拷贝做了一组测试:

通用TCP/IP协议栈与专用协议栈

  可以很明显的看出,在硬件配置相同的情况下,协议栈内部的拷贝每增加一次就几乎会带来大约10%的性能损失,也就是说专有协议栈和通用协议栈相比,通用协议栈单就内存拷贝一项就至少比专有协议栈低30%,考虑到内核的内存管理算法相比我们实现的内存管理算法要复杂,很可能这个性能损失还不止30%。

  第三个是并发处理,要提高效率就需要处理并发,通用协议栈处理并发不可避免的需要用到同步机制,通过连接跟踪模块之前做过的优化数据来看,在多核并发访问带有读写锁的连接跟踪表比起访问分核处理过没有读写锁的连接跟踪表,性能要低大约20%左右。由于TCP的连接控制块的规模和连接跟踪表在同一个数量级,因此协议栈如果带有读写锁来处理并发问题也应该带来类似的性能损失。为此,专有协议栈很好的利用了分流器带来的一些便利,把TCP连接控制块等和连接相对应的数据结构独立组织在各个核上,这样就可以让每个核上的连接顺序的访问对应核上的数据结构,避免了并发访问,从而避免了锁机制。

  采用专有协议栈可以通过把它运行在应用程序相同的空间来避免系统调用,可以通过一些专门的技术实现数据收发的“0”拷贝,同样可以通过软件架构实现无锁并发访问。这些都为太一应用交付产品在硬件配置相同的情况下,提供了更高的性能。

  4、系统可移植性

  通用协议栈由于复杂度高,功能集合庞大,因此它的接口也非常庞大,这样给其带来了移植上的复杂性。

  专用协议栈由于复杂度低,功能集合较小,接口也相对单一,因此移植也很方便。举个例子:我们实现的专用协议栈对底层实际上只有一个接口函数,对上层只有一组套接字;通用协议栈底层的接口就有多个,套接字种类更是种类繁多。

  5、兼容性

  兼容性方面通用协议栈由于实现完备,功能集合齐全,因此它的兼容性是很好的,但是由于无论是专用协议栈还是通用协议栈其实都是符合统一的协议规范,专用协议栈甚至都可以移植通用协议栈的某些算法,因此从兼容性的角度来说由于专用协议栈可以预知它需要面对的应用场景,因此它的兼容性也是可控的。

  6、稳定性

  通用协议栈一般稳定性都比较好,那是因为它经过了各种实际应用长期的检验,专用协议栈在经历了相同级别的应用检验以后也应该能够达到通用协议栈的级别。

  专用协议栈则因为处理的场景专一,复杂性相对较低,因此即便出现了更新或者升级,其稳定性也基本是可控的。

  小结

  与通用协议栈相比,专用协议栈在很低的开销下带来了十倍的性能提升(当然,整合到系统中,这个系数会降低)。采用专用协议栈的风险主要是系统设计的难度以及在实际应用中兼容性和稳定性的考验(这些问题相信我们的开发、测试同事是可以搞定的)。

1
相关文章