tayga nat64优化的自省揭示tun虚拟网卡的正确玩法

tayga可以完成NAT64转换,它看起来阵势很大,一般能用yum/apt-get直接源上安装的软件都是信得过的软件,我也因此信得过tayga,无论是功能,还是性能。所以我也就没有去看它的代码,直接拿来主义使用了。

可是tayga的大并发测试远不达预期,它竟然是一个使用单队列tun网卡的单进程单线程程序,其结构就是一个大循环:tayga不停地从tun字符设备读取IPv6或者IPv4报文,经过6-4/4-6转换后再发回该tun字符设备。

看到这般场景,我的老毛病便又犯了。

  • 用多个线程分别执行大循环。
  • 用多队列tun分配给每个线程一个fd。
  • 上锁访问全局数据结构。

就跟我多年前的做法一样。但实际上最终我只是做了一堆垃圾而已。这就是我,并不懂编程却又要表现的会编程,见代码就改但却只改一点点,时不时还要炫技一把。

多年以后,我嘲笑自己。

其实用不着改一行代码,仅靠配置完成性能横向扩展的做法更能彰显水平。随着把幼稚褪去,现如今同样是为了扩展tayga的并发处理能力,我的做法多少显得没有工作量。

  • 准备n份配置文件,每份配置文件中tun-device参数,dynamic-pool参数区分开来。
    需要将一个大的dynamic-pool拆分成n个小段,或者干脆就准备n个独立的pool。
  • 以tayga --config conf$id为命令行启动n个tayga进程。
  • 配置multipath路由,分散IPv6流量路由到n个tun设备。

其中multipath路由的配置如下:

ip -6 route add 64:ff9b::/96 \
> nexthop via fe80::991d:bc54:482:5f1 dev nat64-1 \
> nexthop via fe80::991d:bc54:482:5f2 dev nat64-2 \
> ...
> nexthop via fe80::991d:bc54:482:... dev nat64-n

对应的反向IPv4流量的路由配置如下:

ip route add $dynamic-pool_from_conf-1 dev nat64-1
ip route add $dynamic-pool_from_conf-2 dev nat64-2
...
ip route add $dynamic-pool_from_conf-n dev nat64-n

enjoy yourself!

我敢打赌这个配置跑起来之后的性能肯定比我魔改的那个多线程多队列tun网卡的tayga版本要好,因为各个tayga实例的配置都是独立的,无需上锁访问共享资源。

曾经我是多么自信深谙UNIX设计哲学,组合小部件而不是编写大程序,这似乎对我这种不会编程的人再合适不过了,然而有多少次我的行为却与此背道而驰。我是多么的肤浅且幼稚。

是时候揭露我曾经的愚蠢了。

5,6年前开始,我自诩在OpenXXX方面无所不能,整天吹嘘将OpenXXX改成了多线程,在2.6.32版本内核支持了tun多队列,reuseport等特性。还给出了一大堆理由证明OpenXXX的单进程单线程大循环结构是愚蠢的,于是我也就有十足的理由对其进行修改。

在对OpenXXX做修改之前,先前的一个方案就是启动多个OpenXXX实例,然后对其网卡做bridge/bonding,对外展示唯一一个虚拟网卡。我不知道是什么执念让我非要做这种只是看起来好看的事情,直到现在我也不得知。

旧事不提了,现在我来展示OpenXXX高性能扩容的正确做法。事实上在其manual中已经有所提示:

–remote-random
When multiple --remote address/ports are specified, or if connection profiles are being used, initially randomize the order of the
list as a kind of basic load-balancing measure.

既然可以在一个集群的不同机器上启动不同的OpenXXX实例,将这些搬到一台机器上又有什么不可以的呢?只需要让它们监听不同的端口且区分不同的虚拟网段即可。

如此一来,在服务端,ifconfig会展示多个tun/tap网卡,这又有什么不好呢?如果我确实觉得这不好,比方说我想使用同一个配置文件,那么多个tun/tap网卡被分配到同一个虚拟IP地址有什么不对吗?我需要做的仅仅是在每个实例client-connect脚本或者plugin中将接入client携带的IP段添加至路由表即可:

ip route add $ipnet_from_this_client dev $tun_of_this_instance

哦,如果连监听端口都想一样,那无非也就是支持一下reuseport罢了,或者说,用LD_PRELOAD机制把bind库函数劫持了增加setsockopt不就妥妥的了么?Oh,no!这里又有不好的味道了,就此打住吧。

写上面这段的目的不仅仅是嘲讽我自己多么愚蠢,更多的是想揭露一下我将一个简单的事情极度复杂化的过程,随着我个人的成长,我渐渐得理解这是多么的不合情理。

而且,在5,6年前的那个时候,我自我感觉比任何时候都理解 “UNIX组合小部件不写大程序” 的内涵,这简直太讽刺了。

结论是什么? tun虚拟网卡的正确玩法真的不一定需要编写多线程代码,组合单进程单线程使用单队列的程序,才是正确的玩法,编程者们同意吗?至少这是对我这种不会编程的人的馈赠。


浙江温州皮鞋湿,下雨进水不会胖。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值