摘要:原文服務器端文件分片合并的思考和實踐筆者在項目中處理大文件上傳的需求,仿照七牛云存儲的接口設計。然而,在服務器端文件合并時遇到了很大的問題合并太慢。服務器端的分片合并現在進入本文的重點。
原文:服務器端文件分片合并的思考和實踐
筆者在項目中處理大文件上傳的需求,仿照七牛云存儲的接口設計。然而,在服務器端文件合并時遇到了很大的問題:合并太慢。本文記錄了當時的思路和解決的方案
大文件的需求文件上傳是個很常見的需求。盡管HTTP是基于TCP上層的協議,但是HTTP協議本身并不適合處理超大的請求體,文件上傳有很大的穩定性問題,如果中途斷開了,將前功盡棄。為了改善用戶體驗或者緩解服務器壓力,通常會考慮將文件分成小片,將小片一個個上傳,如果中途斷開了也能從某個失敗的小片開始繼續上傳。
在前端的處理上,對于Web頁面,可以采用plupload作為上傳組件,該組件支持html5、flash、sl等多種上傳方式,因此,可以提供較好的瀏覽器兼容性。七牛云存儲的js-sdk就是基于這個組件開發的。不過本文的重點并不是討論前端技術,關于前端就到此為止。
服務器端的策略既然文件被分成片上傳,那么自然在服務器端需要將分片合并成原始的文件,那么這里存在兩種策略
邊傳邊合并:每上傳一個分片,就將分片合并到文件的后面
傳完一起合并:先將分片保存起來,客戶端發起一個合并請求時,再將分片合并成一個文件
邊傳邊合并這種方式要注意:
由于HTTP的無狀態性,這種方式需要客戶端和服務器端維持一個標識。服務器端根據標識,才能知道分片應該向哪個目標文件Append
如果客戶端中途停止上傳,那么保存在服務器上的目標文件將成為垃圾文件,文件即不能被刪除又沒有利用價值。因為服務端無法知道文件究竟的完成狀態還是正在進行狀態
由于分片直接合并進了文件,無法管理分片
傳完一起合并七牛云存儲就是使用的這種策略,具體的實現方式如下:
每上傳一個分片,服務端將分片保存下來,并返回客戶端一個唯一標識ctx,這個標識ctx與當前這個分片關聯
客戶端應當妥善保存每個分片的標識,以及它們的先后順序
服務端需要提供一個接口,客戶端用這個接口請求分片合并,在請求時候將標識按順序告知服務端,ctx0,ctx1,ctx2...
服務端根據標識的順序找到對應的分片,并合并成完成的文件
這種設計解決了客戶端中途停止上傳帶來的服務器端資源的浪費,因為分片都是正在進行態,可以對時間很早的分片進行清理。而且分片被記錄了下來,容易對分片進行一些管理。
服務器端的分片合并現在進入本文的重點。文件合并是IO操作,IO操作是最耗時的工作了。上文的第一種策略,有一個好處是文件的合并是在上傳的過程中完成的,對于用戶來說幾乎感知不到文件Append時的延時。然而,第二種策略的文件合并卻是在一個時刻同時進行的。筆者測試過,即使是4-5個4MB的分片,也會使客戶端有明顯的延遲感。如果分片再多的話,延遲將更大,甚至請求超時,這是不能接受的。
但是筆者在七牛云上的測試,合并的請求在七牛的服務器端幾乎沒有延時。為此,筆者還發了一問:七牛云mkfile如何實現將大量的文件chunk快速合并的,但是七牛的技術太“吝嗇”,一點也不透露。那該怎么辦呢?
并行處理?由于是將分片合并,那么很容易會想到并行。類似歸并排序的思想,將合并任務分開,然后通過集群服務器的協調完成合并。但是筆者對這方面是知之甚少,而且這種方案會使原本簡單的架構變的異常復雜,不敢采用這種方案。而且感覺會有坑:
并行處理往往是異步的,如何處理好與web服務器的同步
再怎么分任務,合并終究是IO操作,IO操作總是要耗費時間的
文件系統底層處理?仔細思考合并這個動作,實際上是將多個文件在文件系統里面復制了一次,而文件的內容并沒有任何的變化。如果能夠在文件系統層面將分片直接連接起來話,合并文件僅僅是修改一些指針,速度將十分的快。不過文件系統各不相同,能不能實現還需要看。而且,由于筆者使用nfs作為數據存儲,nfs的文件讀寫完全是通過接口提供的,接口也不提供底層的文件系統操作,所以似乎是無法實現。
為什么非要合并!再思考下去,如果文件系統無法做到將分片直接連接起來的的話,那么從用戶接口層(HTTP)是否能做到呢?試想,通過HTTP的方式提供文件的訪問,如果HTTP服務器能夠知道這個文件是由多個小文件按何種順序組成的,那么就可以按照順序將分片依次放在同一個HTTP流中返回,對用戶來說一次請求還是得到一個文件,好像文件是合并好的一樣,但實際上文件在文件系統并不存在。
這樣做需要多帶帶將分片的順序維護好,每次都要讀出分片的順序和位置,然后依次一個個寫入HTTP流中。但是高層的Web編程框架似乎無法支持這種做法。
巧用Nginx避免文件合并筆者立刻想到了之前用過的Nginx模塊mod_zip,這個模塊能夠將多個文件打包以zip流的方式返回。現在的需求其實跟這個模塊的工作幾乎差不多,甚至還要更簡單。苦苦尋覓網上的Nginx模塊,似乎沒有找到筆者需要的,于是決定自己基于mod_zip開發一個。幸好,之前用mod_zip的時候看過一些源碼。
目前這個模塊筆者命名為mod_pieces,已經開發完成并在windows和linux兩個平臺下測試通過,唯一不好的是無法支持HTTP Range,HTTP Range有點難弄,以后可能有時間再慢慢實現。代碼還沒有整理,有時間放到Github上去共享。
mod_pieces的工作方式和原理和mod_zip很相似,有進一步需求的讀者可以移步至:利用Nginx第三方模塊,實現附件打包下載
后續還是要合并的現在用戶那頭可以"欺騙"成功了,但是如果系統本身需要對文件進一步處理,比如視頻的格式轉換,那么還是需要將文件合并起來的,不過這個時候就可以用一個后臺的服務異步的慢慢做了,用戶不會感知。基于這些復雜的問題,筆者已經把文件上傳下載和處理作為的一個全新的產品功能獨立出來,以支持主產品對文件的各種功能需求。
后記本文沒有一張圖片,沒有一行代碼,有些不適應。文字雖短,但是這些東西都是經過筆者的實踐并且有感而發,希望有個總結,并能夠帶來更多的交流。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/39088.html
摘要:感受構建工具給前端優化工作帶來的便利。多多益處邏輯清晰,程序注重數據與表現分離,可讀性強,利于規避和排查問題構建工具層出不窮。其實工具都能滿足需求,關鍵是看怎么用,工具的使用背后是對前端性能優化的理解程度。 這篇主要介紹一下我在玩Webpack過程中的心得。通過實例介紹WebPack的安裝,插件使用及加載策略。感受構建工具給前端優化工作帶來的便利。 showImg(https://se...
摘要:,在后續測試時遇到一個詭異,當文件過大時,任務腳本上傳到七牛云失敗。當我遇到大文件無法上傳到七牛云時,斷點調試到這里,發現返回的是。后來還真被我找到了,七牛云官方提供一個腳本工具。 業務場景 需求 我們項目有一個文件上傳需求,需要從客戶端上傳到七牛云的對象存儲和自己的應用服務器上。這里使用七牛云主要是實現下載分發。應用服務器需要留一份是因為后續需要做文件分析(并且是上傳后需要立馬分析出...
摘要:在年推出了為云主機磁盤提供持續數據保護的數據方舟產品,支持最小精確到秒級的恢復,針對數據刪除或者丟失事件,能夠最大程度的挽回數據。為此我們推出了磁盤快照服務,基于數據方舟技術并進一步升級,以更低的成本為全系列云盤普通提供了數據備份功能。UCloud在2015年推出了為云主機磁盤提供持續數據保護(CDP)的數據方舟(UDataArk)產品,支持最小精確到秒級的恢復,針對數據刪除或者丟失事件,能...
摘要:在年推出了為云主機磁盤提供持續數據保護的數據方舟產品,支持最小精確到秒級的恢復,針對數據刪除或者丟失事件,能夠最大程度的挽回數據。為此我們推出了磁盤快照服務,基于數據方舟技術并進一步升級,以更低的成本為全系列云盤普通提供了數據備份功能。UCloud在2015年推出了為云主機磁盤提供持續數據保護(CDP)的數據方舟(UDataArk)產品,支持最小精確到秒級的恢復,針對數據刪除或者丟失事件,能...
閱讀 1025·2021-09-26 09:55
閱讀 3565·2021-09-24 10:30
閱讀 1368·2021-09-08 09:36
閱讀 2556·2021-09-07 09:58
閱讀 606·2019-08-30 15:56
閱讀 773·2019-08-29 18:32
閱讀 3614·2019-08-29 15:13
閱讀 1844·2019-08-29 13:49