百度空间 | 百度首页 
               
 
查看文章
 
一个高负荷服务器点对点通讯模块的若干问题
2008-10-21 21:51
服务器集群之间的多个服务器之间通讯通常有组播或点对点直连发送两种方式。组播可以参看前文JGroups 简介,适用场合,配置,程序例子Demo等完全使用指南。最近由于业务需要,研究了点对点直连的模式,及需要考虑的各种情况。

点对点传输可以用UDP或TCP实现。究竟用什么实现每个人都有自己的喜好。我是坚决 站在TCP这边。我们目前有个程序由于某种原因需要用UDP传输,优化了好几周目前可以达到5-6M/s了(100M LAN)。那TCP可以达到多少,随便叫个高中生写个Socket C/S程序在上面相同的环境100M LAN,可以达到 100Mbps / 8 = 12.5 M/s。

相对于服务器之间通讯来说,传输速率只是一方面,需要考虑的点包括:
  • 发送方连接数控制。熟悉Socket的朋友都清楚,Socket通讯简单的方法是发送方用1个固定连接发送(比如SMTP/POP3等),或发送方每个请求数据包新建一个连接发送(比如PHP/Ruby连MySQL)。对于服务器之间的通讯程序情况可能会比较特殊,通常会出现峰值,比如有几秒服务器负荷大,可能要几秒内传输数万个数据包。采用1个固定连接或每个数据包新建多个连接都有问题。
  • 接收方要快。可能有多个发送方同时发过来数据。同时发送的量可能非常大,每秒需要处理数万个并发的数据包。
  • 网络或接收方暂时故障。比如服务器之间专线短期故障或者接收方程序崩溃导致不能发送。通常大家自己实现的程序没有 MySQL 或者 Memcached 那么稳定,进程挂掉是概率很高的随机事件。死掉的解决方法可用一个守护进程监测,发现死掉再次重启。那监测到死机到重启需要一个过程,发送方这段事件需要发送的数据怎么处理?
  • 如果接收方一直不起来怎么办,发送方会不会被待发送的数据撑满到内存溢出。
  • 通讯协议是自定义的,可采用定长包或变长包。如果采用变长包,接收方收到一个坏数据也没法判断这个坏数据有多长怎么办。是不是整个数据流都废了?
所以最近搞的这个东西,95%的功能上面高中生那个程序搞定了,剩下这5%的功能才让人头大。目前大部分细节已经分别处理,简单流程如下。
  • 发送方用一个连接池。那多个线程对有限的几个固定连接资源占用怎么分配?可以用发送队列,我现在是用发送线程池。
  • 接收方也启用线程池,同时配合non-blocking非阻塞io的方式。
  • 暂时失败的数据放入一个队列定时重发。同时记录发送失败的错误次数。
  • 如果接收方一直不起来,有业务需要的数据进行持久保存。
  • 对于坏数据,最简单把连接close,让发送方再次开新连接发送。
当然这里没有描述全部情况,实际需要考虑的问题比这些更复杂,并且还有不少运行期间新问题待捕捉。

类别:高性能服务器 | 添加到搜藏 | 浏览() | 评论 (3)
 
最近读者:
 
网友评论:
1
2008-10-22 09:10 | 回复
接收方也应该有一个数据处理队列,同过线程池、non-blocking非阻塞io接收过来的数据及时放到接收队列中,有另外一个数据分析与处理线程池专做处理。 对通讯协议的定长包或变长包,应该有断包、连续包、丢包、非法数据包的处理机制。
 
2
2008-12-08 10:55 | 回复
暂时失败的数据放入一个队列定时重发。同时记录发送失败的错误次数。 如果接收方一直不起来,有业务需要的数据进行持久保存。 对于坏数据,最简单把连接close,让发送方再次开新连接发送。 ---我认为这个IO错误的处理逻辑不应该由IO层来关心,而应该是出现IO错误,则上报逻辑层,逻辑层根据错误类型,数据类型选择对应的策略进行处理, 可以重发(对消息时序没有要求时),可以丢弃,可以存储等等, 欢迎讨论
 
3
2008-12-09 18:15 | 回复
@7219012 是一种不错的思路。但也要防止重发死循环,管理消息包的时间戳失效等逻辑,实现起来也有点繁琐。
 
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
验证码: 请点击后输入四位验证码,字母不区分大小写
      

     

©2009 Baidu