百度空间 | 百度首页 
 
查看文章
 
再谈点对点通讯模块的故障问题
2008-12-14 00:05
上个月曾经提过一个高负荷服务器点对点通讯模块的若干问题,目前这个模块已经基本稳定,其中一些朋友的留言对改进这个模块也很有启发。最近主要考虑了通讯故障的问题并进行了测试。

服务器之间的通讯通常会由于网络原因造成各种故障,如果在一个LAN之内,出现故障的概率很小,几乎可以不用考虑。但如果分布在不同的地点比如跨机房跨地域,短时故障的概率就会变大,由于中间线路,路由器等各种设备或者VPN的问题,容易出现短期(比如10-30S左右)对方不可到达的情形。如果每秒系统传递的包有成千上万,那问题就会变得很严重,大量的业务数据投递会发生问题,并且按先后顺序发生以下事件。

(Figure 1 应用程序,操作系统及相关参数的影响)

1. Socket send buffer 未占满期间socket会继续可写, 如果设置了SO_SNDBUF则会使用SO_SNDBUF, 否则使用Linux默认的配置。
# increase TCP max buffer size setable using setsockopt()
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
# increase Linux autotuning TCP buffer limits
# min, default, and max number of bytes to use
# set max to at least 4MB, or higher if you use very high BDP paths
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
SO_SNDBUF通常按以下公式设置:BDP = link_bandwidth * RTT
远端
BDP = 100MBps * 0.050 sec / 8 = 640KB
本地
BDP = 1024MBps * 0.005 sec / 8 = 655KB

2.
Socket占满后写socket会block, 或者设置了TCP_NODELAY则不管SOCKET buffer是否占满都会block

3. 如果应用写入操作没有队列概念则应用程序会出现异常,所有操作会阻塞。

4. 强壮的应用会对发送数据做应用层的buffer,像Connection Manager/Openfire之间是使用发送 Thread Pool,在对方不可到达的时段内,内存占用会急剧上升。

5. 如果网络层恢复正常,首先是socket buffer中的数据会被发送,然后应用层堆积的数据也随后发送。

6. 如果网络层长时间不可用,有2种方法可以判断,通过达到SO_SNDTIMEO Socket返回错误检测,应用层如果需要更早知道错误,可以调低SO_SNDTIMEO。另外一种检测方法是应用检测发送队列达到上限临界值来做进一步 处理。避免服务器内存溢出造成崩溃。实际环境中需要结合这2种方式一起考虑。

Update: 感兴趣朋友可了解后续文章:多服务器通讯层应该如何设计—一次code review小记

类别:高性能服务器 | 添加到搜藏 | 浏览() | 评论 (6)
 
最近读者:
 
网友评论:
1
2008-12-14 05:04 | 回复
呵呵 很专业,而且写blog的态度很认真
 
2
2008-12-14 16:10 | 回复
谈谈第四点。 以前我做一个服务器,在接收客户端发送过来的数据时,也要将数据做处理后转发给另一个服务器。拓扑图大致如下 Client <---> ServerA <----> ServerB 当服务器ServerB可能由于处理能力,或是网络原因,无法及时接收并处理堆积在底层的数据,这时候ServerA发送的数据就会在应用层堆积起来,内存逐渐上涨。 我尝试在这种情况发生时,停止接收Client的数据(一段时间内不处理Client的数据是可以接受的),在ServerA中注销对读事件的监听,直到堆积的发送数据下降到合理的值,才继续注册读事件。 只是那时候用的NIO框架对 Client <-> ServerA,ServerA <-> ServerB 的通讯是用不同的Reactor处理,导致了代码繁琐和不稳定,如果是用同一个Reactor进行处理,相信会简单不少。
 
3
2008-12-14 18:47 | 回复
应用层的buffer不限制上限是很傻的做法。我通常发送时都要设置O_NONBLOCK的选项,只要系统发送缓冲区满就失败
 
4
2008-12-15 12:03 | 回复
@Atry 嗯,我说的是设了上限,然后客户端还继续发消息过来,这时候就要取消对读的监听了。发送的消息队列可以设置长度,当满的时候阻塞或者抛错。
 
5
2008-12-27 11:09 | 回复
请教一个可能很白痴的问题,我也用baidu的blog,贴代码的时候,就很难看,不知道你贴代码是怎么贴,那个框是怎么搞定的?
 
6
2008-12-30 09:31 | 回复
5楼的回答见 http://hi.baidu.com/jabber/blog/item/ce62c0fc7c0355f9fd037f26.html/cmtid/ec2047c20a55b730e5dd3bc9#ec2047c20a55b730e5dd3bc9
 
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
验证码: 请点击后输入四位验证码,字母不区分大小写
      

     

©2009 Baidu