干翻 nio ,王炸 io_uring 来了 ,史上最详细说明及最全图解!!

Image
大趋势:全链路异步化,性能提升10倍+ 随着业务的发展,微服务应用的流量越来越大,使用到的资源也越来越多。 在微服务架构下,大量的应用都是 SpringCloud 分布式架构,这种架构总体上是 全链路同步模式 。 全链路同步模式 不仅造成了资源的极大浪费,并且在流量发生激增波动的时候,受制于系统资源而无法快速的扩容。 全球后疫情时代,降本增效是大背景。如何降本增效?一条好的路径: 全链路同步模式  ,升级为  全链路异步模式 。 全链路异步模式 改造 具体的内容,请参考尼恩的深度文章: 全链路异步,让你的 SpringCloud 性能优化10倍+ 先回顾一下全链路同步模式架构图 全链路同步模式  ,如何升级为  全链路异步模式 , 就是一个一个 环节的异步化。 40岁老架构师尼恩,持续深化自己的3高架构知识宇宙,当然首先要去完成一次牛逼的 全链路异步模式 微服务实操,下面是尼恩的实操过程、效果、压测数据(性能足足提升10倍多)。 全链路异步模式 改造 具体的内容,请参考尼恩的深度文章: 全链路异步,让你的 SpringCloud 性能优化10倍+ 并且,上面的文章,作为尼恩 全链路异步的架构知识,收录在《 尼恩Java面试宝典 》V52版的架构专题中 注:本文以 PDF 持续更新,最新尼恩 架构笔记、面试题 的PDF文件,请从这里获取: 语雀 或者 码云 全链路异步化的最终目标 全链路异步化的最终目标,如下图所示: 应用层:编程模型的异步化 框架层:IO线程的异步化 OS层:IO模型的异步化 一:应用层:编程模型的异步化 这个请大家去看 尼恩的 《 响应式 圣经 PDF 》电子书 随着 云原生时代的到来, 底层的 组件编程 越来越 响应式、流化, 从命令式 编程转换到 响应式 编程,在非常多的场景 ,是大势所趋。 而响应式编程, 学习曲线很大, 大家需要多看,多实操。 二:框架层:IO线程的异步化 这个大家 都选择 具有异步 回调功能的 异步线程模型,如 Reactor 线程模型 这个是面试的绝对重点 IO的王者组件,Netty框架,整体就是一个 Reactor 线程模型 实现 也是非常核心的知识,这里不做展开,请大家去看尼恩的畅销书《Java 高并发核心编程卷 1 加强版》。 三:OS层:IO模型的异步化 目前的一个最大难题,是IO模型的异步化。 注意,Netty

Linux 服务器 存在多网卡多IP UDP 监听 INADDR ANY(0.0.0.0)出现收包源IP不一致问题解决方案!



在多IP服务器上,通过策略路由如何保证 回复给客户端的数据不从从原来的网卡出去导致访问不通的问题?


比如在一台双线上,电信 IP 是182.x.x.119 ,网通 IP 是 119.x.x.107 

可以通过以下策略路由保证:

ip route flush table ct
ip route add default via 182.x.x.97 dev eth0 src 182.x.x.119 table ct
ip rule add from 182.x.x.119 table ct
ip route flush table cu
ip route add default via 119.x.x.97 dev eth1 src 119.x.x.107 table cu
ip rule add from 119.x.x.107 table cu

对这段策略路由简单解释下。

ip rule add from 182.x.x.119 table ct 表示源地址是 182.x.x.119 的包,通过ct路由表选路,

ip route add default via 182.x.x.97 dev eth0 src 182.x.x.119 table ct 表示ct路由表的默认路由是从 eth0 的 182.x.x.97 这个网关路由,源地址设置为 182.x.x.119 。

有了这层保证后,我们在实现Server 的时候,监听 socket 依然 bind 到 0.0.0.0 ,在回 数据 包的时候,只要设置该数据包从本机发出去的 源地址 配合策略路由,就可以保证 数据包 正确返回。

现在的关键问题是: 如何获取 数据 包的目的地址? 

对于无连接状态的 UDP socket 获取目的地址就很难了,木有现成的系统调用,获取方法还是有点点麻烦的。通过 man ip 可以获取详细的步骤和原理:

IP_PKTINFO (since Linux 2.2)
    Pass an IP_PKTINFO ancillary message that contains a pktinfo 
    structure that supplies some information about the incoming packet. 
    This only works for datagram oriented sockets. 
    The argument is a flag that tells the socket 
    whether the IP_PKTINFO message should be passed or not. 
    The message itself can only be sent/retrieved as control message 
    with a packet using recvmsg(2) or sendmsg(2).
    
    struct in_pktinfo {
        unsigned int   ipi_ifindex;  /* Interface index */
        struct in_addr ipi_spec_dst; /* Local address */
        struct in_addr ipi_addr;     /* Header Destination
                                        address */
    };
    
    ipi_ifindex is the unique index of the interface the packet was received on. 
    ipi_spec_dst is the local address of the packet and 
    ipi_addr is the destination address in the packet header. 
    If IP_PKTINFO is passed to sendmsg(2) and ipi_spec_dst is not zero, 
    then it is used as the local source address for the routing table lookup 
    and for setting up IP source route options. When ipi_ifindex is not zero, 
    the primary local address of the interface specified 
    by the index overwrites ipi_spec_dst for the routing table lookup.

这里的说明说的相当清楚

先决条件就是要 setsockopt 设置 IP_PKTINFO ,通过系统调用 recvmsg 便可获取 in_pktinfo 结构数据,其中 ipi_spec_dst 便是我们想要的目的地址,

然后 sendmsg 的时候传入 ipi_spec_dst ,这样就会使用这个地址来做策略路由。

有了这个做指导,编码起来就很简单的啦,有 C版本 的实现,这里的 python 版本 通熟易懂些。

上面的方法固然好,但是很多语言目前稳定版本,socket 都不支持 sendmsg,recvmsg,更不要说 setsockopt 设置 IP_PKTINFO 了。在 java 中没有,在 python 2.7 版本也没有,只有 python 3.3 版本支持。所以这种方法还不具有普适性,但是如果用的是 C 或者 Go 语言,实现起来倒是很方便的。


原文来自:再论UDP SERVER绑定IP到INADDR ANY - On the road (qiusuo.im)

Comments

Popular posts from this blog

便宜好用又稳定的VPN-桔子云,性价比极高!

V2rayN 电脑客户端如何在 win7/win10/win11上 实现全局代理

IOS小火箭/Shadowsocks无需AppleID即可在线安装!