首页 > 代码库 > 文件广播的实现

文件广播的实现

商户搜索索引高达22G(压缩之后10G),而replication有17台,尽管现在索引机出口带宽高达2Gb/s,下载还要花费15~20分钟。
用广播/组播方式可以节省出口,以及公用网络带宽, 早在两年前就有做广播工具的想法(当时是ipad会议系统,需要把文件分发到每台ipad上,ipad最多有700-800台,无线网络较差),憋了一段时间设计、整理思路、实现、调试,终于出结果了,感觉蛮有收获:

https://github.com/bryanzhang/ufbp

使用上类似http/ftp由客户端主动发起pull request,服务器端对同时请求同一个uri的多个客户端做下载调度。文件使用udp广播实现(以chunk为单位,一个chunk为60K),客户端请求,服务器端返回,以及客户端定时发送的已传确认包使用tcp。这样在较可靠的网络中,同时发起的请求可以共享文件数据,从而节省带宽。

在192.168.5.x的局域网内测试下载19G的索引,单台客户端下载带宽为188MBps,约3分10秒下载完,客户端增加到3台,3分25秒全部下载完(单台客户端下载带宽约170MBps)。对照nginx,单台客户端下载时约为100MBps,两台客户端同时下载花费6分5秒完成,平均到单台的下载带宽为62.7MBps(哈哈,写个服务器性能超过nginx真是爽啊:)

整个代码就1500行,服务器使用epoll(水平触发)单线程实现。这里面最有意思的就是调度器的算法,刚开始想对每个块都做优先级排序,后来想想块非常多,如果要完全用优先级,内存中的结构很大,关闭连接时的操作代价也很高。所以采用一种代价较低的公平调度方式,每次找最早收到ack的连接,先看waitforack队列是不是满的,如果满了,要发送其中不在那个uri的recentSendChunks的包,如果没满,chunkpos游标继续在文件中向前,总是不发送在recentSendChunks的包(近两秒该uri对应文件的包),可以尽量不重复发送。

广播对整体网络影响较大,改用组播达到的效果应该类似,但是不会全网传送。后来和老大、运帷讨论了一下,组播配置比较麻烦,升级出口网卡到万兆网卡,使用光线连接核心备板,只要花五六千块钱!不过写这个程序真是很有收获的尝试, 顶自己!

有不少可以改进的地方,因为公司暂时不需要这个好东西了一段时间内不会投入精力在上面,先列出来:
1.如果找不到可以调度的包(uri中所有数据都发完了,但未收到完整确认),要继续发送待确认数据,这样传输小文件不会浪费时间
2.uri请求建立起来之后,要清空该uri下的recentSendChunks
3.waitforack队列可以设大一点,如有必要的话
4.epoll中没有请求的时候,把udp OUT监听关闭,避免cpu 100%的问题
5.log可以整理更清楚一点(如使用glogs),甚至可以内潜一个打印状态的socket,看看性能瓶颈在哪里
6.组播实现,config用gflags

文件广播的实现