オブジェクトストレージ向けマルチスレッド分割アップロードの実装方法

大容量ファイルを効率的にアップロードするための分割アップロード手法について解説します。以下の実装例では5MB単位でファイルを分割し、マルチスレッドで並列アップロードを行います。

// 分割アップロードメインクラス
public class ChunkedUploader {
    private static final int DEFAULT_CHUNK_SIZE = 5 * 1024 * 1024; // 基本分割サイズ
    
    public void executeUpload(File targetFile, String storageBucket) throws Exception {
        // アップロードセッション開始
        StartUploadSessionRequest startReq = new StartUploadSessionRequest(storageBucket, targetFile.getName());
        UploadSession session = storageClient.startUploadSession(startReq);
        
        // 並列処理用スレッドプール
        ExecutorService threadPool = Executors.newFixedThreadPool(getOptimalThreadCount());
        List<Future<UploadPartTag>> taskResults = new ArrayList<>();
        
        // ファイル分割処理
        long totalSize = targetFile.length();
        int totalParts = calculateTotalParts(totalSize, DEFAULT_CHUNK_SIZE);
        
        // 分割タスク実行
        for (int partIndex = 1; partIndex <= totalParts; partIndex++) {
            long startByte = (partIndex - 1) * DEFAULT_CHUNK_SIZE;
            long partSize = Math.min(DEFAULT_CHUNK_SIZE, totalSize - startByte);
            
            UploadTask task = new UploadTask(
                session.getSessionId(),
                storageBucket,
                targetFile.getName(),
                targetFile,
                startByte,
                partSize,
                partIndex
            );
            taskResults.add(threadPool.submit(task));
        }
        
        // 全タスク完了待機
        List<UploadPartTag> partTags = new ArrayList<>();
        for (Future<UploadPartTag> result : taskResults) {
            partTags.add(result.get());
        }
        
        // 分割ファイル結合
        CompleteUploadRequest completeReq = new CompleteUploadRequest(
            storageBucket, targetFile.getName(), session.getSessionId(), partTags);
        storageClient.completeUpload(completeReq);
    }
    
    private int calculateTotalParts(long fileSize, int chunkSize) {
        return (int) Math.ceil((double)fileSize / chunkSize);
    }
    
    private int getOptimalThreadCount() {
        return Runtime.getRuntime().availableProcessors() * 2;
    }
}

// 分割アップロードタスク
class UploadTask implements Callable<UploadPartTag> {
    // 各分割部分のアップロード処理実装
    @Override
    public UploadPartTag call() throws Exception {
        // ファイルチャンク読み込み
        // アップロードリクエスト作成
        // ストレージへのアップロード実行
        // 結果タグを返却
    }
}

ファイルサイズに応じた動的な分割サイズ決定ロジック:

def determine_chunk_size(file_size_bytes):
    # ファイルサイズに基づき最適な分割サイズを決定
    if file_size_bytes <= 50 * 1024 * 1024:    # 50MB以下
        return 1 * 1024 * 1024                # 1MB分割
    elif file_size_bytes <= 5 * 1024 * 1024 * 1024:  # 5GB以下
        return 5 * 1024 * 1024                # 5MB分割
    else:
        return 10 * 1024 * 1024               # 10MB分割

タグ: オブジェクトストレージ マルチスレッド 分割アップロード 並列処理 ストレージAPI

7月23日 17:05 投稿