使用自定义 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 对于存储我们的每日快照非常有吸引力。顺便说一句,亚马逊实际上在内部使用完全相同的基础设施,所以你知道有一个管理团队保证他们 5 个 9 的承诺。

为了使用 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 项目提供一些关爱。这样做的好处是,我们已经释放了超过 30GB 的空间,并大大减少了带宽使用量,而过去两个月的所有这些费用约为 4.00 美元。

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

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

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

先人一步

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

了解更多

获得支持

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

了解更多

即将举行的活动

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

查看全部