系统中,用户的消息在移动设备与接入服务器建立的Tcp长连接上传递。这些消息包括:文本,复合文本,位置信息,音频剪辑,图像等等。
发送者传送消息到平台系统内部并将消息写入gridfs,待接收者上线时平台将消息推送至接收者。
考虑到带宽利用,接收者得到的消息将不包含二进制数据,例如: 音频,图像等等。 这要求接收者对平台发起一次获取消息包内指定的音频和图像数据的请求。
移动端向平台请求二进制数据的情况还包含 【离线文件传送】场景 。
二进制数据往往是指那些数据量比较大的对象,这些对象在移动两端交换时,交互通道将不占用与接入服务器的连接通道,而是通过nginx传送到平台内部; 同样接收者获取二进制数据也是通过nginx获取。这种请求是HTTP的。
这里整理的是如何在平台部署 【负载均衡的集群的分布式的文件服务】
nginx : http服务,提供反向代理和负载均衡服务(集群可用DNS或考虑LVS方案)
mongodb+gridfs : 用于文件服务提供,其内置gridfs提供了分布式,海量存储的方案
gevent+webpy : nginx直接读取gridfs是不合适的,配置了cgi才能完成特定功能,这里使用webpy,比django更轻更好用。
webpy的作用是接收到上传和下传文件的请求,读写gridfs文件内容给移动端。
gevent是高效的通信框架,虽然单线程工作,但性能非常的好;
用好gevent关键在与外部的io必须全部都是异步的,例如: 数据库,文件磁盘访问等等。
mongodb对gevent已经支持,gevent对webpy,django,psycopg2支持也相当的好,所以要提供webservice服务那就考虑用gevent+webpy或django把,性能是杠杠的,比 apache+mod_wsgi要好很多 ,而且gevent是进程内的不同的HTTP REQUEST可以是共享数据的,这一点非常诱惑(apache+mod_wsgi的REQUEST可是隔离的哦!除非您通过redis的PUB/SUB实现两个REQUEST的通信)
关注的问题:
1.下传大文件时的处理
如果直接用nginx当然没有这个问题 ,但用webpy读取文件返回HttpResponse时问题来了,总不至于读取整个文件,然后再return。
这种方式在php有flush方法,python只能用yield来做
2.上传大文件时的处理
当接收到http的文件POST请求时,文件已经全部缓存到web服务器,如果同时几千个文件上传在进行,服务器就会被挤爆,这也是很多网站不允许大文件上传的缘故吧。关于这个问题,我想就需要修改一下webpy关于文件上传的处理代码了,将接收到的文件数据以流的形式写入到gridfs里去作为临时文件被缓存,等完全接收文件时,才通知到handler代码,这样必定高效很多(新的问题又来了,会不会把gridfs搞爆掉! 处理时考虑延时缓存提交gridfs把)。
BUF_SIZE = 262144
class download:
def GET(self):
file_name = 'file_name'
file_path = os.path.join('file_path', file_name)
f = None
try:
f = open(file_path, "rb")
webpy.header('Content-Type','application/octet-stream')
webpy.header('Content-disposition', 'attachment; filename=%s.dat' % file_name)
while True:
c = f.read(BUF_SIZE)
if c:
yield c
else:
break
except Exception, e:
print e
yield 'Error'
finally:
if f:
f.close()
links:
http://api.mongodb.org/python
http://webpy.org/cookbook/storeupload.zh-cn
http://webpy.org/cookbook/streaming_large_files
http://gevent.org 下份代码 demo很值得看哦 gevent 1.0 由libev 替换了libevent