jclouds_使用jclouds在S3上分段上传

jclouds

1.目标

在上一篇文章中 ,我们研究了如何使用jclouds中的通用Blob API将内容上传到S3。 在本文中,我们将使用jcloudsS3特定的异步API上传内容并利用S3提供的分段上传功能。

2.准备


2.1。 设置自定义API

上传过程的第一部分是创建jclouds API-这是针对Amazon S3的自定义API:

public AWSS3AsyncClient s3AsyncClient() {String identity = ...String credentials = ...BlobStoreContext context = ContextBuilder.newBuilder('aws-s3').credentials(identity, credentials).buildView(BlobStoreContext.class);RestContext<AWSS3Client, AWSS3AsyncClient> providerContext = context.unwrap();return providerContext.getAsyncApi();
}

2.2。 确定内容的零件数

Amazon S3对于每个要上传的部分都有5 MB的限制。 因此,我们需要做的第一件事是确定可以分割内容的适当数量的部分,以使我们没有低于5 MB限制的部分:

public static int getMaximumNumberOfParts(byte[] byteArray) {int numberOfParts= byteArray.length / fiveMB; // 5*1024*1024if (numberOfParts== 0) {return 1;}return numberOfParts;
}

2.3。 将内容分成几部分

将把字节数组分成一定数量的部分:

public static List<byte[]> breakByteArrayIntoParts(byte[] byteArray, int maxNumberOfParts) {List<byte[]> parts = Lists.<byte[]> newArrayListWithCapacity(maxNumberOfParts);int fullSize = byteArray.length;long dimensionOfPart = fullSize / maxNumberOfParts;for (int i = 0; i < maxNumberOfParts; i++) {int previousSplitPoint = (int) (dimensionOfPart * i);int splitPoint = (int) (dimensionOfPart * (i + 1));if (i == (maxNumberOfParts - 1)) {splitPoint = fullSize;}byte[] partBytes = Arrays.copyOfRange(byteArray, previousSplitPoint, splitPoint);parts.add(partBytes);}return parts;
}

我们将测试将字节数组分成多个部分的逻辑–我们将生成一些字节,将字节数组拆分,使用Guava将其重新组合在一起,并验证是否可以恢复原始字节:

@Test
public void given16MByteArray_whenFileBytesAreSplitInto3_thenTheSplitIsCorrect() {byte[] byteArray = randomByteData(16);int maximumNumberOfParts = S3Util.getMaximumNumberOfParts(byteArray);List<byte[]> fileParts = S3Util.breakByteArrayIntoParts(byteArray, maximumNumberOfParts);assertThat(fileParts.get(0).length + fileParts.get(1).length + fileParts.get(2).length,equalTo(byteArray.length));byte[] unmultiplexed = Bytes.concat(fileParts.get(0), fileParts.get(1), fileParts.get(2));assertThat(byteArray, equalTo(unmultiplexed));
}

要生成数据,我们只需使用Random的支持:

byte[] randomByteData(int mb) {byte[] randomBytes = new byte[mb * 1024 * 1024];new Random().nextBytes(randomBytes);return randomBytes;
}

2.4。 创建有效载荷

既然我们已经为内容确定了正确的部分数量,并且设法将内容分解为多个部分,那么我们需要为jclouds API 生成Payload对象

public static List<Payload> createPayloadsOutOfParts(Iterable<byte[]> fileParts) {List<Payload> payloads = Lists.newArrayList();for (byte[] filePart : fileParts) {byte[] partMd5Bytes = Hashing.md5().hashBytes(filePart).asBytes();Payload partPayload = Payloads.newByteArrayPayload(filePart);partPayload.getContentMetadata().setContentLength((long) filePart.length);partPayload.getContentMetadata().setContentMD5(partMd5Bytes);payloads.add(partPayload);}return payloads;
}

3.上载

上传过程是一个灵活的多步骤过程-这意味着:

  • 可以在拥有所有数据之前开始上传-数据可以在输入时上传
  • 数据分上传-如果这些操作之一失败,则可以简单地将其检索
  • 块可以并行上传–这可以大大提高上传速度,尤其是在大文件的情况下

