請教理想的圖片處理方式
目前使用paperclip來處理圖片的縮圖
client端用swfupload來上傳,可以顯示進度
圖片存在amazon s3
為了不讓paperclip縮圖動作影響到UI,我用delayed_paperclip把縮圖的工作丟到背景去執行
即便如此,仍然覺得速度不是很理想
如果上傳圖片150k的話,縮成6個尺寸,大概要花7~8秒
如果圖片是2M的話,大概要花20~60秒
以上是在本機測試
如果很多使用者同時上傳圖片,不知會不會造成系統掛掉
看速度是挺危險的
請問各位有沒有好方法可以改善呢
謝謝
壓圖機拆到別台去作如何?另外看起來壓圖速度也不是很理想,你是放在 linode 上嗎?
我是在本機測的,看來除了把圖片處理到另一台機器也很難解決問題
想到要做負載平衡頭就有點痛
另外,我想先測可不可以用javascript直接上傳到flickr api,讓flickr去處理
便宜又大碗
你應該會被 ban 掉 ...XDXD
7~8秒是包含上傳到s3?
s3速度一直都不是很快... 換到sg或是jp的S3看看?
由於project主要都是圖,user會大量上傳圖片,如果background沒有足夠的instance的話,會變得大家都在排隊,每個instance又佔120MB左右,坦白說同時間一個user在上傳至少要3個background job專門在處理縮圖,如果10個user同時都在上傳就要30個bakcground job,而且速度也不是說很快,只是可接受而已。
今詢問一個朋友用nodejs,他說background job nodejs instance大概佔10MB,所以,我打算試看看把縮圖交給nodejs去做,不然太燒錢了。
壓圖最好用image_science,消耗的CPU和Memory比較少,可以同時多開幾個進程。
我後來用node.js實作,不用丟到background job速度就很快,大概速度跟flickr上傳的速度差不多,上傳完就縮完,速度為什麼差這麼多,幾點感想:
1. background job原本可能是I/O過多的job或與遠端server溝通的job,放在rails完全不合適,除非資金很多,可以投很多錢在買大memory的VPS,但即使如此,速度仍不及non-blocking。
2. paperclip在處理uploader上傳時是先把原檔存在s3後,再下載回server縮圖,這點我不確定,之前是觀察s3的行為時看到,但沒去查paperclip source code。
3. 縮圖次序依原始檔縮成大圖,再用大圖縮中圖,用中圖縮小圖,最好不要都用原圖縮圖。
4. 每張圖縮完就可以上傳至s3,不須等全部縮完才傳。
事實上,縮圖的動作並不會佔用太大的cpu資源,而且很快。如果想再更快,可以配置一塊memory出來,縮圖都在memory做,但我在disk上做就很快了,就沒去弄memory。
最後實作出來的結果,一個node.js instance可以抵超過5個以上rails instance的速度,而且它不用丟到background job做,使用者經驗比較好,大概佔實體memory在10M~30M左右。
background job可以參考beanstalkd,雖然很陽春,但很快,它的相關gem沒resque多,有點可惜,我覺得它是個不錯的open source,因為它很陽春,很多動作它不直接支援,例如想砍掉某種工作,要自已寫script去刪掉,原本在ruby寫,但太慢,這工作放在ruby不合適,我又用node.js去做,同樣輕量快速就完成,因為有時我會砍上百個或千個以上的工作(相依性)。
由於我不會用ruby event machine,說不定也是個好解
參考看看
看到第二點,我使用 carrierwave + amazon s3 時,因為傳大檔導致連線時間過長,所以自己改寫成先上傳到 s3 再下載下來處理,想不到 paperclip 也這麼做嗎XD
剛剛從 wikipedia 看到有特定設計來作圖形處理的 image processing server,感覺 http://github.com/kristopolous/apophnia 還不錯,只不過有點久沒更新了。
@tonytonyian, 先傳至s3再下載回server不是浪費流量,又多花一段時間?client在上傳至server時會先放在/tmp下,所以直接去/tmp下取得cache file直接縮圖,應該是最快的方式。至於大檔應該都還是會先放在/tmp下,等全收到後再上傳至s3,所以這樣就多一個步驟了。
補充一下,Production我是用nginx+unicorn,所以必須在nginx把上傳的網址指向node.js web server,這樣只要是上傳的動作,nginx就會轉向node.js不會丟給rails了。
hi @Psi,
如果原本client端上傳已經寫好就不用動,只要寫node.js去接就行了,如果時間允許或是尚沒有實作client端的話,我會推薦用看看http://github.com/blueimp/jQuery-File-Upload , 不要用YUI 2.X的,因為當server端有錯誤時,它無法接收exception,YUI 3.X有實作,但又有其它問題,其它SWFUploader忘了有啥限制,不推薦。
http://github.com/rsms/node-imagemagick 我是用這個處理縮圖
http://github.com/dosx/node-vips 有評比指出vips的速度和memory都是最佳,有興趣可以玩玩
http://github.com/LearnBoost/knox 上傳至s3
用express接收後,console.log印出req所有內容就知道所有內容,包含cahce file路徑或是在上傳時有post其它parameters都可以取得,有這些資料,其餘只需看imagemagick和knox文件就做得出來。
imagemagick不像paperclip這麼容易使用,但你可以控制轉檔順序和各轉檔後的檔案存放位置。
memory暴增問題,坦白說我只做很簡單的事,連express doc都沒看,你可以去問看看node.js的developer。
遇到什麼問題再跟我說吧:)
Heroku 不是有 /tmp 可以寫入,不過大小未知~
http://devcenter.heroku.com/articles/read-only-filesystem
@tonytonyjan, 坦白說,租個linode512就可以跑node.js。通常建議node.js instance數是依cpu核心個數而定,我沒實際去跑benchmark,只有很粗略的測試,是可以多跑些instance加快許多,細節就不談。linode 512是4核心,我加倍給它設定8個node.js instance,每個月繳個$600擁有高速轉檔效能,是覺得很划得來啦,相較於heroku,會覺得有點綁手綁腳。
另外,不確定Heroku worker dynos可不可以跑beanstalkd jobs,如果可行的話,可以動態關掉一些worker dynos節省荷包,這樣有可能在荷包和效能中取最佳解。當然,如果/tmp無法存取的話,那就不適合採用Heroku了。
或是你可以把縮圖的動作另外架台server在linode就可解決,在nginx做設定就行。(怎麼好像一直勸你離開Heroku, haha...)