引子几个月前的一次午饭间,和同事闲聊,突然想起可以在实现Socks4/5等连接代理的时候,当认证等过程结束后,对tcp数据包(即skb)直接做NAT,从而降低CPU占用率、避免内存拷贝,最终达到增大网络流量的目的。当时同事有些异议,后来也就渐渐地遗忘了此事,直到看到中的tcp splicing(TCP粘合)实现,发现有种不谋而合的感觉。
定义Also called "delayed binding," it is the postponement of the connection
between the client and the server in order to obtain sufficient
information to make a routing decision. |
以上定义摘自,译成中文为:
为了获得足够的信息用来制定路由策略而对客户端到服务器的连接进行延迟的一种技术,所以又被称为“延迟绑定”。
|
个人觉得这个定义不够贴切,倒是有些应用环境的味道。
原理当两个socket之间需要互相交换(relay)数据时,不再把数据拷贝到一个临时的缓冲区(大多数情况下是用户空间缓冲区),而是修改tcp数据包的一些参数,如源、目的ip地址和端口号等,然后将修改后的数据包直接通过ip层网络接口发送出去。可见,与基于recv/send机制的数据交换相比,这个过程根本就不需要内核空间到用户空间的转换,也至少避免了两次数据拷贝:从接收缓冲区到用户缓冲区和从用户缓冲区到发送缓冲区,效率也不可同日而语[1][2]。更加详细的内容请参看
TCP粘合技术原理,实际的TCP splicing技术实现还要考虑更多的
细节。
实现目前能够找到源码的Linux环境下实现就是l7sw中的,通过阅读头文件中的注释不难发现此实现是以章文嵩先生的为基础的,发展了有5年左右,应该没什么大的问题。有些小的问题不得不提,此实现不支持TCP协议的一些附加选项比如SACK和TCP Scaling等,还好这些选项开闭的主动权位于客户端,所以我们可以简单地在运行TCP Splicing的机器上关闭这些选项,这样就没有选项不匹配的问题了。似乎是逃避策略,不过试想一下如果TCP Splicing机器和服务器的选项不同,那么TCP Splicing恐怕是不能实现的,又要退化到应用层的数据交换。还有另外一个考虑,此技术多用于类似HTTP协议的存在大量短连接的情况,而那些选项多是为大带宽、长延时和高错误率的网络环境而设计,两者的应用环境交集不大,所以即使不支持也没什么大问题。
应用环境定义中说的已经足够好了,举例来说就是应用层网关、代理服务器和应用层交换机(内容交换机)等。
参考资料[1]
[2]
阅读(3491) | 评论(0) | 转发(0) |