3.1。 启动上传操作

Upload操作的第一步是启动该过程 。 对S3的请求必须包含标准的HTTP标头–特别是内容MD5标头。 我们将在这里使用Guava哈希函数支持:

Hashing.md5().hashBytes(byteArray).asBytes();

这是整个字节数组(而不是各个部分)的md5哈希

为了启动上载以及与S3的所有进一步交互,我们将使用AWSS3AsyncClient –我们之前创建的异步API:

ObjectMetadata metadata = ObjectMetadataBuilder.create().key(key).contentMD5(md5Bytes).build();
String uploadId = s3AsyncApi.initiateMultipartUpload(container, metadata).get();

密钥是分配给对象的句柄–它必须是客户端指定的唯一标识符。

还要注意,即使我们使用的是异步版本的API, 我们也阻止了该操作的结果–这是因为我们需要初始化的结果才能继续前进。

操作的结果是S3返回的上载ID –这将在整个生命周期中识别上载,并将出现在所有后续的上载操作中。

3.2。 上载零件

下一步是上传零件 。 我们的目标是并行发送这些请求,因为上载零件操作代表了大部分上载过程:

List<ListenableFuture<String>> ongoingOperations = Lists.newArrayList();
for (int partNumber = 0; partNumber < filePartsAsByteArrays.size(); partNumber++) {ListenableFuture<String> future = s3AsyncApi.uploadPart(container, key, partNumber + 1, uploadId, payloads.get(partNumber));ongoingOperations.add(future);
}

零件编号必须是连续的,但发送请求的顺序无关紧要。

提交所有上载零件请求后,我们需要等待它们的响应,以便我们可以收集每个零件的单独ETag值:

Function<ListenableFuture<String>, String> getEtagFromOp =new Function<ListenableFuture<String>, String>() {public String apply(ListenableFuture<String> ongoingOperation) {try {return ongoingOperation.get();} catch (InterruptedException | ExecutionException e) {throw new IllegalStateException(e);}}
};
List<String> etagsOfParts = Lists.transform(ongoingOperations, getEtagFromOp);

如果由于某种原因,上载部分操作之一失败, 则可以重试该操作,直到成功为止。 上面的逻辑不包含重试机制,但是建立它应该足够简单。

3.3。 完成上传操作

上传过程的最后一步是完成分段操作 。 S3 API要求以Map的形式上传来自先前零件的响应,现在我们可以从上面获得的ETag列表中轻松创建这些响应:

Map<Integer, String> parts = Maps.newHashMap();
for (int i = 0; i < etagsOfParts.size(); i++) {parts.put(i + 1, etagsOfParts.get(i));
}

最后,发送完整的请求:

s3AsyncApi.completeMultipartUpload(container, key, uploadId, parts).get();

这将返回完成对象的最终ETag,并完成整个上传过程。

4。结论

在本文中,我们使用自定义S3 jclouds API构建了一个支持多部分的,完全并行的S3上传操作。 此操作可以按原样使用,但是可以通过几种方法进行改进 。 首先,应在上传操作周围添加重试逻辑,以更好地处理失败。 接下来,对于非常大的文件,即使该机制并行发送所有上载的多部分请求, 限制机制仍应限制发送的并行请求的数量。 这既可以避免带宽成为瓶颈,又可以确保Amazon本身不会将上传过程标记为超过每秒允许的请求限制– Guava RateLimiter可能非常适合此操作。

参考:来自badung博客的JCG合作伙伴 Eugen Paraschiv的jclouds在S3上进行分段上传 。

翻译自: https://www.javacodegeeks.com/2013/04/multipart-upload-on-s3-with-jclouds.html

jclouds

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/349272.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql+表中公共信息,計算mysql中兩個表之間的公共行數

so heres my question...這是我的問題…Hi have two tables in mysql, called go_H and go_J, both looking like this:在mysql中有兩個表&#xff0c;叫做go_H和go_J&#xff0c;它們都是這樣的:go_Hgo_H---------------------------| gene | GoCode |-----------------------…

极域课堂管理系统软件如何取消控制_微缔电子组装业MES系统软件六大功能组成...

