使用自定义 ANT 任务上传到 Amazon S3

工程 | Ben Hale | 2007年4月25日 | ...

可靠的 CI 结构的一个有趣的副作用是,当事情运行可靠时,新的问题开始出现。在 Spring 的 CI 系统开始平稳运行后不久,我们在static.springframework.org上的偶尔空间和带宽问题变得更加突出。Colin Sampaleanu 早些时候研究了如何缓解其中一些问题,并选择了Amazon S3

Amazon S3 是Amazon Web Services 的一部分,提供了一种极其便宜的在线文件存储服务。“极其便宜”是什么意思?从网站上看,1 GB/月的存储费用为 0.15 美元,1 GB 带宽费用为 0.20 美元。除此之外,还有一个高带宽透明镜像服务,S3 对于存储我们的夜间快照非常有吸引力。顺便说一下,Amazon 内部实际上使用了完全相同的基础设施,因此您知道有一个管理员团队保证他们的五个九的承诺。

为了将 S3 用于我们的夜间快照,我们首先必须替换使用scp的旧快照上传过程。四处查看后,我没有看到任何上传到 S3 的 ANT 任务,所以我开始创建自己的任务。我的目标配置非常简单。


<aws:s3 accessKey="${s3.accessKey}" secretKey="${s3.secretKey}">
	<upload bucketName="static.springframework.org"
		file="${target.release.dir}/${release-with-dependencies.zip}"
		toFile="SPR/spring-framework-${spring-version}-with-dependencies-${tstamp}-${build.number}.zip"
		publicRead="true"/>
	<upload bucketName="static.springframework.org"
		file="${target.release.dir}/${release.zip}"
		toFile="SPR/spring-framework-${spring-version}-${tstamp}-${build.number}.zip"
		publicRead="true"/>
</aws:s3>

我希望能够定义一个由我们的访问密钥和密钥(S3 的加密登录)控制的单个 S3 会话,并在该定义中执行多个上传。每次上传都进入一个“存储桶”,这是 S3 提供的唯一粒度级别。

S3 本身通常用作 RESTful 服务,因此易于交互。为此,我使用了一个名为jets3t(发音为 jet-set)的库。对于任何使用 Java 与 S3 交互的人来说,这是使用 S3 的首选方法(据我所知,这是 Amazon 唯一认可的库)。Jets3t 使用与我的 XML 定义类似的范例(或者也许是我使用了它们的范例?),您创建对服务器的引用并重复使用它来执行多个操作。在 ANT 任务中,我根据访问密钥和密钥创建一组凭据,并将它们绑定到对服务的引用。


AWSCredentials credentials = new AWSCredentials(accessKey, secretKey);
S3Service service = new RestS3Service(credentials);

for (Upload upload : uploads) {
	upload.upload(service);
}

如您所见,我已经模块化了上传操作,以便将来如果需要扩展 s3 任务来执行其他操作(下载、设置权限等),我可以这样做。Upload 对象完成了繁重的工作。它根据bucketName创建对存储桶的引用,根据toFile值创建对新对象的引用,然后通过 HTTP 上传文件的内容。


private S3Bucket getBucket() {
	return new S3Bucket(bucketName);
}

private S3Object getObject() {
	S3Object object = new S3Object(toFile);
	if (publicRead) {
		object.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ);
	}
	object.setDataInputFile(file);
	object.setContentLength(file.length());
	return object;
}

S3Bucket bucket = getBucket();
S3Object object = getObject();
service.putObject(bucket, object);

在这个任务的实际代码中,我添加了一些漂亮的输出,以便您可以看到文件的上传速度有多快以及上传速度是多少。

upload-s3:
   [aws:s3] Uploading /opt/j2ee/domains/springframework.org/build/bamboo-home/xml-data/build-dir/
                SPR-NIGHTLY/spring/target/release/spring-framework-2.0.5-with-dependencies.zip (65132641B)
                to bucket static.springframework.org
   [aws:s3] Transfer Time: 34.0s - Transfer Rate: 1915665.9B/​s
   [aws:s3] Uploading /opt/j2ee/domains/springframework.org/build/bamboo-home/xml-data/build-dir/
                SPR-NIGHTLY/spring/target/release/spring-framework-2.0.5.zip (10752085B)
                to bucket static.springframework.org
   [aws:s3] Transfer Time: 6.0s - Transfer Rate: 1792014.1B/​s

这项工作对我们来说非常成功,以至于我们将其扩展到了 Spring 产品组合中的所有基于 ANT 的构建中。Spring Framework、Spring LDAP、Spring Web Flow 和 Spring Modules 现在都上传到这个 S3 夜间快照存储库,我的待办事项清单中也包括为 Maven 项目提供一些支持。这样做的好处是,我们在过去两个月中节省了超过 30 GB 的空间并大幅减少了带宽使用,总共花费约 4.00 美元。

由于我必须编写一些代码才能使这一切正常工作,所以我将其放入我们的源代码控制区域。我还将其放在我们的内部私有 Maven 存储库中,该存储库镜像到公共 Maven 存储库。如果您有兴趣查看代码,请查看SVN 存储库。如果您想使用 ANT 任务,您可以使用groupIdorg.springframework.awsartifactIdspring-aws-ant从 Maven 获取它。请注意,这是完全不受支持且未记录的代码!它所做的非常有限,目前没有计划以任何方式改进或记录它。如果我有空闲时间,情况可能会改变,但不要指望它 :)

看来我的航班现在要降落了,所以我将借此机会结束。请关注后续文章,该文章描述了我们如何构建快照下载页面,以便您可以直接从 S3 获取快照。

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,以加速您的进步。

了解更多

获取支持

Tanzu Spring 在一个简单的订阅中提供对 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

即将举行的活动

查看 Spring 社区中所有即将举行的活动。

查看全部