作者:張醫博
合理的遷移配置
目前還是推薦客戶按照 VPC 的環境方式進行遷移,在服務體驗感上有很大提升。在遷移過程中 OSS SLA 沒有承諾遷移速度有明确名額,而且遷移資料和多因素有關(機器配置、資料量、網絡、線程、限流等),是以根據實際情況進行問題診斷。
首先在遷移之前,要求使用者要先大緻的學習一下我們的配置屬性說明,和相關檔案的作用,日志存儲,異常處理等。
https://help.aliyun.com/document_detail/56990.html?spm=a2c4g.11174283.6.1079.sbu1ch配置遷移檔案單機版
遷移前要明确用戶端的遷移體量和檔案數量。目的是合理的配置 task 和線程數量,以及 ossimport 的工作模型。
- 一般遷移體量小于 30TB 的完全可以采用單機模式進行遷移,單機版可以配置多線程的方式進行遷移,調節 workerTaskThreadNum 參數,需要注意的是如果是高配,實體機的話,數量可以調大,可以參考 平均檔案 size * 線程數量,對比 memory 是否夠用,同時也要參考 CPU 核心數量是否能否抗住這種并發量。
- 當高并發,且檔案的 size 較大時,如果配置數量不合理,會出現裝置 OOM 的情況,可以通過 /var/log/message 看到,這是要麼選擇降低并發線程數量,要麼是增大機器配置。
- 如果是本地 ECS 或者第三方存儲遷移到 OSS ,請注意源是否有限流,目前經常會出現源發現有大流量流出後直接給限制住,導緻遷移速度無法增長。關鍵參數 workerMaxThroughput(KB/s),如果源沒有限制,可以釋放調大這數。
- 其他 sys.properties 檔案中的屬性不要随意改動。
配置分布式遷移檔案
- 分布式遷移模式的資料體量都是大于 30TB ,甚至上 PB 的級别才會用到,遷移模型也比較特殊,是通過 master 帶多個 worker 協同工作,類似 nginx 的模型,master 隻是用來切割任務和配置設定任務,對資料量龐大的使用者,worker 的數量也要配置好,才能高效遷移。
- 首先通過用戶端檔案數量,來計算任務數,該項目中用戶端總檔案數 424421917 個,源頭限制 3Gbps ,客戶的機器數量有 12 台。
- 計劃分成 20000 個 task ,每個 task 遷移 21221 個檔案。每個 worker 機器開 200 線程,并發處理 200 個 task ,并發也就是能處理 2400 個,更新 17600 個 task 在隊列中。
- 源流限制是 3000Mbps ,其實并發 worker 全部也就能跑到 375MB ,是以即便是你的線程開的再多,機器配置在高其他的線程也隻能阻塞住。
OSS 單機版遷移速度慢優化建議
所有優化都是基于 ECS 的基礎上,如果是自己的 PC 優化空間不大
- 如果是 OSS 遷移到 OSS 可以買 ECS 做遷移,将配置做大點,比 32G 16 核,64G 32核, 16G 8 核 等。
- 将 ECS 的 srcdomain destdomain 都設定為内網 internal 的域名。
- 如果不是 OSS 遷移到 OSS ,将配置做大點,比 32G 16 核,64G 32核, 16G 8 核 等。将 ECS 的 destdomain 設定為内網 internal 的域名。
- 将本機的遷移 heap 調大到 ECS 記憶體的 1/2 ,如果本機記憶體使用較高的請調到 1/4
- 線程數可以開到 workerTaskThreadNum=120
- 設定 workerMaxThroughput=0
OSS 分布式版遷移速度慢優化建議
- master 和 worker 機器要使用 ECS 機器進行遷移,master 機器要配置大點,如果想遷移快建議 master 64G 32核,worker 機器 32G 16 核 或者以上,數量越多越好,客戶根據自己的業務情況買,具體情況再分析。将 ECS 的 srcdomain destdomain 都設定為内網 internal 的域名。
-
如果不是 OSS 遷移到 OSS ,将配置做大點,比 32G 16 核,64G 32核, 16G 8 核 等。
将 ECS 的 destdomain 設定為内網 internal 的域名。
- 配置檔案線程數可以開到 workerTaskThreadNum=150
問題:
ossimport NullPointException
排查:

- 空指針的目前存在于低版本的 ossimport 工具中,官網的新版本已經修複,下載下傳新版本後重新開機任務程序即可解決。
- get target meta faild 是正常報錯,ossimport 會自動重試,重試如果還是失敗,最後會變成 failed success 任務,可以用 sh console.sh stat 看到,錯誤原因一般因為上傳到 OSS 檔案失敗,無法拉去 meta 資訊進行校驗導緻,可以不用關心。
ossimport 上傳 oss 逾時
通過上傳報錯即可知道 socket timeout ,基本上和網絡脫不了關系,延遲過高、丢包、網絡不通都會出現這種問題;
最有效的辦法是用戶端抓包走一波,然後通過抓包分析症結。
原檔案帶有特殊符号
出現這種錯誤,要檢查下原檔案是否存在特殊字元
, " ' \ / & <> 、? :
如果是以上帶有特殊字元的原檔案,需要經過本地先特殊字元處理掉,有些特殊字元可能在 Linux 的檔案系統中可能無法正常顯示,可能導緻 OSS 擷取原檔案失敗,最好自己将這種特殊的字元處理掉。
設定增量遷移,任務一直存在
isIncremental=true
incrementalModeInterval=86400
設定了這增量遷移參數後,如果第一次全量遷移完後,程序會一直存在,根據設定的間隔時間發起增量掃描,屬于正常現象。
LocalScanner.run Exception:java.lang.StringIndexOutOfBoundsException: String index out of range
遷移的源檔案設定了軟連結單機版的暫時不支援,分布式版本的可以支援。
如何降低 ossimport 的遷移帶寬,占用記憶體?
- 如果降低遷移帶寬或者記憶體,将導緻整體的 ossimport 遷移速度下降,耽誤遷移時間,請做好預期。
- javaHeapMaxSize , 預設是 1024 最低的堆棧配置,想要調整遷移占用記憶體可以調整堆棧大小,不能少于 1024;
- workerMaxThroughput(KB/s) ,可以控制它遷移速度,機關是 KB;
- workerTaskThreadNum,遷移線程數,預設 60 ,可以調整。
通過以上幾個參數可以降低遷移的占用帶寬和記憶體消耗。所有配置檔案都在 sys.properties 裡面;
遷移過程中,出現 NoSuckKey ,但是本地檔案存在,或者第三方存儲源檔案存在,為什麼報 404?
[2018-12-05 10:33:13] [ERROR] Oss get meta failed, bucket:single key:mpg/All Japan 3200 Database Complete/Japan Data
base/J100040.mpg Exception:com.aliyun.oss.OSSException: Not Found
[ErrorCode]: NoSuchKey
[RequestId]: 5C0738E8D06C7BFCBDFFBAC1
[HostId]: null
at com.aliyun.oss.common.utils.ExceptionFactory.createOSSException(ExceptionFactory.java:104)
at com.aliyun.oss.internal.OSSErrorResponseHandler.handle(OSSErrorResponseHandler.java:56)
at com.aliyun.oss.common.comm.ServiceClient.handleResponse(ServiceClient.java:253)
at com.aliyun.oss.common.comm.ServiceClient.sendRequestImpl(ServiceClient.java:135)
at com.aliyun.oss.common.comm.ServiceClient.sendRequest(ServiceClient.java:69)
at com.aliyun.oss.internal.OSSOperation.send(OSSOperation.java:94)
at com.aliyun.oss.internal.OSSOperation.doOperation(OSSOperation.java:156)
at com.aliyun.oss.internal.OSSObjectOperation.getObjectMetadata(OSSObjectOperation.java:398)
at com.aliyun.oss.OSSClient.getObjectMetadata(OSSClient.java:582)
at com.aliyun.oss.OSSClient.getObjectMetadata(OSSClient.java:576)
at com.aliyun.ossimport.worker.uploader.OssUploader.getMeta(OssUploader.java:374)
at com.aliyun.ossimport.worker.task.localimpl.LocalAuditTask.checkWithRetry(LocalAuditTask.java:92)
at com.aliyun.ossimport.worker.task.localimpl.LocalImportTask.audit(LocalImportTask.java:101)
at com.aliyun.ossimport.worker.task.localimpl.LocalImportTask.run(LocalImportTask.java:150)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
ossimport 的工作過程是要先将源檔案 list 出來,然後分成不同的 task 去執行,當是以任務執行完成後,再進行統計的檔案校驗比對,其方式是通過本地發起一條 http 的 header 請求到 OSS ,如果校驗通過表示上傳成功,如果校驗失敗上傳就失敗。
通過報錯可以看到是 ossimport 執行了一個 http 請求到 OSS 端,擷取了 404 的結果,這種情況隻有兩種可能:
-
遷移的資料源是 OSS,并且 OSS 上沒有這個檔案;
源檔案存在,但是遷移過程中出現了失敗任務,沒有遷移成功,在最後 ossimport 校驗時沒有請求到目标 bucket 這條 object 是以出現 404 ;