电子组装业MES系统软件六大功能组成MES系统软件是制造执行系统的英文简称&#xff0c;MES系统软件在整个企业信息集成系统中承上启下&#xff0c;是生产活动与管理活动信息沟通的桥梁&#xff0c;MES系统软件在产品从工单下发到生产成成品的整个过程中&#xff0c;扮演着促进生…

使用虚拟时间测试基于时间的反应堆堆芯流

Reactor Core实现了Reactive Streams规范&#xff0c;并处理了&#xff08;可能无限的&#xff09;数据流。 如果您感兴趣&#xff0c;请查看它提供的出色文档 。 在这里&#xff0c;我假设对Reactor Core库的Flux和Mono类型有一些基本的了解&#xff0c;并且将介绍Reactor Cor…

matlab二维数组排序函数,Matlab 用sort函数排序 二维数组

在Matlab中排序某个向量(一维)时&#xff0c;可以使用sort(A)&#xff0c;其中A为待排序的向量&#xff0c;如果仅是用来排序A&#xff0c;那么直接使用sort(A)即可&#xff0c; 如果排序后还需要保留原来的索引可以用返回值&#xff0c;即[B,ind]sort(A)&#xff0c;计算后&am…

多个cuda 被单进程沾满_报名 | 提高GPU利用率,听英伟达专家分享这个CUDA工具

随着 NVIDIA GPU 计算性能的不断提升&#xff0c;如何提升 GPU 利用率是开发者普遍关心的问题之一。从 Kepler 架构开始&#xff0c;NVIDIA GPU 支持多个 CUDA kernels 函数的并发执行&#xff0c;称为 Hyper-Q 技术。Hyper-Q 技术支持多个 CUDA streams、多个 CPU threads 或者…

usb转ttl模块与matlab,USB接口转TTL小板的自检测试

现在电脑基本上都不会配置DB9串行数据端口了&#xff0c;这给一些喜欢折腾刷机和单片机加载程序的朋友带来了诸多的不便。还好&#xff0c;随着技术的发展&#xff0c;USB接口转TTL的产品越来越成熟&#xff0c;而这种产品主要以采用PL-2303HX芯片作为主控器的居多&#xff0c;…

程序员python工作_程序员如何在工作中进步

工作&#xff0c;对于大部分人都是不可避免的一件事&#xff0c;有的人是为了生存&#xff0c;有的人是为了自我价值的实现&#xff0c;也有人是为了将来不工作而现在努力工作&#xff0c;出发点可能各种各样&#xff0c;但是工作总是大部分人不可避免的一部分。程序员&#xf…

matlab 误差椭圆,求3倍标准差误差椭圆分析的程序

根据《白话空间统计之九&#xff1a;方向分布(标准差椭圆)修正版》(有些地方没有理解清楚)&#xff0c;写了下面的程序。但是好像结果不对Zmvnrnd([0.5 1.5], [0.025 0.03 ; 0.03 0.16], 50);XZ(:,1); YZ(:,2);mean_Xnanmean(X); mean_Ynanmean(Y); %椭圆圆心%确定长短半轴…

java ee cdi_Java EE CDI处理程序方法示例

java ee cdi这是CDI Disposer方法的教程。 在CDI中&#xff0c;由于Producer方法生成的对象随后可以注入到应用程序中&#xff0c;因此使用Disposer方法&#xff0c;以便在其工作完成时将其删除。 Disposer方法始终与Producer方法匹配。 Disposer方法使用的一个示例是当应用程…

python皮卡丘编程代码_再接再厉,用python编程13行代码解方程组(纯字符)

因为是示例为主&#xff0c;我们将方程组限制在二元一次方程组&#xff1a;x,y两个变量&#xff0c;两个方程。类似这样&#xff1a;每个方程有两个变量&#xff0c;x和y&#xff0c;形式为&#xff1a;axbycd由于这次有了两个方程&#xff0c;我们提取参数的代码就适合提炼为一…

快速提示:使用Chrome开发工具调试GWT应用程序

