AWS S3 应用 KMS Key 进行服务端数据加密

当我们把数据搬上云端,为了保护敏感数据一定要对数据存储进行加密。而对于 S3 上的数据加密最简单莫过于启用服务端数据加密,可以是 AES-256 或 AWS-KMS。进行了服务端加密码的文件有什么不同呢?首先从 AWS S3 文件列表视图中看到的文件大小与原始文件大小是一样的,其实数据在 AWS 机房是加密存储了的,比如说直接在 AWS 服务器上拷出那些 S3 文件是不能理解的。

本文涉及的内容包括:

  1. 服务器端加密后的 S3 文件有何不同
  2. 不启用 Bucket 的默认加密如何进行服务端数据加密(含 AWS CLI 和  Java 代码操作)
  3. 启用及应用 Bucket 的默认加密
  4. 上传与下载文件的 IAM role 需要的权限

服务器端加密后的 S3 文件有何不同

首先看现象,后面才能确认我们的操作是否对数据真的进行了服务端加密。查看使用 AWS-KMS key 加密后的 S3 文件的 Overview, 看到下面两个属性

Server-side encryption
AWS-KMS
KMS key ID
arn:aws:kms:us-east-1:123456789012:key/e4ce859b-786b-4b8e-8b73-4968adb6e4ed

没加密的话, Server-side encryption 是 None, 并且没有 KMS key ID 属性。 阅读全文 >>

实现 Amazon S3 数据(文件)分段上传

探索是否能以流式写数据到 S3

通常,在我们项目中用 Java 代码上传数据到 S3 是下面那样的操作

AmazonS3 s3Client = AmazonS3ClientBuilder.defaultClient();
s3Client.putObject("bucket_name", "s3key.txt", new ByteArrayInputStream("hello".getBytes()), new ObjectMetadata()); //ObjectMetadata 没什么特别的话可以为 null

虽然  putObject() 的第三个参数是一个流,但它是输入流, 并非输出流啊。也就是说在执行该方法时必须把所有待上传的上据全部准备在这个输入流中,所以这里就直接用一个 ByteArrayInputStream 来包裹需上入到 S3 的数据内容。

当然 putObject() 也就无法像 FileObjectOutputStream 那样流式写入内容到文件中,因为 putObject() 前后都没有与 bucket 上那个文件上有联系。即使是用 PipedInputStream/PipedOutputStream  也不行, 比如说下面的代码 阅读全文 >>

AWS S3 Key 前缀分布优化数据请求的性能

很早就想写下这篇日志的,因为实际使用 AWS S3 来存取文件使用什么样的 Key 对性能的影响是极其大的。当然,如果你对 S3 的并发请求在 50 以内是无所谓的,要是并发要求很高的话,Key 的选择就变得至关重要的,不可不察。S3 Key 从第一个字符算起的任意长度子字符串都被称作前缀(prefix), 而对 S3 文件访问性能影响不在完整的 Key, 恰恰是那个前缀。

背景:我们最初在使用 S3 时,存储的文件的 Key 直接用了数据库的自增 ID,于是保存到 Bucket 中大概下面那样子的

examplebucket/12134850.csv
examplebucket/12134851.csv
examplebucket/12134852.csv
examplebucket/12134853.csv
examplebucket/12134854.csv
examplebucket/12134855.csv
examplebucket/12134856.csv
examplebucket/12134857.csv
examplebucket/12134858.csv

Bucket 中有百万个文件,当初测试时 60 个左右的 Lambda 实例同时访问这个 Bucket 中不同的文件时,加载每个 S3 文件的时间大约在几百毫秒,然后并发上到 70, 80 后加载同样大小的 S3 文件的时间陡然增加到 10 秒以上,并发继续上到 100 以上直接导致众多 S3 的请求超时。后来了解到虽然一个 Bucket 中放多少个文件是没有限制的,而且官方文档说了文件多了并不影响访问的性能,但背后却有一个文件的分区存储机制,这个才是关键。

S3 的分区存储就像是硬盘分区,或文件分布在不同硬盘上的效果。试想一下,如果我们多个线程同时从一块硬盘上读取数据,每个线程需共同一个磁头来读取数据,性能就差; 但如果那些线程同时从不同的硬盘上读取各自的数据,那性能就大大提升了,它们互不干扰。在使用机械硬盘时我有过这样的体验,在同一个磁盘上拷贝文件比从一个磁盘拷贝到另一个磁盘要慢很多。 阅读全文 >>