oss多线程 上传_解读阿里云oss-android/ios-sdk 断点续传(多线程)
摘要: oss sdk 斷點(diǎn)續(xù)傳功能使用及其相關(guān)原理
前言
移動(dòng)端現(xiàn)狀
隨著移動(dòng)端設(shè)備的硬件水平的不斷提高,如今的cpu,內(nèi)存等方面都大大的超過(guò)了一般的pc電腦,因此在現(xiàn)今的程序中,合理的使用多線程去完成一些事情是非常有必要的。
多線程上傳的好處
進(jìn)一步占滿網(wǎng)絡(luò)資源。
進(jìn)一步占滿I/O資源。
實(shí)現(xiàn)原理
策略
oss有分片上傳的功能,阿里云斷點(diǎn)續(xù)傳就是基于分片上傳的幾個(gè)api接口進(jìn)行的封裝,主要由InitiateMultipartUpload,UploadPart,CompleteMultipartUpload,AbortMultipartUpload,ListParts這幾個(gè)組成。
流程
細(xì)節(jié)
斷點(diǎn)續(xù)傳是一個(gè)大任務(wù),又3部分來(lái)完成,分別是獲取uploadId,分片上傳,完成上傳,這一整個(gè)連續(xù)的步驟統(tǒng)一在一個(gè)線程中進(jìn)行。
獲取uploadId這塊需要先對(duì)本地緩存文件進(jìn)行獲取,如未拿到,就會(huì)直接重新生成新的uploadId直接去進(jìn)行分片上傳,否則會(huì)對(duì)記錄的id進(jìn)行之前上傳了多少片進(jìn)行還原,繼續(xù)原來(lái)的位置繼續(xù)上傳。
分片上傳部分,采用多線程并發(fā)上傳機(jī)制,目前線程開(kāi)啟數(shù)量最多5條,根據(jù)cpu的核數(shù)進(jìn)行判斷,如果核數(shù)<5 會(huì)采用核數(shù)進(jìn)行配置, 分片的個(gè)數(shù)最多5000。
完成上傳,對(duì)上傳的part進(jìn)行排序,需要按照自然順序1~n 的順序進(jìn)行上傳。
文件校驗(yàn),通過(guò)文件的md5等其他信息進(jìn)行校驗(yàn),分片上傳中每一片也會(huì)跟服務(wù)器做md5校驗(yàn)。
進(jìn)度回調(diào)機(jī)制,目前進(jìn)度回調(diào)算是最基礎(chǔ)版,目前回調(diào)原理是根據(jù)每一個(gè)分片來(lái)回調(diào)的,即當(dāng)分片上傳成功回調(diào)一次。
使用方式
在本地持久保存斷點(diǎn)記錄的調(diào)用方式:
android:
String recordDirectory = Environment.getExternalStorageDirectory().getAbsolutePath() + "/oss_record/";
File recordDir = new File(recordDirectory);
// 要保證目錄存在,如果不存在則主動(dòng)創(chuàng)建
if (!recordDir.exists()) {
recordDir.mkdirs();
}
// 創(chuàng)建斷點(diǎn)上傳請(qǐng)求,參數(shù)中給出斷點(diǎn)記錄文件的保存位置,需是一個(gè)文件夾的絕對(duì)路徑
ResumableUploadRequest request
= new ResumableUploadRequest("", "", "", recordDirectory);
// 設(shè)置上傳過(guò)程回調(diào)
request.setProgressCallback(new OSSProgressCallback() {
@Override
public void onProgress(ResumableUploadRequest request
, long currentSize, long totalSize) {
Log.d("resumableUpload", "currentSize: " + currentSize + " totalSize: " + totalSize);
}
});
OSSAsyncTask resumableTask = oss.asyncResumableUpload(request
, new OSSCompletedCallback() {
@Override
public void onSuccess(ResumableUploadRequest request, ResumableUploadResult result) {
Log.d("resumableUpload", "success!");
}
@Override
public void onFailure(ResumableUploadRequest request, ClientException clientExcepion
, ServiceException serviceException) {
// 異常處理
}
});
ios:
// 獲得UploadId進(jìn)行上傳,如果任務(wù)失敗并且可以續(xù)傳,利用同一個(gè)UploadId可以上傳同一文件到同一個(gè)OSS上的存儲(chǔ)對(duì)象
OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];
resumableUpload.bucketName = ;
resumableUpload.objectKey = ;
resumableUpload.partSize = 1024 * 1024;
resumableUpload.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);
};
resumableUpload.uploadingFileURL = [NSURL fileURLWithPath:];
NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
resumableUpload.recordDirectoryPath = cachesDir;//記錄斷點(diǎn)的文件路徑
OSSTask * resumeTask = [client resumableUpload:resumableUpload];
[resumeTask continueWithBlock:^id(OSSTask *task) {
if (task.error) {
NSLog(@"error: %@", task.error);
if ([task.error.domain isEqualToString:OSSClientErrorDomain]
&& task.error.code == OSSClientErrorCodeCannotResumeUpload) {
// 該任務(wù)無(wú)法續(xù)傳,需要獲取新的uploadId重新上傳
}
} else {
NSLog(@"Upload file success");
}
return nil;
}];
性能統(tǒng)計(jì)
數(shù)據(jù)分析
android/ios 端的分片上傳改為并發(fā)后的測(cè)試與之前對(duì)比,上傳分片的網(wǎng)絡(luò)請(qǐng)求速度 多線程 和 單線程是一樣的使用時(shí)間,這個(gè)主要是取決于帶寬速度, 多線程相較于單線程主要是提高了讀取文件的io時(shí)間。數(shù)據(jù)如下:
iOS 模擬器測(cè)試
100mb大小文件
1000 part num 單線程 104.530217s 多線程 54.528591s
100 part num 單線程 59.306880s 多線程 54.336914s
1.31g 大小文件
100 part num 單線程 746.775666s 多線程 731.940330s
1000 part num 單線程 822.866331s 多線程 733.306236s
2000 part num 單線程 965.428122s 多線程 731.940330s
5000 part num 單線程 1205.379382s 多線程 732.982330s
android motoXT1085 雙核cpu
100mb文件
100 part num 單線程 70.484s 多線程 53.656s
1000 part num 單線程 104.530217s 多線程54.528591s
1.31g視頻文件
135 part num 單線程 869s 多線程 738s
1342 part num 單線程 1079.081s 多線程 732.079s
總體來(lái)看比之前有提升,單線程隨著片的個(gè)數(shù)的增加時(shí)間耗時(shí)越來(lái)越高,而多線程下,時(shí)間基本是一樣的,按照目前默認(rèn)配置的part size 256kb ,單線程下網(wǎng)絡(luò)資源與I/O資源都吃滿,并發(fā)下性能提高平均有30%左右(上傳時(shí)間減少)
小結(jié)
移動(dòng)端下,網(wǎng)絡(luò)資源與I/O資源一般都比較緊缺,多線程不會(huì)提高網(wǎng)絡(luò)的總帶寬:比如,在跑滿某個(gè)資源下載策略分配一個(gè)連接供給帶寬2000Kb/s的時(shí)候,本地單線程 能夠同時(shí)吃滿 2000Kb/s,這里就到達(dá)了一個(gè)峰值;但是如果某個(gè)資源連接帶寬是2000Kb/s,但是單線程請(qǐng)求帶寬 已經(jīng)達(dá)到 2000Kb/s,那么就是本地網(wǎng)絡(luò)帶寬 Block了上傳速度,也就是說(shuō)開(kāi)再多線程,再多連接也都無(wú)濟(jì)于事;但,如果本地網(wǎng)絡(luò)帶寬 吃完2000Kb/s 的同時(shí)還有很多的網(wǎng)絡(luò)資源剩余,假如還有2000Kb/s的提升空間,那么這時(shí)再建立一個(gè)連接 將這 2000Kb/s 也吃滿,那么此時(shí)的速度就可以達(dá)到 4000Kb/s,這時(shí)提速很明顯,I/O資源同理。
后續(xù)計(jì)劃
增加crc64編碼方式進(jìn)行文件正確性校驗(yàn),服務(wù)端與客戶端進(jìn)行交互驗(yàn)證。
分片上傳的多線程數(shù)量改為可配置,用戶可以根據(jù)自己的實(shí)際需求進(jìn)行設(shè)置。
進(jìn)度回調(diào)優(yōu)化,對(duì)進(jìn)度的粒度進(jìn)一步的細(xì)化,支持回調(diào)頻率可配置等。
總結(jié)
以上是生活随笔為你收集整理的oss多线程 上传_解读阿里云oss-android/ios-sdk 断点续传(多线程)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: kotlin sealed 中_7.8
- 下一篇: gossip 区块链_区块链技术创新生态