免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1083 | 回复: 1
打印 上一主题 下一主题

[网络子系统] UDP Socket列表变化问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-10-30 00:18 |只看该作者 |倒序浏览
需要做udp proxy的功能,但是在网上看到一篇文章提到了关于UDP Socket列表变化问题的问题,相关的内容如下,自己试验了下,没有出现文章中所提到的
UDP Socket列表变化问题,当然有可能是测试数据量不够,不知有没有哪位朋友了解,是否在所有的linux内核都有这个问题?
要进行多处理,就免不了要在相同的地址端口上处理数据,SO_REUSEADDR允许端口的重用,只要确保四元组的唯一性即可。对于TCP,在bind的时候所有可能产生四元组不唯一的bind都会被禁止(于是,ip相同的情况下,TCP套接字处于TIME_WAIT状态下的socket,才可以重复绑定使用);对于connect,由于通信两端中的本端已经明确了,那么只允许connect从来没connect过的对端(在明确不会破坏四元组唯一性的connect才允许发送SYN包);对于监听listen端,四元组的唯一性油connect端保证就OK了。
TCP通过连接来保证四元组的唯一性,一个connect请求过来,accept进程accept完这个请求后(当然不一定要单独accept进程),就可以分配socket资源来标识这个连接,接着就可以分发给相应的worker进程去处理该连接后续的事情了。这样就可以在多核服务器中,同时有多个worker进程来同时处理多个并发请求,从而达到负载均衡,CPU资源能够被充分利用。
UDP的无连接状态(没有已有对端的信息),使得UDP没有一个有效的办法来判断四元组是否冲突,于是对于新来的请求,UDP无法进行资源的预分配,于是多处理模式难以进行,最终只能“守株待兔“,UDP按照固定的算法查找目标UDP socket,这样每次查到的都是UDP socket列表固定位置的socket。UDP只是简单基于目的IP和目的端口来进行查找,这样在一个服务器上多个进程内创建多个绑定相同IP地址(SO_REUSEADDR),相同端口的UDP socket,那么你会发现,只有最后一个创建的socket会接收到数据,其它的都是默默地等待,孤独地等待永远也收不到UDP数据。
UDP这种只能单进程、单处理的方式将要破灭UDP高效的神话,你在一个多核的服务器上运行这样的UDP程序,会发现只有一个核在忙,其他CPU核心处于空闲的状态。创建多个绑定相同IP地址,相同端口的UDP程序,只会起到容灾备份的作用,不会起到负载均衡的作用。
要实现多处理,那么就要改变UDP Socket查找的考虑因素,对于调用了connect的UDP Client而言,由于其具有了“连接”性,通信双方都固定下来了,那么内核就可以根据4元组完全匹配的原则来匹配。于是对于不同的通信对端,可以查找到不同的UDP Socket从而实现多处理。而对于server端,在使用SO_REUSEPORT选项(linux 3.9以上内核),这样在进行UDP socket查找的时候,源IP地址和源端口也参与进来了,内核查找算法可以保证:

这样对于不同client发来的数据包就能查找到不同的UDP socket从而实现多处理。这样看来,似乎采用SO_REUSEADDR、SO_REUSEPORT这两个socket选项并利用内核的socket查找算法,我们在多核CPU服务器上多个进程内创建多个绑定相同端口,相同IP地址的UDP socket就能做到负载均衡充分利用多核CPU资源了。然而事情远没这么顺利、简单。

2.2 UDP Socket列表变化问题
通过上面我们知道,在采用SO_REUSEADDR、SO_REUSEPORT这两个socket选项后,内核会根据UDP数据包的4元组来查找本机上的所有相同目的IP地址,相同目的端口的socket中的一个socket的位置,然后以这个位置上的socket作为接收数据的socket。那么要确保来至同一个Client Endpoint的UDP数据包总是被同一个socket来处理,就需要保证整个socket链表的socket所处的位置不能改变。
然而,如果socket链表中间的某个socket挂了的话,就会造成socket链表重新排序,这样会引发问题。于是基本的解决方案是在整个服务过程中不能关闭UDP socket(当然也可以全部UDP socket都close掉,从新创建一批新的)。要保证这一点,我们需要所有的UDP socket的创建和关闭都由一个master进行来管理,worker进程只是负责处理对于的网络IO任务,为此我们需要socket在创建的时候要带有CLOEXEC标志(SOCK_CLOEXEC)。

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
2 [报告]
发表于 2016-10-31 10:01 |只看该作者
"列表变化"什么意思?是要避免同一个udp“连接”在不同core之间变来变去么?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP