V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NGINX
NGINX Trac
3rd Party Modules
Security Advisories
CHANGES
OpenResty
ngx_lua
Tengine
在线学习资源
NGINX 开发从入门到精通
NGINX Modules
ngx_echo
ab
V2EX  ›  NGINX

TCP 转发 Nginx VS iptables 哪个稳?

  •  
  •   ab · 2022-05-16 17:23:30 +08:00 · 7490 次点击
    这是一个创建于 948 天前的主题,其中的信息可能已经有所发展或是发生改变。

    没有负载均衡的需求

    第 1 条附言  ·  2022-05-16 20:21:28 +08:00
    懵了~
    眼看着问题从应用层被歪到完全看不懂的原理层
    43 条回复    2022-05-23 01:45:08 +08:00
    markgor
        1
    markgor  
       2022-05-16 17:31:06 +08:00
    我更喜欢 iptable
    稳定性的话 nginx 和 iptable 都差不到哪里,
    性能的话我不清楚,毕竟我转发机公网带宽只有 5M 。
    gxm44
        2
    gxm44  
       2022-05-16 17:32:55 +08:00
    感觉 iptables 更好些
    ryd994
        3
    ryd994  
       2022-05-16 17:40:11 +08:00 via Android   ❤️ 2
    一个是 3 层,一个是 4 层,根本不是一回事
    3 层的性能可能比 4 层差,但有专有硬件时可能比 4 层好。但是说回来大多数人应该接触不到这个级别的带宽。

    4 层会处理好 TCP 超时和重传( terminate connection ),对于延迟高、不稳定的网络来说能提速。简单假设就是延迟和丢包率都减半,那 TCP 的流控自然会稳定很多。
    heiher
        4
    heiher  
       2022-05-16 17:40:16 +08:00
    从转发节点内部来看,用户态转发比 iptables 肯定包括了更多的上下文切换以及可能更多的 copy 开销。用户态转发是两条 tcp stream ,且有缓冲; iptables 转发是 raw packet 转发;考虑到网络延迟及对流控的影响,转发节点内部开销不一定是决定性因素。
    alexsunxl
        5
    alexsunxl  
       2022-05-16 17:55:44 +08:00
    Nginx 简单一点。性能差别不太清楚。
    iptables 有些情况要打开内核参数(比如需要 source 要改内网这样的参数)
    fisherwei
        6
    fisherwei  
       2022-05-16 17:59:13 +08:00
    iptables 是指 PAT 吗?那肯定是 iptables 更稳定呀
    ab
        7
    ab  
    OP
       2022-05-16 18:03:53 +08:00
    @ryd994 所以推荐 nginx ?
    tdtdttdd
        8
    tdtdttdd  
       2022-05-16 18:18:58 +08:00 via Android
    都稳,防火墙占资源更少
    ryd994
        9
    ryd994  
       2022-05-16 18:51:36 +08:00 via Android   ❤️ 5
    @heiher 理论上是这么个情况,实际上恰恰相反
    用户态收发 TCP 数据高度依赖硬件加速。tso/lro
    而 3 层转发需要修改每一个数据包,还不能碰 payload 。所以 3 层包处理是个很费 CPU 的工作。

    这也是为什么云平台的虚拟防火墙的性能上不去。高效能网络都是要靠硬件加速。把虚拟化网络相关的操作也下放到专有硬件上。

    不靠 sriov ,不靠 dpdk ,一般操作系统的单线程包转发性能也就 10G-20G 最多了。用好 RSS 可以更多,但那成本就高了。而且对单个连接无效。

    jumbo frame 也是个办法,但那也属于硬件支持了。

    但是普通的 CPU 收发 40G ,100G ,其实都不是什么难事。因为操作系统此时收发的实际上是 65535 字节的超大包。网卡 tso 会拆分成 1500 的普通包发出。接收时也同理。
    geeglo
        10
    geeglo  
       2022-05-16 19:28:57 +08:00
    @ryd994 你这理论明显站不住脚啊。

    首先,传输层转发要拆包改 dst ip ,应用层转发也要拆包改,你说费 CPU 这事,用户态程序做的事情更多,CPU 反而能省下?

    另外,您说的应用层优化问题就更奇怪了,应用层层最终也要丢到传输层去传输,TCP 超时机制,重传机制,什么时候是靠应用层去实现的?
    geeglo
        11
    geeglo  
       2022-05-16 19:36:25 +08:00 via iPhone
    可以这么理解
    有个快递要转运,你打电话给快递公司,他们帮你在中转站的时候就寄到你要的地址去。iptables 做的事情。

    nginx 类似于快递员到你楼下了,然后你再通知他转运。
    heiher
        12
    heiher  
       2022-05-16 19:48:24 +08:00
    @geeglo
    @ryd994

    我理解当有网卡加速来处理 tcp stream 与 iptables 处理 raw packet 的区别,借用快递类似的话,接收:raw packet 是能一次运送(DMA)很多个 packet ,且每个 packet 都带有收发人地址,快递员到达时按一下门铃(中断)让接收人( CPU )处理,CPU 需要修改每个 packet 上的收发人地址。而 tcp stream 的话,网卡收到若干个 raw packet ,将同一个 tcp stream 的 packet 在网卡上合并成一个较大的 packet ,大 packet 只带有一个收发人地址(因为同 stream 都相同),通知 CPU 处理,CPU 只需改一次收发人地址即可。在内核态、用户态交互上,只要 buffer 不大小,上下文切换的次数也是比较少的。
    geeglo
        13
    geeglo  
       2022-05-16 20:03:15 +08:00
    @heiher
    还是有点区别的。
    合并、拆小 这些动作你也说了在网卡的 hardware offload 阶段,同 buff 大小的情况下,内核态也是只改一次。

    只要包到了应用层,肯定是要有其他动作的,相应的优化技术比如 0 拷贝等也存在消耗。

    其实我感觉,无论是内核优化,还是应用层优化,各路大神已经转移重心了,在往着专用硬件,专用芯片的方向,比如 fpga 。
    heiher
        14
    heiher  
       2022-05-16 20:10:28 +08:00
    @geeglo iptables 可以过滤到 tcp 流中每一个具体的 packet 的转发与否,所以可推测这种情况下在与网卡的交互上没有启用相关的硬件加速技术。记得之前在有些光猫上使用 iptables 实现某些操作还需要关闭硬件加速,否则根本走不到 iptables 的路径上。

    具体情况具体对待吧,利用好硬件加速会更香。
    geeglo
        15
    geeglo  
       2022-05-16 20:13:46 +08:00
    @heiher 哦,你这么一说,我得去看看文档,感谢。
    heiher
        16
    heiher  
       2022-05-16 20:23:11 +08:00
    @geeglo 有结论来分享一下哈,把推测证实或证伪,细节具体化,感谢~
    haah
        17
    haah  
       2022-05-16 21:24:27 +08:00
    “稳”貌似是网络层的任务吧!与应用层貌似关系不大。
    haah
        18
    haah  
       2022-05-16 21:25:04 +08:00
    要是内网,UDP 也稳呀!
    among
        19
    among  
       2022-05-16 21:31:26 +08:00
    临时用用,nginx 挺好。
    victorc
        20
    victorc  
       2022-05-16 22:09:51 +08:00
    都很稳,如果不是特别需要考虑性能,用 nginx ,方便调试
    FabricPath
        21
    FabricPath  
       2022-05-16 22:11:14 +08:00   ❤️ 3
    @ryd994 tso 是在网卡 driver 收完,送到协议栈之前就完成了,netfilter 阶段看到的就是一个超大的 skb ;同理,出方向只要 dev 的 feature 带 tso ,那一路都会是一个大 skb ,直到真正的网卡驱动,或者中途某个不支持 tso 的 dev 时,才会被 gso 拆分成多个 skb 。你可以随便找个 docker 环境,起一个 bridge 的容器,在 host 侧的 veth 抓包,会发现 tcpdump 看到的都是大包,因为 veth 默认是开启了 tso 。
    FabricPath
        22
    FabricPath  
       2022-05-16 22:13:14 +08:00
    回到楼主的问题,nginx 会二次建联 tcp ,而 iptables 只是对同一条连接做修改。真因为如此,nginx 可以跨协议代理,比如 HTTPS 转 http 、quic 转 http ,而 iptables 是做不到的。综上,看需求,对性能有要求,只是做 L4 的连接修改,那选 iptables ,对性能没要求,那尽量 nginx ,毕竟 L7 的灵活性无敌
    Rocketer
        23
    Rocketer  
       2022-05-16 22:16:27 +08:00 via iPhone
    别懵,学一下 OSI 7 层模型很有用,也很简单。现在连各种培训班都会讲这个。
    ab
        24
    ab  
    OP
       2022-05-16 22:48:12 +08:00
    heiher
        25
    heiher  
       2022-05-16 23:02:56 +08:00
    @geeglo 感谢 @FabricPath 前面说法被证伪了,刚才查了一下资料也做了一下实验,开启 TSO 或 TSO 时,在 netfilter 确实是合并后的大 skb 。
    ryd994
        26
    ryd994  
       2022-05-17 01:44:26 +08:00 via Android
    @geeglo
    “用户态程序做的事情更多,CPU 反而能省下?”
    我上面着一大段就是在解释,为什么 L4 代理可以比 L3 代理更快。
    L4 代理并不是改每个包的地址,而是在建立了两个 TCP 连接,分别收发。这种情况下,两侧连接都可以充分利用硬件加速。
    L3 代理因为不经过 TCP 协议栈,tso lro 都是用不了的。就要修改每个包的地址。

    家用路由器为什么需要硬件 nat 加速?说白了就是 SoC 性能不足以处理每个包。软路由所需的 CPU 的性能 vs 硬路由的 SoC 的性能,这没法比。硬路由可以用更弱的 SoC 实现同样的性能(在有限的功能范围内),恰恰是说明了,硬件加速对于网络处理的重要性。

    以上是对于比较稳定的高性能网络。瓶颈在硬件性能。

    对于不稳定的网络,L4 代理可以减少重传和延迟,因此能提高单个连接的 throughput ,准确的说是 goodput 。对于这类网络,瓶颈在于 TCP 流控和重传。连接处理性能不是瓶颈。


    以上是我原本的观点。

    但是楼下 @FabricPath 说 nf 在 driver 上层,而 gro/lro 是对所有 TCP 包都有效,因此 nf 也可以享受到硬件加速。如果是这样的话,那 nf 的转发能力肯定是要比 Nginx 要强的。
    bigbyto
        27
    bigbyto  
       2022-05-17 02:05:45 +08:00
    @ryd994
    @heiher
    @geeglo
    @FabricPath

    感谢各位精彩的讨论
    ryd994
        28
    ryd994  
       2022-05-17 02:32:48 +08:00
    @FabricPath 找到了两个 reporte bug:
    https://support.hpe.com/hpesc/public/docDisplay?docId=c03168563&docLocale=en_US
    http://ehaselwanter.com/en/blog/2014/11/02/mtu-issue--nope-it-is-lro-with-bridge-and-bond/

    GRO LRO 导致 ip_forwarding 出问题,说明了 LRO 对 iptables 和后续的转发是有效的。或者说预期上应当有效。
    但是由于某些驱动的 bug ,导致出错进而不得不关闭 GRO LRO ,这是另一回事了。
    arloor
        29
    arloor  
       2022-05-17 02:46:22 +08:00 via Android
    学术讨论之后想用 iptables 做转发的可以看看这个项目: https://github.com/arloor/iptablesUtils
    方便的设置 nat 转发,不需要手敲命令了

    或者可以用 nftables 的项目:
    https://github.com/arloor/nftables-nat-rust
    ab
        30
    ab  
    OP
       2022-05-17 03:11:17 +08:00 via iPhone
    @arloor #29 谢谢
    geekvcn
        31
    geekvcn  
       2022-05-17 07:43:39 +08:00
    @heiher 神论,建议多学习而不是半斤八两的时候急于误导别人
    tramm
        32
    tramm  
       2022-05-17 08:40:21 +08:00
    公司用的 Haproxy, 测试时用的 Nginx.

    打算空下来搞搞 Envoy
    heiher
        33
    heiher  
       2022-05-17 08:55:50 +08:00 via Android
    @geekvcn 哈哈,确实不是非常清楚 TSO/GSO 的实现细节,结合平时的使用感受(我的 r8169 网卡不支持 TSO)就“推测”了一把,好在被及时指正了 :P
    arloor
        34
    arloor  
       2022-05-17 14:13:38 +08:00 via Android
    @arloor #29 增加了 10 个 star 了。。看来还是要找机会发一发才能涨 star 。。
    FabricPath
        35
    FabricPath  
       2022-05-17 15:32:57 +08:00   ❤️ 1
    @ryd994 lro 应该已经被 gro 淘汰了,没用过 lro ,这块儿不是很了解。nf 大部分钩子是夹在协议栈和 driver 之间的,协议栈不会去检查 dev 的 features ,所以 nf+协议栈+用户态看到的报文内容是相同。 区别是用户态在收发包的时候需要多一次内存拷贝,所以要实现相同的功能,任何情况下内核态的 iptables 都会比用户态的 nginx 性能要好。
    比如都是做 L4 代理,在 rx 收到包之后,首包做完 dnat 后建 ct ,后续报文 nat 表的 hook 直接匹配 ct 就修改报文转发出去了,不会经过协议栈;同一个报文,nginx 是 rx->link->network->protocol->copy 到用户态->nginx 解析->把 data 发送到到 rs 的 socket->copy 到内核态->protocol->network->link->tx 。
    另外关于硬件加速这部分,对于 x86 服务器来说,通常情况下只关注 csum offload 、tso 、tls offload ,只有这几个是真正硬件在做的,其他如 gso 、gro 都是纯软件实现。家用路由器的 nat 加速是针对特定场景定制的处理器,具体我不是很清楚它的实现方式,盲猜应该是快慢路径,iptables 处理建联过程,ct 建好后通过 sdk 下发到转发芯片上。
    至于说要实现真正的硬件 offload ,目前有且仅有 mellanox 的 cx5 、cx6 的 switchdev sriov+tc flower offload 是在生产环境大规模使用过,当 tc flower 是 in_hw ,那 tcpdump 都看不到报文,全部在 eswitch 处理了(带 ct 的规则除外,ct offload 比较特殊)。
    ttl123
        36
    ttl123  
       2022-05-17 16:18:31 +08:00
    @FabricPath 虽然看不懂,感觉你比较专业
    tkl
        37
    tkl  
       2022-05-18 16:42:30 +08:00
    @FabricPath
    @heiher
    @ryd994

    https://imgur.com/a/UHKhPZn

    https://github.com/fermads/node.js-process-load-balancing

    我也觉得 iptables 更好,毕竟少了一层

    云平台的虚拟防火墙的性能上不去?感觉有点偷换概念,你用 nginx 就没有瓶颈了?
    ryd994
        38
    ryd994  
       2022-05-18 16:56:10 +08:00 via Android
    @tkl 根本问题不在多一层少一层,而在于能否充分利用硬件 offload 。高性能网络早已不是 CPU 加高频率硬扛可以扛下来的。而是要靠 offload 为主。
    如果 iptables 同样能充分利用硬件,那当然 iptables 会快。
    问题就在于这个如果是否成立,在多大程度上成立。
    纯靠 iptables 的路由器有没有,有,但是用的是魔改内核和 netfilter 。比如博通的 ctf 。后来博通也开始搞硬件的 offload ,也就是 flow accelerator 。
    FabricPath
        39
    FabricPath  
       2022-05-18 17:45:37 +08:00
    @ryd994 不知道说的是哪家的防火墙有性能问题。云平台的防火墙的性能,不知道你是指 nfv 版的防火墙,还是普通的安全组。如果是安全组,各家公有云都是在 Host 侧的 dpdk 实现的,本来 Host 的 dpdk 就一定会有 ct ,连接一旦连接之后,都是在快路径匹配五元组转发,不会遍历流表,所以性能上不去是不存在的,至少目前没听说过国内国外那家公有云的安全组会影响影响。ACL 是无状态的,无 ct 的功能更不可能影响性能。唯一可能就是 nfv 的边界防火墙,或者入侵检测,对应阿里云的云防火墙,这种都是 dpdk 实现的 dpi ,如果说有的云厂商初期会选择用 x86 的 server 来用 iptables 做防火墙,那是有可能会有性能问题,不过迟早都会走向 dpdk 。
    iptables 已经在云网络绝迹了,如果哪家云还在用 iptables 或者 iptables 类似物做产品,最好别买。

    此外有什么“网络加速能力是内核态用不了,而只能用户态能用”,我理解是不存在这样特性的,如果有的话可以贴一下,我也学习一下。
    iptables offload 这个事情社区推进很久了,但是 iptables 本身也即将退出历史舞台,而无论是 iptables 还是 nftables ,绝大部分场景都是用来做有状态服务,而有状态服务要做 offload 最难的地方就是要管理 ct ,网卡无法完成 ct offload 的闭环,需要将带 sync 、rst 、fin 等 flag 的报文送到内核来变更 ct 状态,并决定是否插入或删除硬件的 entry ,带来的问题就是对短连接性能影响较大,家用场景因为连接数少( 16k 以内),所以是没啥问题的。
    关于网卡 offload 能力的 feature ,比如可以搜 NETIF_F_TSO ,来看哪些地方和 TSO 有关,理论上有它出现的地方都是在网卡 driver 。
    ryd994
        40
    ryd994  
       2022-05-18 18:25:17 +08:00
    @FabricPath
    “如果哪家云还在用 iptables 或者 iptables 类似物做产品,最好别买”
    我说的就是 Azure 。Azure 使用 VFP 处理数据包。就算单纯匹配 5 元组,但是因为还有各种封包 /解封包操作。单连接带宽是过不了 10G 的。你想要满血网络,就必定要靠硬件加速。Azure 用的是 FPGA 。多连接当然可以靠堆 CPU 靠 RSS 硬抗,但是那就贵了。
    AWS 虽然是以 smartnic 为主,但是碰到复杂情况硬件不支持就只能靠软件扛了。
    GCP 是以 DPDK/自研软件处理,但是 GCP 单连接是跑不满线速的。
    这是当年的性能比较: https://blog.acolyer.org/2018/05/01/azure-accelerated-networking-smartnics-in-the-public-cloud/
    当然这里 Azure 取巧了:比的是单线程带宽


    言归正传,楼主的问题是基于原版 netfilter vs nginx 的情况,扯 dpdk 那就是完全两回事了。咱们先把 dpdk 放下。

    “网络加速能力是内核态用不了,而只能用户态能用”
    我从来没说过这话。理论上当然 iptables 干什么都行。魔改内核干什么都行。但是原版内核还是有一些原则需要遵守。
    iptables nat 转发不能使用 LRO 是因为 LRO 破坏了 end-to-end 原则。L3 的 ip_forwarding 不应该去修改 L4 的内容。GRO 保留了包边界,因此应当是可以使用的。但是 GRO 的效果和硬件支持的 LRO 比,哪个更好还未可知。

    说实话,我近年都是搞 Windows 网络为主,Linux 并不是我的强项。但是既然这个问题也算是我分内之事,我会再研究一下,不希望误导大家。
    ryd994
        41
    ryd994  
       2022-05-21 14:00:55 +08:00   ❤️ 1
    @FabricPath
    @tkl
    @heiher
    找到了这封邮件: https://www.spinics.net/lists/netdev/msg107539.html
    可见 LRO 在特定情况下是有性能优势的,也可见 iptables 无法使用 LRO 。
    但是我忽略了 GRO 的影响。有 GRO 的情况下,LRO 的“边际收益”并不大,更不用说内存拷贝的开销了。
    所以 iptables 更快是对的。但原因并不是 iptables 更简单所以一定更快这么简单。

    昨天上班时和 Stephen Hemminger 聊了一下这个问题,结论如下:
    1. 如果网络不稳定,带宽不太高,那 nginx 等 L4 代理能改善 timing 和 congestion control ,throughput 会更好一点。
    2. 这封邮件说的情况可能存在,但肯定是个非常少见的 corner case 。支持 LRO 的设备本来就少,Linux 社区也倾向于废弃 LRO 改用 GRO 。
    3. 所以如果是比较干净的网络,那还是用 iptables 更快。
    4. 如果想要 nginx 的灵活性,但又想要 iptables 的性能,可以考虑 BPF/XDP 。
    FabricPath
        42
    FabricPath  
       2022-05-22 20:19:03 +08:00
    @ryd994 在 L4LB 场景下,如果能测出 nginx 能比 ipvs 更快,我也想学习一下这到底是什么样的条件和场景,无论是 latency 还是 throughput
    ryd994
        43
    ryd994  
       2022-05-23 01:45:08 +08:00 via Android
    @FabricPath 如果耍赖,不给用 GRO ,那就有可能。
    nginx 可以用 LRO ,iptables 不行。也不一定是 Nginx ,可以是其他能更好利用 0 copy/1 copy 的用户态软件。

    用 iptables 实现的是 L3 代理。L3 代理受到 end-to-end 限制,而 L4 代理不受。如果能在内核态实现 L4 代理或者允许 L3 代理放宽 end-to-end 限制,那当然可能得到更高的性能。

    上面的邮件就是有人忽略限制硬开 LRO ,获得了比 GRO 更好的性能。
    但是这个案例能否在用户态重现,那就很难讲了。因为 Linux 在 socket 到 socket 的情况下,并没有 0 copy API ,splice 也用不了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3102 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 13:12 · PVG 21:12 · LAX 05:12 · JFK 08:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.