云服务器价格_云数据库_云主机【优惠】最新活动-搜集站云资讯

CDN_数据库软件排行_

小七 141 0

SOCKMAP—未来的TCP拼接

最近我们偶然发现了反向代理的圣杯——一个TCP套接字拼接API。这引起了我们的注意,因为,正如你所知,我们经营着一个全球反向代理服务网络。正确的TCP套接字拼接可以减少用户空间进程的负载,并实现更高效的数据转发。我们意识到Linux内核的SOCKMAP基础设施可以重用。SOCKMAP是一个非常有前途的API,它可能会导致数据密集型应用程序(如软件代理)的架构发生结构性变化。图片来源:Mustad Marine public domain但让我们倒带一点。L7代理人的分娩痛苦从用户空间传输大量数据效率低下。Linux提供了两个专门的系统调用来解决这个问题。例如,sendfile(2)syscall(Linus不喜欢)可以用来加速将大文件从磁盘传输到套接字。然后是传统代理用于在两个TCP套接字之间转发数据的拼接(2)。最后,可以使用vmsplice将内存缓冲区粘贴到管道中而不进行复制,但很难正确使用。遗憾的是,sendfile、splice和vmsplice非常专业化、同步化,只解决了问题的一部分——它们避免将数据复制到用户空间。他们没有解决其他效率问题。之间避免用户空间内存零拷贝发送文件磁盘文件-->套接字对不剪接管座对对?VMPLICE公司内存区域-->管道不对转发大量数据的过程面临三个问题:系统调用成本:为每个转发的数据包进行多个系统调用代价高昂。唤醒延迟:必须经常唤醒用户空间进程才能转发数据。根据调度程序的不同,这可能会导致较差的尾部延迟。复制成本:将数据从内核复制到用户空间,然后立即返回到内核是不免费的,这会增加可测量的成本。很多人试过了在TCP套接字之间转发数据是一种常见的做法。它需要:透明的转发HTTP代理,比如Squid。反向缓存HTTP代理,如Varnish或NGINX。负载平衡器,如HAProxy、Pen或Relayd。在过去的几年里,有很多人试图降低Linux上TCP套接字之间哑数据转发的成本。此问题通常称为"TCP拼接"、"L7拼接"或"套接字拼接"。让我们比较一下TCP拼接的常用方法。为了简化问题,我们将编写一个简单的tcpeecho服务器,而不是编写丰富的第7层TCP代理。不是开玩笑。echo服务器可以很好地演示TCP套接字拼接。你知道吗?"回声"基本上是用它自己拼接插座的!天真:读写循环简单的TCP echo服务器如下所示:同时数据:数据=读取(sd,4096)writeall(sd,数据)再简单不过了。这是一个完全有效的程序,可以正常工作。为了完整起见,我在这里准备了完整的代码。拼接:专用系统调用Linux有一个惊人的拼接(2)系统调用。它可以告诉内核在套接字上的TCP缓冲区和管道上的缓冲区之间移动数据。数据保留在内核端的缓冲区中。这解决了在用户空间和内核空间之间不必要地复制数据的问题。有了SPLICE_F_MOVE标志,内核就可以完全避免复制数据!我们使用splice()的程序如下所示:管道,管道=管道()fcntl(管道,F_SETPIPE_SZ,4096);而n:n=接头(sd,管道-wr,4096)接头(管接头,sd,n)我们仍然需要唤醒用户空间程序并进行两次系统调用来转发任何数据,但至少我们避免了所有的复制。全部来源。io_submit:使用Linux AIO API在之前的一篇关于io_submit()的博客文章中,我们建议使用带有网络套接字的AIO接口。请阅读博客文章以了解详细信息,但这里是一个准备好的程序,它只使用一个syscall实现了echo服务器循环。图像由jrsnchzhrs通过Nd 2.0SOCKMAP:终极武器近年来,Linux内核引入了eBPF虚拟机。有了它,用户空间程序可以在内核上下文中运行专门的、非图灵完整的字节码。现在可以为许多用例选择eBPF程序,从包过滤到策略执行。从内核4.14开始,Linux得到了新的eBPF机制,可以用于套接字拼接——SOCKMAP。它是由约翰·法斯塔本德在纤毛,向eBPF程序公开Strparser接口。Cilium使用SOCKMAP来执行第7层策略,它使用的所有逻辑都嵌入到eBPF程序中。这个API没有很好的文档记录,需要root用户,而且根据我们的经验,它有点缺陷。但很有希望。阅读更多:LPC2018-结合KTL和BPF进行反思和政策实施纸质视频幻灯片原始SOCKMAP提交这是如何使用SOCKMAP:SOCKMAP,特别是"BPF_MAP_TYPE_SOCKMAP",是eBPF映射的一种类型。这个映射是一个"数组"——索引是整数。所有这些都很标准。神奇之处在于映射值——它们必须是TCP套接字描述符。这张地图很特别,它有两个eBPF程序。你读对了:eBPF程序实时连接到一个映射,而不是像往常一样连接到套接字、cgroup或网络接口。以下是在用户程序中设置SOCKMAP的方法:sock_map=bpf_create_map(bpf_map_类型_SOCKMAP,sizeof(int),sizeof(int),2,0)prog_parser=bpf_加载_程序(bpf_prog_TYPE_SK_SKB,…)prog_判决=bpf_load_程序(bpf_prog_TYPE_SK_SKB,…)bpf_prog_attach(prog_parser,sock_map,bpf_SK_SK_STREAM_parser)bpf_prog_attach(程序裁决、sock_map、bpf_SK_SK_STREAM_裁决)塔达!在这一点上,我们已经建立了一个sock_-map-eBPF映射,附带了两个eBPF程序:parser和verdiction。下一步是向这个映射添加一个TCP套接字描述符。再简单不过了:int idx=0;int val=标准差;bpf_map_update_elem(sock_map,&idx,&val,bpf_ANY);在这一点上魔术发生了。从现在起,每当我们的socket sd接收到一个包时,都会调用prog_parser和prog_decision。它们的语义在strparser.txt文件以及介绍性的SOCKMAP提交。为了简单起见,我们的普通echo服务器只需要最小的存根。这是eBPF代码:SEC("程序分析器")int prog_解析器(struct_usk_buff*skb){返回skb->len;}SEC("程序裁决")内部程序判决(struct\u sk_buff*skb){uint32_t idx=0;返回bpf_sk_redirect_map(skb,&sock_map,idx,0);}旁注:为了这个测试程序的目的,我编写了一个最小的eBPF加载程序。它没有依赖关系(bcc、libelf或libbpf),可以进行基本的重新定位(比如解析上面提到的sock_映射符号)。查看代码。对bpf_sk_redirect_map的调用正在完成所有工作。它告诉内核:对于接收到的数据包,请噢,请将其从某个套接字的接收队列重定向到位于索引0下sock_map中的套接字的发送队列。在我们的例子中,这些是相同的插座!在这里,我们实现了echo服务器应该做的事情,但纯粹是在eBPF中实现的。这项技术有多重好处。首先,数据永远不会复制到用户空间。其次,我们永远不需要唤醒用户空间程序。所有的操作都在内核中完成。很酷,不是吗?我们还需要一段代码来挂起用户空间程序,直到套接字关闭。这是最好的旧民意测验(2):/*等待插座关闭。让SOCKMAP变魔术吧。*/结构pollfd fds[1]={{.fd=sd,.events=POLLRDHUP},};投票(fds,1,-1);完整代码。基准在此阶段,我们介绍了四个简单的TCP echo服务器:天真读写循环剪接io提交插座图总而言之,我们衡量的是三件事的成本:系统调用成本唤醒潜伏期,主要表现为尾部潜伏期复制数据的成本理论上,SOCKMAP应该击败所有其他公司:系统调用成本唤醒用户空间复制成本读写循环2个系统调用对2份副本剪接2个系统调用对0份拷贝(?)io提交1个系统调用对2份副本插座图没有人不0份副本给我看看号码这是帖子的一部分,我向你展示了惊人的数字,清楚地展示了不同的方法。可悲的是,基准测试很难,而且。。。SOCKMAP是最慢的。重要的是要公布负面结果。我们的试验台如下:两台裸机Xeon服务器与25Gbps网络连接。两者都禁用了涡轮增压,并且测试程序都是CPU固定的。为了更好地定位,我们将RX和TX队列分别定位到一个IRQ/CPU。测试服务器运行一个脚本,该脚本发送10k批固定大小的数据块。该脚本测量echo服务器返回通信量所需的时间。我们为每个测量的echo服务器程序执行10次单独的运行。TCP:"立方"和非角度=1。两台服务器都运行4.14内核。我们对实验数据的分析发现了一些异常值。我们认为一些最糟糕的时刻,表现为长回音响应,是由不相关的因素造成的,比如网络数据包丢失。在所展示的图表中,我们跳过了最底层的1%的异常值,以便集中精力于我们认为重要的数据上。此外,我们在SOCKMAP中发现了一个bug。一些运行的延迟高达64毫秒。以下是其中一个测试:价值观最小值:平均236.00:669.28地中海=390.00最大值:78039.00偏差:3267.75分计数:2000000价值观:值|--------------------------------------------------计数1 | 02 | 04 | 08 | 016 | 032 | 064 | 0128 | 0256 | 3531512 |**********************************************17560521024 |*****2082262048年-18589年4096个|