我尝试了几个Imagemagik包装器库和一些S3库。由于性能差异很大,我很难选择最佳概念。
我已经使用了节点库"gm",这是一个很愉快的工作,并且有很好的文档记录。
至于S3,我已经尝试了亚马逊自己的AWS库以及"S3 Streams"
编辑:我刚刚发现AWS库可以处理流。我想这是一个新函数s3.upload(或者我刚刚错过了它?)。无论如何,我抛弃了s3流,它使用了更复杂的s3uploadPart在我的测试用例中,切换库流等于上传缓冲区
我的测试用例是将一个2MB的jpg文件拆分为大约30个512px的瓦片,并将每个瓦片发送到S3。Imagemagick有一种非常快速的自动方式,可以通过crop命令生成瓦片。不幸的是,我没有发现任何节点库可以捕获自动生成的tile的多文件输出。相反,我必须通过为每个瓦片单独调用crop命令来在循环中生成瓦片。
我将在详细信息之前介绍总计时:
A:85秒(s3流)
A:34秒(aws.s3.上传)(编辑)
B:35秒(缓冲区)
C:25秒(缓冲区并行)
显然,在这种情况下,缓冲区比流处理得更快。我不知道gm或s3 streams是否有一个糟糕的流实现,或者我是否应该调整一些东西。现在我将采用解决方案B.C速度更快,但占用的内存更多。
我在低端的Digital Ocean Ubuntu机器上运行这个。这就是我尝试过的:
A。生成瓦片并逐个流式传输
-
我为每个瓦片准备了一个数组,其中包含作物信息和s3Key,以生成
-
数组是用"async.echLimit(1)"循环的。我没有成功地一次生成多个瓦片,因此限制(1)。
-
生成瓦片时,它们直接流式传输到S3
伪代码:
async.eachLimit(tiles, 1, function(tile, callback) {
gm(originalFileBuffer)
.crop(tile.width, tile.height, tile.x, tile.y)
.stream()
.pipe(s3Stream({Key: tile.key, Bucket: tile.bucket})) //using "s3-streams" package
.on('finish', callback)
});
B。生成区块到缓冲区,并使用AWS包直接上传每个缓冲区
- 当瓦片被生成到缓冲区时,它们被直接上传到S3
伪代码:
async.eachLimit(tiles, 1, function(tile, callback) {
gm(originalFileBuffer)
.crop(tile.width, tile.height, tile.x, tile.y)
.toBuffer(function(err, buffer) {
s3.upload(..
callback()
)
})
});
C。与B相同,但将所有缓冲区存储在瓦片阵列中,以便稍后并行上传l
伪代码:
async.eachLimit(tiles, 1, function(tile, callback) {
gm(originalFileBuffer)
.crop(tile.width, tile.height, tile.x, tile.y)
.toBufer(function(err, buffer) {
tile.buffer = buffer;
callback()
})
});
下一步是在完成第一个each循环之后完成的。我似乎并没有通过把极限推到10以上来提高速度。
async.eachLimit(tiles, 10, function(tile, callback) {
s3.upload(tile.buffer..
callback()
)
});
编辑:根据Mark的要求提供更多背景我最初省略了细节,希望我能得到一个关于缓冲区与流的明确答案。
我们的目标是通过节点/Express API以响应的方式为我们的应用程序提供图像。后端数据库是Postgres。批量存储为S3。
传入的文件主要是照片、平面图和pdf文档。照片需要以多种尺寸存储,这样我就可以以响应的方式将它们提供给应用程序:缩略图、低分辨率、中分辨率和原始分辨率。
平面图必须是瓷砖,这样我就可以在应用程序中增量加载(滚动瓷砖)。全分辨率A1绘图可以是大约50M像素。
上传到S2的文件跨度从50kB(瓷砖)到10MB(平面图)。
文件来自不同的方向,但始终是流:
- 通过web或其他API(SendGrid)形成帖子
- 从应用程序上传
- 上传文件需要更多处理时从S3下载的流
我不喜欢把文件临时放在本地磁盘上,因此只有缓冲区和流。如果我可以使用磁盘,我会使用IM自己的平铺功能来快速平铺。
为什么不使用本地磁盘?
- 在上传到S3之前对图像进行加密。我不希望未加密的文件在临时目录中徘徊
- 总是存在清理临时文件的问题,在意外崩溃后可能会出现孤立文件等
经过更多的修改,我觉得有必要回答自己的问题。
最初,我使用npm包s3streams流式传输到s3。此包使用aws.s3.uploadPart.
现在我发现aws包有一个整洁的函数aws.s3.upload,它使用缓冲区或流。
切换到AWS自己的流媒体功能后,缓冲区/流上传之间没有时间差。
我可能用错了s3流。但我也在这个库中发现了一个可能的错误(regaring files>10MB)。我发布了一个问题,但没有得到任何答复。我的猜测是,自从s3.upload函数出现以来,这个库已经被放弃了。
所以,我自己的问题的答案是:
缓冲区/流之间可能存在差异,但在我的测试用例中,它们是相等的,这使得这暂时不是问题
以下是每个循环中新的"保存"部分:
let fileStream = gm(originalFileBuffer)
.crop(tile.width, tile.height, tile.x, tile.y)
.stream();
let params = {Bucket: 'myBucket', Key: tile.s3Key, Body: fileStream};
let s3options = {partSize: 10 * 1024 * 1024, queueSize: 1};
s3.upload(params, s3options, function(err, data) {
console.log(err, data);
callback()
});
感谢您的阅读。