访问本机 Server,使用 127.0.0.1 能比 192.168.x 更快吗?
The following article is from 架构技术漫谈 Author 张彦飞allen
来源丨经授权转自 架构技术漫谈(ID:gh_f115c9e21b4c)
作者 | 张彦飞allen思考题:访问本机 Server 时,使用 127.0.0.1 能比使用本机 ip(例如192.168.x.x) 更快吗?
飞哥的结论是,这两种使用方法在性能上没有啥差别。
一、相关源码分析
第一: 所有 local 路由表项内核都会标识为 RTN_LOCAL。
前面文章里可以看到选用哪个设备是在网络层里路由选择的时候决定的,函数是 __ip_route_output_key。
//file: net/ipv4/route.c
struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
{
if (fib_lookup(net, fl4, &res)) {
}
if (res.type == RTN_LOCAL) {
dev_out = net->loopback_dev;
...
}
rth = __mkroute_output(&res, fl4, orig_oif, dev_out, flags);
return rth;
}
这里会查询到 local 路由表。
# ip route list table local
local 10.162.*.* dev eth0 proto kernel scope host src 10.162.*.*
local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1
很多人在看到这个路由表的时候就被它给迷惑了,以为上面 10.162.. 真的会被路由到 eth0。而其实内核在初始化 local 路由表的时候,把 local 路由表里所有的路由项都设置成了 RTN_LOCAL。这个过程是在设置本机 ip 的时候,调用 fib_inetaddr_event 函数完成设置的。
static int fib_inetaddr_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
switch (event) {
case NETDEV_UP:
fib_add_ifaddr(ifa);
break;
case NETDEV_DOWN:
fib_del_ifaddr(ifa, NULL);
//file:ipv4/fib_frontend.c
void fib_add_ifaddr(struct in_ifaddr *ifa)
{
fib_magic(RTM_NEWROUTE, RTN_LOCAL, addr, 32, prim);
}
第二: 所有 RTN_LOCAL 类型的路由表都会选择到 loopback 虚拟设备。
来看网络层的这段源码。
//file: net/ipv4/route.c
struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
{
if (fib_lookup(net, fl4, &res)) {
}
if (res.type == RTN_LOCAL) {
dev_out = net->loopback_dev;
...
}
rth = __mkroute_output(&res, fl4, orig_oif, dev_out, flags);
return rth;
}
所以即使本机 IP,不用 127.0.0.1,内核在路由项查找的时候仍然会使用 net->loopback_dev。也就是 lo 虚拟网卡。
二、实践验证
为了稳妥起见,飞哥再抓包确认一下。开启两个控制台窗口,一个对 lo 设备进行抓包。因为局域网内会有大量的网络请求,为了方便过滤,这里使用一个特殊的端口号 8888。如果这个端口号在你的机器上占用了,那需要再换一个。
#tcpdump -i eth0 port 8888
另外一个窗口使用 telnet 对本机 IP 端口发出几条网络请求。
#telnet 10.162.*.* 8888
Trying 10.162.*.*...
telnet: connect to address 10.162.*.*: Connection refused
这时候切回第一个控制台,发现啥反应都没有。说明包根本就没有过 eth0 这个设备。
再把设备换成 lo 再抓。当 telnet 发出网络请求以后,在 tcpdump 所在的窗口下看到了抓包结果。
# tcpdump -i lo port 8888
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 65535 bytes
08:22:31.956702 IP 10.162.*.*.62705 > 10.162.*.*.ddi-tcp-1: Flags [S], seq 678725385, win 43690, options [mss 65495,nop,wscale 8], length 0
08:22:31.956720 IP 10.162.*.*.ddi-tcp-1 > 10.162.*.*.62705: Flags [R.], seq 0, ack 678725386, win 0, length 0
总结
我觉得有相当大一部分人都会认为访问本机 Server 的话,用 127.0.0.1 更快。原因是直觉上认为访问 IP 就会经过网卡。
其实内核知道本机上所有的 IP,只要发现目的地址是本机 IP 就可以全走 loopback 回环设备了。本机其它 IP 和 127.0.0.1 一样,也是不用过物理网卡的,所以访问它们性能开销基本一样!
识别关注我们
了解更多精彩内容
点分享
点点赞
点在看