调试是软件开发的重要方面。 拥有正确的工具可以节省大量时间和头痛。 在GWT Super Dev模式之前&#xff0c;经典的Dev模式允许使用JVM调试。 开发人员可以在其IDE中设置断点&#xff0c;并使用调试模式来跟踪错误和错误。 现在&#xff0c;在超级开发模式下&#xff0c;情况有…

用matlab做纹理合成,关于图像纹理合成的Matlab例程

纹理是普遍存在的视觉现象&#xff0c;其可以描述地形、植物、矿石、纤维和皮肤等等物体的表面特征。纹理结构在图像中反映其图像像素取值的空间变化情况&#xff0c;这种变化具有某中统计规律&#xff0c;在纹理区域内的各部分具有大致相同的结构。纹理合成是利用计算机产生纹…

python 服务端与c++客户端通讯_[原创]python socket 服务端 与 c++客户端通讯,发包内容加密,支持大文件,并发...

代码经过网络搜索,综合算是原创吧.py脚本为服务端项目文件在https://github.com/jinjie412/service_client_socketimport socketserverimport jsonimport base64import osfrom te import OPMysql,Caltimeimport time#数据库操作opm OPMysql()#加密发包内容def crypt(source,ke…

matlab评估边缘检测性能,【模糊推理】模糊逻辑图像边缘检测,原理+matlab代码~...

这篇博客是接着上一篇来哒&#xff0c;https://blog.csdn.net/luolan9611/article/details/94285158本篇博客及上篇博客搜集的资料、实验代码、实验报告、PPT均已上传至百度网盘&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1AmT4TtBAxj1FKf4KUFcsBw 提取码&#x…

qt中实现左右分割线_Qt项目中,实现屏幕截图并生成gif的详细示例(值得细读)...

总第50篇平时我们在工作和学习的过程中&#xff0c;有时需要将桌面的某些动作截图生成gif动图&#xff0c;以更生动地呈现出来。目前有很多这样的软件&#xff0c;并且方便易使用&#xff0c;比如我经常使用的GifCam&#xff0c;软件小巧&#xff0c;生成的图片文件也比较小&am…

构建Spring Boot RESTful服务+ Spring Boot执行器

总览 什么是REST&#xff1f; REST&#xff08;代表状态转移&#xff09;是Web构建的体系结构样式&#xff0c;已成为用于Web应用程序的标准软件设计模式 。 代表性国家转移一词最早由REST的发起人&#xff0c;HTTP规范的主要作者之一Roy Fielding在其博士论文中使用 。 REST上…

matlab 安装glpk,mac上安装GLPK

Obsolation note:Thanks to Dave Coleman’s comment I found out that glpk is available through homebrew now! So you just need these 2 steps to get glpk now:homebrewbrew install glpkIf you still want to read on, the old way is still here…So you want copy-pas…

tf调不到keras怎么 回事_格力变频空调快速维修方法及技巧 空调压缩机不到一分钟就停,怎么回事?...

格力变频空调快速维修方法及技巧一、 室内部分&#xff1a; 1、F1开路&#xff1a;制冷时不启动或启动一下就停机&#xff1b;制热正常&#xff0c;且一直高频运转。 2、F2开路&#xff1a;工作6—10分钟就停机&#xff0c;显示E2停止外机。 3、F2短路&#xff1…

php 档案,PHP 档案包 (PHAR)

PHP 档案包 (PHAR)要获取 PHPUnit&#xff0c;最简单的方法是下载 PHPUnit 的 PHP 档案包 (PHAR)&#xff0c;它将 PHPUnit 所需要的所有必要组件(以及某些可选组件)捆绑在单个文件中&#xff1a;要使用 PHP档案包(PHAR)需要有 phar 扩展。要使用 PHAR 的 --self-update 功能需…

pycharm是不是python编程_使用PyCharm进行python开发的简介

使用PyCharm进行python开发的简介这个是很常见的一个问题&#xff0c;我想学习python&#xff0c;用什么编辑器呢&#xff1f;eclipsepydev?IDLE?vim?每个人有自己的习惯&#xff0c;可能是自己琢磨的&#xff0c;也可能是前辈指导的&#xff0c;这里只分享自己孤陋寡闻琢磨…