Fd779852eb8e519999f8b35c47777608

請教理想的圖片處理方式

2012-01-23 22:35:39 +0800chiayiRuby 節點 中發起
最後由 chiayi2012-07-14 20:06:06 +0800回應 , 738次閱讀

目前使用paperclip來處理圖片的縮圖
client端用swfupload來上傳,可以顯示進度
圖片存在amazon s3
為了不讓paperclip縮圖動作影響到UI,我用delayed_paperclip把縮圖的工作丟到背景去執行
即便如此,仍然覺得速度不是很理想
如果上傳圖片150k的話,縮成6個尺寸,大概要花7~8秒
如果圖片是2M的話,大概要花20~60秒
以上是在本機測試

如果很多使用者同時上傳圖片,不知會不會造成系統掛掉
看速度是挺危險的
請問各位有沒有好方法可以改善呢
謝謝

截至 2012-07-14 20:06:06 +0800,共收到 18 條回應
19e786a2a74377ff6e052d87fd8d1fa8
xdite 1樓, 於2012-01-24 02:09:21 +0800回應

壓圖機拆到別台去作如何?另外看起來壓圖速度也不是很理想,你是放在 linode 上嗎?

Fd779852eb8e519999f8b35c47777608
chiayi 2樓, 於2012-01-26 03:37:47 +0800回應

我是在本機測的,看來除了把圖片處理到另一台機器也很難解決問題
想到要做負載平衡頭就有點痛
另外,我想先測可不可以用javascript直接上傳到flickr api,讓flickr去處理
便宜又大碗

19e786a2a74377ff6e052d87fd8d1fa8
xdite 3樓, 於2012-01-26 03:38:58 +0800回應

你應該會被 ban 掉 ...XDXD

94575b73a05d48e567423d7d6ca8273c
devpoga 4樓, 於2012-01-26 19:23:51 +0800回應

7~8秒是包含上傳到s3?

Fd779852eb8e519999f8b35c47777608
chiayi 5樓, 於2012-01-26 20:22:17 +0800回應

@devpoga
是的,怎麼覺得s3速度不優,我沒仔細去研究是不是因為免費帳戶的關係。

94575b73a05d48e567423d7d6ca8273c
devpoga 6樓, 於2012-01-27 01:11:59 +0800回應

s3速度一直都不是很快... 換到sg或是jp的S3看看?

Fd779852eb8e519999f8b35c47777608
chiayi 7樓, 於2012-06-08 11:54:28 +0800回應

由於project主要都是圖,user會大量上傳圖片,如果background沒有足夠的instance的話,會變得大家都在排隊,每個instance又佔120MB左右,坦白說同時間一個user在上傳至少要3個background job專門在處理縮圖,如果10個user同時都在上傳就要30個bakcground job,而且速度也不是說很快,只是可接受而已。
今詢問一個朋友用nodejs,他說background job nodejs instance大概佔10MB,所以,我打算試看看把縮圖交給nodejs去做,不然太燒錢了。

Cb6ee60e6dfdc5de6db0908ea52446d4
nouse 8樓, 於2012-06-23 19:13:47 +0800回應

壓圖最好用image_science,消耗的CPU和Memory比較少,可以同時多開幾個進程。

Fd779852eb8e519999f8b35c47777608
chiayi 9樓, 於2012-07-12 11:59:10 +0800回應

我後來用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,說不定也是個好解
參考看看

2a01ae9942939ee2b3954a6727d2bb92
tonytonyjan 10樓, 於2012-07-13 09:34:44 +0800回應

看到第二點,我使用 carrierwave + amazon s3 時,因為傳大檔導致連線時間過長,所以自己改寫成先上傳到 s3 再下載下來處理,想不到 paperclip 也這麼做嗎XD

009994c3985985809d2d644bd49aa1c2
lulalala 11樓, 於2012-07-13 09:43:51 +0800回應

剛剛從 wikipedia 看到有特定設計來作圖形處理的 image processing server,感覺 http://github.com/kristopolous/apophnia 還不錯,只不過有點久沒更新了。

Fd779852eb8e519999f8b35c47777608
chiayi 12樓, 於2012-07-13 10:47:25 +0800回應

@tonytonyian, 先傳至s3再下載回server不是浪費流量,又多花一段時間?client在上傳至server時會先放在/tmp下,所以直接去/tmp下取得cache file直接縮圖,應該是最快的方式。至於大檔應該都還是會先放在/tmp下,等全收到後再上傳至s3,所以這樣就多一個步驟了。

補充一下,Production我是用nginx+unicorn,所以必須在nginx把上傳的網址指向node.js web server,這樣只要是上傳的動作,nginx就會轉向node.js不會丟給rails了。

454dcacc6b66e1ea03430a65feff7398
Psi 13樓, 於2012-07-13 12:16:11 +0800回應

@chiayi 可否分享一下 Node.js 的技術構成?比如採用了什麼圖片處理的模塊?文件上傳的 server 採用什麼進行?(我之前測試了一下採用 Express 作爲 server 上傳大文件會導致 node memory暴增)

Fd779852eb8e519999f8b35c47777608
chiayi 14樓, 於2012-07-13 14:22:39 +0800回應

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。

遇到什麼問題再跟我說吧:)

454dcacc6b66e1ea03430a65feff7398
Psi 15樓, 於2012-07-13 15:26:30 +0800回應

#14樓 @chiayi 感谢回答 :)

2a01ae9942939ee2b3954a6727d2bb92
tonytonyjan 16樓, 於2012-07-14 02:34:11 +0800回應

#14樓 @chiayi 之所以會有這種解是因為我放在 heroku 上面啊Orz

888339de9e7a88688b6acb30d33e66cd
elct9620 17樓, 於2012-07-14 13:00:01 +0800回應

Heroku 不是有 /tmp 可以寫入,不過大小未知~
http://devcenter.heroku.com/articles/read-only-filesystem

Fd779852eb8e519999f8b35c47777608
chiayi 18樓, 於2012-07-14 20:06:06 +0800回應

@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...)

需要 登入 後方可回應,如果你還沒有帳號按這裡 註冊