1 背景前端
用戶本地有一份txt或者csv文件,不管是從業務數據庫導出、仍是其餘途徑獲取,當須要使用螞蟻的大數據分析工具進行數據加工、挖掘和共創應用的時候,首先要將本地文件上傳至ODPS,普通的小文件經過瀏覽器上傳至服務器,作一層中轉即可以實現,但當這份文件很是大到了10GB級別,咱們就須要思考另外一種形式的技術方案了,也就是本文要闡述的方案。web
技術要求主要有如下幾方面:數據庫
支持超大數據量、10G級別以上後端
穩定性:除網絡異常狀況100%成功api
準確性:數據無丟失,讀寫準確性100%瀏覽器
效率:1G文件分鐘級、10G文件小時級緩存
體驗:實時進度感知、網絡異常斷點續傳、定製字符特殊處理安全
2 文件上傳選型服務器
文件上傳至ODPS基本思路是先文件上傳至某中轉區域存儲,而後同步至ODPS,根據存儲介質能夠分爲兩類,一類是應用服務器磁盤,另外一類類是中間介質,OSS做爲阿里雲推薦的海量、安全低成本雲存儲服務,而且有豐富的API支持,成爲中間介質的首選。而文件上傳至OSS又分爲web直傳和sdk上傳兩種方案,所以上傳方案有以下三種,詳細優缺點對好比下:網絡
螞蟻的文本上傳功能演進過程當中對第一種、第二種方案均有實踐,缺點比較明顯,如上表所述,不知足業務需求,所以大文件上傳終極方案是方案三。
3 總體方案
如下是方案三的總體過程示意圖。
請求步驟以下:
用戶嚮應用服務器取到上傳policy和回調設置。
應用服務器返回上傳policy和回調。
用戶直接向OSS發送文件上傳請求。
等文件數據上傳完,OSS給用戶Response前,OSS會根據用戶的回調設置,請求用戶的服務器。若是應用服務器返回成功,那麼就返回用戶成功,若是應用服務器返回失敗,那麼OSS也返回給用戶失敗。這樣確保了用戶上傳成功,應用服務器已經收到通知了。
應用服務器給OSS返回。
OSS將應用服務器返回的內容返回給用戶。
啓動後臺同步引擎執行oss到odps的數據同步。
同步實時進度返回返回給應用服務器,同時展現給用戶。
4 技術方案
4.1 上傳
OSS提供了豐富的SDK,有簡單上傳、表單上傳、斷點續傳等等,對於超大文件提供的上傳功能建議採用斷點續傳方式,優勢是能夠對大文件並行分片上傳,利用OSS的並行處理能力,中間暫停也能夠從當前位置繼續上傳,網絡環境影響能夠降到最低。
4.2 下載
OSS文件下載一樣也有多種方式,普通下載、流式下載、斷點續傳下載、範圍下載等等,若直接下載到本地一樣建議斷點續傳下載,但咱們的需求並不只僅是下載文件本地存儲,而是讀取文件作數據從OSS到ODPS的同步,所以不作中間存儲,直接邊讀變寫,一方面採用OSS流式讀取,一方面ODPS tunnel上傳,用多線程讀寫方式提升同步速率。
4.3 兩階段數據轉移
文件從本地到ODPS能夠分爲兩個階段,第一階段前端分片段點續傳將本地文件上傳至OSS,第二階段後端流式讀寫將數據從OSS同步至ODPS,以下圖所示:
涉及技術點:
4.3.1 前端,js sdk帶STS token 安全上傳
在須要上傳的文件較大時,能夠經過multipartUpload接口進行分片上傳。分片上傳的好處是將一個大請求分紅多個小請求來執行,這樣當其中一些請求失敗後,不須要從新上傳整個文件,而只須要上傳失敗的分片就能夠了。通常對於大於100MB的文件,建議採用分片上傳的方法,每次進行分片上傳都建議從新new一個新的OSS實例。
阿里雲分片上傳流程主要會調用3個api,包含
InitiateMultipartUpload, 分片任務初始化接口。
UploadPart, 單獨的分片上傳接口。
CompleteMultipartUpload, 分片上傳完成後任務完成接口
臨時訪問憑證是經過阿里雲Security Token Service(STS)來實現受權的一種方式。其實現請參見STS Java SDK。臨時訪問憑證的流程以下:
客戶端向服務器端發起得到受權的請求。服務器端先驗證客戶端的合法性。若是是合法客戶端,那麼服務器端會使用本身的AccessKey來向STS發起一個請求受權的請求,具體能夠參考訪問控制。
服務器端獲取臨時憑證以後返回給客戶端。
客戶端使用獲取的臨時憑證來發起向OSS的上傳請求,更詳細的請求構造能夠參考臨時受權訪問。客戶端能夠緩存該憑證用來上傳,直到憑證失效再向服務器端請求新的憑證。
4.3.2 後端,多線程流式讀寫
OSS端:若是要下載的文件太大,或者一次性下載耗時太長,能夠多線程流式下載,一次處理部份內容,直到完成文件的下載。
ODPS端:tunnel sdk對OSS流式數據直接寫入,一次完整的數據寫入流程一般包括如下步驟:
先對數據進行劃分;
爲每一個數據塊指定 block id,即調用 openRecordWriter(id);
而後用一個或多個線程分別將這些 block 上傳上去, 並在某個 block 上傳失敗之後,須要對整個 block 進行重傳;
在全部 block 都上傳之後,向服務端提供上傳成功的 blockid list 進行校驗,即調用 session.commit([1,2,3,…])
而因爲服務端對block管理,鏈接超時等的一些限制,上傳過程邏輯變得比較複雜,爲了簡化上傳過程,SDK提供了更高級的一種RecordWriter——TunnelBufferWriter。
5 實現過程及壓測
太多了,能夠參考我寫的這篇文章:http://blog.ncmem.com/wordpress/2019/08/09/%e5%a4%a7%e6%96%87%e4%bb%b6%e4%b8%8a%e4%bc%a0%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88/
6 總結
實測結果顯示,本文的上傳方案實現了第一節提出的幾點技術要求,以下:
支持超大數據量、10G級別以上沒有任何壓力,主要是前端在分片上傳設置好分片限額便可(最大10000片,每片最大100G),目前設置每片1M知足10G需求。
穩定性:實測觀察網絡異常狀況較少,文件內容正常狀況下100%成功。
準確性:實測數據無丟失,讀寫準確性100%。
效率:辦公網帶寬1.5M/s的狀況下1G文件分鐘級、10G文件小時級,實際速度視用戶端的當前網絡帶寬變化。
體驗:實時進度感知、網絡異常斷點續傳、定製字符特殊處理等高級功能能夠提高用戶體驗。
做者:谷壹連接:https://www.jianshu.com/p/8b2756a2ec60來源:簡書簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。