提问

AWS S3事件通知的两个实践

AWS技术交流  / 只看大图  / 倒序浏览   © 著作权归作者本人所有

#楼主# 2019-7-26

跳转到指定楼层
本帖最后由 社群技术交流 于 2019-7-26 18:09 编辑

作者:光环云 徐毅
概述上一篇,我们实践了AWS S3跨区域复制功能(CRR),将对象从一个region的存储桶复制到另一个region的存储桶,可见:AWS S3跨区域复制实践。今天来实践一下对于S3事件通知的操作。
S3提供了事件通知功能,可以在存储桶发生某些事件时接收通知。本次实践的目标有两个,一是当存储桶上传新对象时发送电子邮件提醒,二是当存储桶上传图片时进行大小缩放。
实践1 存储桶上传新对象时发送邮件提醒
这个操作比较简单,S3+SNS即可实现,基本流程如下:
步骤1 创建存储桶
在aws S3控制台上创建一个存储桶xytempbucket(位于欧洲巴黎region),如图1所示
image1.png
步骤2 创建SNS通知
在SNS控制台创建一个通知主题xuyisnstopicmail,如图2所示:
image2.png
注意,在这个主题中需要明确其访问策略,如图3所示
image3.jpeg
策略主要明确SNS主题名称和aws 存储桶的名称(分别用蓝色标明)。
至此,主题的发布完成,接下来需要订阅该主题。主题界面中点击"创建订阅",开始配置订阅,在"主题ARN"中把上一步发布的主题ARN填进去即可,在"协议"中选择"电子邮件",在"终端节点"中填入email接收地址,点击"创建订阅"即可,如图4所示
image4.png
此时,只是进行了订阅主题的操作,还没有生效,AWS会发送一封电子邮件至图中所填邮箱,需要据此点击确认对主题的订阅。如图5所示
image5.png
根据邮件提示操作即可确认订阅成功。
步骤3 在存储桶上配置事件,启用存储桶通知
回到S3控制台,在所选的存储桶->属性->事件栏点击"添加通知",如图6所示
image6.png
步骤4 验证
至此,配置完毕,现在开始验证。在配置之前存储桶中已经存在了7个图片(screen-shot1~screen-shot7),现在从控制台再上传一张xytestpng.png的图片,如图7所示
image7.png
图片上传成功之后,随即qq邮箱传来邮件提醒,查看邮箱,如图8所示
image8.png
注意:邮件通知的时间可能有一定的延时,不确定。
至此,实践1完毕。(非常简单,在控制台点击即可完成。)

实践2 存储桶上传图片进行缩放
整体流程:将图片上传到源存储桶,通过事件触发lambda函数,lambda获取上传的图片进行缩放处理,再将处理完成的图片存入到目标存储桶。如图9所示:
image9.png
步骤1 创建存储桶
在S3控制台创建存储桶,需要创建两个存储桶,一个是源存储桶xytempbucket,一个是目标存储桶xytempbucketresized(创建过程省略),区域为欧洲巴黎。如图10所示

