免费注册 查看新帖 |

Chinaunix

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

[算法] 短时间内大量connect()会出现Cannot assign requested address错误 [复制链接]

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:49:45
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-11-09 16:46 |只看该作者 |倒序浏览
有一个代理程序,每接到一个请求,就向服务器发起一个新的链接,把请求传个服务器,然后关闭链接。但是如果在短时间内,代理接到大量的请求,在调用connect的时候connect会返回Cannot assign requested address错误。
现在已经确认代理程序不存在文件描述符泄漏。有啥好的解决方法没有? 不想把服务器和代理都改成长链接模式的,长链接没短链接处理起来简单。

论坛徽章:
1
射手座
日期:2014-08-04 16:49:43
2 [报告]
发表于 2012-11-09 17:03 |只看该作者
unix网络编程里好像有说tcp有个参数可以改..缩短TIME-WAIT时间

论坛徽章:
0
3 [报告]
发表于 2012-11-09 18:26 |只看该作者
koolcoy 发表于 2012-11-09 16:46
有一个代理程序,每接到一个请求,就向服务器发起一个新的链接,把请求传个服务器,然后关闭链接。但是如果 ...


没看懂。
是因为大量connect都指向同一个地址,而该地址尚未结束处理而关闭吗?
如果是这样确实不如长连接好,或者你把同一个地址的请求全部放入队列逐个处理(还不如长连接,相当于手工做I/O复用)。

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:49:45
4 [报告]
发表于 2012-11-09 18:31 |只看该作者
回复 3# NalaGinrut

就是我反复地connect同一个地址,connect后发送完了就关闭。 如果这个操作短时间内大量发生,connect就会报错。

短链接比长链接简单一些。
   

论坛徽章:
0
5 [报告]
发表于 2012-11-09 18:34 |只看该作者
回复 4# koolcoy

估计端口号用完了。
http://www.51testing.com/?uid-66 ... space-itemid-147278

   

论坛徽章:
1
2015年迎新春徽章
日期:2015-03-04 09:49:45
6 [报告]
发表于 2012-11-09 19:05 |只看该作者
回复 5# NalaGinrut

不知道准确原因, 因为我每次发完数据后都关闭了链接, 按理来说端口应该很快就能被释放出来,但事实上, 端口释放时间比较长。

论坛徽章:
0
7 [报告]
发表于 2012-11-09 23:07 |只看该作者
回复 6# koolcoy


照着那个链接的设置做就行了,目的是缩短等待的时间,快速关闭,不然关闭太慢就是会这样。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
8 [报告]
发表于 2012-11-10 10:31 |只看该作者
如果代理程序在Internet上运行,缩短TIME_WAIT时间可不是个好主意

如果你能控制本地端口号的使用,可以这么创建连接

第一步:创建SOCKET
第二步:分配一个本地端口号和本地地址
第三步:设置SOCKET选项允许REUSED端口
第四步:bind第二步的地址和端口
第五步:connect服务器的地址和端口

我做一个单进程1万并发的FTP服务器的数据连接就是这么做的,PORT方法数据连接是由服务器发起的

为保证端口不被用光,本地IP至少申请10个以上,发起连接的IP地址和端口轮换着用
否则碰上迅雷之类的立马端口耗尽

论坛徽章:
0
9 [报告]
发表于 2012-11-10 11:48 |只看该作者
safedead 发表于 2012-11-10 10:31
PORT方法数据连接是由服务器发起的


能否解释下这句话?

另外,“分配一个本地端口号和本地地址“是针对最一开始那个socket吗?
我没有搞懂这个用法,是bind两次?还是一旦失效就根据分配好的port列表重新bind,以此类推?

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
10 [报告]
发表于 2012-11-10 11:52 |只看该作者
本帖最后由 linux_c_py_php 于 2012-11-10 11:53 编辑

看样是TIME_WAIT引起的, 端口被占用光了, 优化一下网络配置吧, /etc/sysctl.conf, 相关文档给你贴俩连接, 这些在<linux性能优化>那本书里是有提及的, http://www.cnblogs.com/hbycool/articles/2269326.html.

至于怎么做一个高效的proxy, 大致可以想到不同层次的几种实现手法, 并且楼主看样还不需要向client返回backend的应答:

1, 线程池, 每个线程单连接阻塞处理, 连接由监听线程accept后派发到空闲线程(适合queue+mutex+cond方式)
2, I/O复用(异步), proxy->backend采取短链接, 每一次请求出发Dproxy向backend发起短连接, 对client保持短连接或者长连接都随意.(甚至结合1,2, 线程池, 每个线程维护一堆连接, 只不过是提高并发能力而已.)
3, I/O复用, proxy->backend采取简单的长连接, 即在client第一次请求时dproxy->backend发起长连接,并与client保持长连接, client多次连续请求均可通过一条->backend的长连接持续处理.
4, I/O复用, 但backend要求预先配置好不可变, 因为前面3种是完全可以让client携带backend地址的. backend预配置的情况下, 就可以做不同的架构了, 那就是把proxy逻辑挪到client I/O 线程之外作为独立线程, proxy线程依然I/O复用异步, 但内部是维护好长连接池的, I/O主线程与proxy I/O线程间采用pipe+queue的方式异步通信, proxy要做的只是把请求丢到对应的连接的写队列里, 如果backend长连接失效, 还需要非阻塞的把连接重新建立起来, 并丢弃掉未完整写出的请求.
5, 最顶级的做法, 单线程完全异步proxy逻辑, 与方法3相同, 即到proxy的连接是第一次请求触发的长连接, 但架构上我们有能力让proxy解耦开来作为一个plugin工作, 具体参考https://github.com/liangdong/Server.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP