Rails 如何解决上传文件并发的问题?

gakki · 2018年03月20日 · 最后由 huacnlee 回复于 2018年03月20日 · 3979 次阅读

项目使用 Rails4,Ruby 2.3.1 我们的项目上传组件用的 Carrierwave,现在大概会有 4000 个用户同时上传文件(大概 300M 左右的大文件),怎么解决并发的问题?各位大神有什么解决方案么?

直接从客户端提交到云服务哪里,不要经过应用服务器

http://docs.upyun.com/api/form_api/

如果你可以使用 Rails 5.2 的话,可以尝试用 Active Storage,我实现的 activestorage-aliyun 已经支持直接从客户端上传文件到阿里云 OSS 了。

详见 http://edgeguides.rubyonrails.org/active_storage_overview.html#direct-uploads


然后 Carrierwave 也有 direct upload 的插件 https://github.com/dwilkie/carrierwave_direct

直传稍微有点不好的就是没办法做大小限制, 再就是有时候云服务商回调的时候有存在回调失败的情况,之后就很难处理这种回调失败的数据

如果单传图片,或者不需要处理的文件,则直连非常好使

Rei 将本帖设为了精华贴 03月20日 11:55
Rei 取消了精华贴 03月20日 11:55
huacnlee 回复

如果 server 不是阿里云呢,我们的 server 是台物理机,并且我们也切不到 Rails5...并且上传完文件我们的应用层还需要进行转换操作,需要对上传的文件进行处理,如果彻底绕开应用层开发的时间就会拉长了。。。我在想是不是能够有别的方法在应用层实现上传并发...

用 rails 来处理 4000 并发的上传,单机基本不可能.

rails 限制不能使用异步方式,所以只能用线程. 按照一个 puma 进程配置 100 个线程,至少要 40 个 puma 进程.

所以上传这一块,只能用其它的高并发语言来写. 或用 ruby ,但只需要 em 之类的异步方式,与 rails 的数据交互走 redis ,或上传成功后再调用 rails 接口.

另外一种简单的做法,使用 nginx upload module, nginx 是异步模型,所以不用担心性能问题. https://www.nginx.com/resources/wiki/modules/upload/

不过, 4000 用户同时上传,按 100Mbps 带宽来算, 一个人的上传带宽只有 25 Kbps . 300 Mbyte 的文件. (300 * 1024 * 8) / 25.6 / (60 * 60) 一个人上传 300M 差不多要 26 小时才能上传完. 改成 1000 M 带宽,也要 2.6 小时. 千 M 带宽的成本真不低吧.

你可以用单的上传进程,nginx 有上传的模块的,上传好了通知 rails 服务器

带宽够吗?

jicheng1014 回复

可以做大小限制的一般云服务都有这样的参数支持

jicheng1014 回复

你不可能靠里面自己的物理服务器来做这件事的。

最大的问题是你们的服务器带宽,例如 Ruby China 只有 5M。

5M 的概念等于同一时刻最大传输只能 5M。

上面思路都已经有了,核心就是这个量的上传文件,文件不应该经过应用服务器(不管是 Puma 还是 Nginx),否则你的应用服务器的正常功能会受到这写文件上传影响。

当然,Nginx 这样的异步 IO 没问题,但 Ruby 的应用服务器是同步 IO 的,意味着上传过程会堵塞,直到上传结束。


如果你们确实无法使用云存储服务,必须用自己的物理机来存储这些上传文件,那你可以考虑把上传服务独立部署,和应用服务器分开。

前提是服务器带宽(用户端 -> 你们的上传服务器)得够大。那种 5M 的带宽的云服务器你就别想搞了。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册