image10.png
步骤2 创建策略
IAM控制台->创建策略,将以下内容复制到json编辑框中,即可生成。
image11.png
注意:其中的源存储桶和目标存储桶要使用自己实际的存储桶ARN。
步骤3 创建角色
策略创建完成后,切换到IAM控制台,创建角色。
image12.png
创建由lambda服务使用的角色,如图12所示,并将步骤2中创建的策略附加到该角色上,如图13、图14所示。
image13.png
image14.png
步骤4 创建lambda函数
切换到lambda控制台,创建函数->从头开始创作,填写函数名称,和语音信息,如图15所示
image15.png
注意区域要与S3中存储桶的区域一致,选欧洲巴黎。
继续,可以再次添加函数的触发器(也可以暂时不添加,而去S3存储桶的事件属性里添加触发lambda,同样的效果),这里选择S3触发,需要选择源存储桶,事件类型选择put,如图16所示
image16.png
点击"添加"即成功添加了lambda函数的触发器。再编辑lambda函数代码,将下面代码复制进去
  1.   var AWS = require("aws-sdk");
  2.     var IM = require('imagemagick');
  3.     var FS = require('fs');
  4.     var compressedJpegFileQuality = 0.80;
  5.     var compressedPngFileQuality = 0.95;
  6.      
  7.     exports.handler = (event, context, callback) => {
  8.         var s3 = new AWS.S3();
  9.         var sourceBucket = "xytempbucket";
  10.         var destinationBucket = "xytempbucketresized";
  11.         var objectKey = event.Records[0].s3.object.key;
  12.         var getObjectParams = {
  13.             Bucket: sourceBucket,
  14.             Key: objectKey
  15.         };
  16.         s3.getObject(getObjectParams, function(err, data) {
  17.             if (err) {
  18.                 console.log(err, err.stack);
  19.             } else {
  20.                 console.log("S3 object retrieval get successful.");
  21.                 var path = require('path');
  22.                 var tmpname = path.basename(objectKey);
  23.                 var resizedFileName = "/tmp/"+tmpname;
  24.                 var quality;
  25.                 if (resizedFileName.toLowerCase().includes("png")){
  26.                     quality = compressedPngFileQuality;
  27.                 }
  28.                 else {
  29.                     quality = compressedJpegFileQuality;
  30.                 }
  31.                 var resize_req = { width:"100%", height:"100%", srcData:data.Body, dstPath: resizedFileName, quality: quality, progressive: true, strip: true };
  32.                 IM.resize(resize_req, function(err, stdout) {
  33.                     if (err) {
  34.                         throw err;
  35.                     }
  36.                     console.log('stdout:', stdout);
  37.                     var content = new Buffer(FS.readFileSync(resizedFileName));
  38.                     var uploadParams = { Bucket: destinationBucket, Key: objectKey, Body: content, ContentType: data.ContentType, StorageClass: "STANDARD" };
  39.                     s3.upload(uploadParams, function(err, data) {
  40.                         if (err) {
  41.                             console.log(err, err.stack);
  42.                         } else{
  43.                             console.log("S3 compressed object upload successful.");
  44.                         }
  45.                     });
  46.                 });
  47.             }
  48.         });
  49.     };
复制代码
注意:代码中的sourceBucket和 destinationBucket需要填写步骤1中相应的桶名称。
如图17所示:
image17.png
并选择运行环境,这里是"Node.js6.10",处理程序名称为"index.handler",如图18所示
image18.png
下面继续配置执行角色,选择"现有角色",选择步骤3中创建的角色,另外可能还需要配置超时时间和内存大小,一般默认即可,后面根据函数执行情况可以再调整。如图19所示:
image19.png
我们现在可以切回到S3控制台,在源存储桶xytempbucket中的事件属性里可以看到刚刚配置过的触发器,如图20所示
image20.png
注意:
  • 1 如果此前没有配置触发器,则现在源存储桶的事件里配置即可。
  • 2 一个存储桶上的事件通知如果重复配置的时候可能会报错,所以触发器配置不成功的时候先看看该存储桶是否有重复配置。
至此,所以配置完毕。
步骤5 验证
向源存储桶分别上传文件girl.jpg、woman.jpg、woman.png、xytestpng.png四张图片,且大小不一(其他图片是此前上传的,不予考虑),如图21所示:
image21.png
考虑到图片的下载上传以及缩放处理都需要时间,等了大约1分多钟再去查看目标存储桶xytempbucketresized,结果如图22所示:
image22.png
可以看到woman000.png图片没有缩放成功,原因未知(因为代码是从网上下载,故此不分析具体原因),其他图片都有一定程度的缩放(从图片大小既能看出来)。
注意:测试的时候是一张一张图片上传进行测试,没有考虑同时上传多张图片这样的场景,因为本次实践的目的是将整个流程走一遍,至于缩放失败的原因可能还跟内存、超时时间等配置有关。






转播转播
回复

使用道具

联系楼主
*
*
客户公司所在区域:
*
产品:
*
简述客户的业务场景和需求
*
*
*

成为第一个回答人

B Color Link Quote Code Smilies
光环云社区 |京ICP备18044167号-13|

京公网安备 11010102003758号