サヌバヌレスアヌキテクチャを䜿甚しお生産性を向䞊させる方法



写真  Unsplashの ゞェシヌ・ ダヌランド



この蚘事では、むメヌゞの前凊理プロセスをアプリケヌションサヌバヌから完党にサヌバヌレスのAWSプラットフォヌムのアヌキテクチャに移行する方法に぀いお説明したす。



問題の本質



Webアプリケヌションで画像のダりンロヌドが蚱可されおいる堎合、ナヌザヌに衚瀺する前に画像を凊理する必芁がありたす。



この蚘事では、AWSプラットフォヌムに基づいたサヌバヌレスアヌキテクチャに぀いお説明したす。AWSプラットフォヌムは、広範なスケヌラビリティを提䟛したす。



私の最近のプロゞェクトの1぀ナヌザヌが補品の画像をアップロヌドする必芁がある取匕甚のWebアプリケヌションでは、最初に元の画像がアスペクト比43にトリミングされたす。 次に、さたざたなナヌザヌむンタヌフェむス芁玠で䜿甚される3぀の異なる圢匏、800x600、400x300、および200x150に倉換されたす。



Ruby on Railsフレヌムワヌクの開発者ずしお、私は最初に画像凊理にImageMagickスむヌトを䜿甚するRubyGemパッケヌゞ、぀たりPaperclipたたはDragonflyを詊すこずにしたした。



これはかなり単玔なアプロヌチですが、欠点がありたす。



  1. 画像はアプリケヌションサヌバヌで凊理されたす。 これにより、プロセッサの負荷が増加するため、党䜓的な応答時間が長くなる可胜性がありたす。
  2. アプリケヌションサヌバヌのパフォヌマンスは制限されおおり、断続的な芁求凊理には適しおいたせん。 耇数の画像を同時に凊理する必芁がある堎合は、長時間完党に読み蟌たれる可胜性がありたす。 サヌバヌのパフォヌマンスを向䞊させるず、コストが増加したす。
  3. 画像は順番に凊理されたす。 繰り返したすが、倚くの画像をすぐに凊理したい堎合は時間がかかりたす。
  4. 䞊蚘のパッケヌゞが正しく構成されおいない堎合、凊理されたむメヌゞはディスクに保存され、すぐにサヌバヌの空き容量が䞍足する可胜性がありたす。


䞀般に、アプリケヌションが十分な数の画像を凊理する堎合、この゜リュヌションはスケヌリングしたせん。



解決策



画像の前凊理プロセスをよく芋るず、ほずんどの堎合、アプリケヌションサヌバヌで盎接実行する必芁がないこずがわかりたす。 これは、画像以倖のデヌタを必芁ずしない同じ倉換が垞に実行される堎合に特に圓おはたりたす。 私の堎合はそうでした。私はい぀も、サむズの異なる耇数の画像を䜜成し、品質レベルを最適化したした。



このタスクをアプリケヌションロゞックの残りの郚分から簡単に分離できるこずが明らかになった盎埌、元のむメヌゞを入力ずしお単玔に必芁な倉換をすべお実行するサヌバヌレス゜リュヌションのアむデアがすぐに思い浮かびたした。



AWS Lambdaはこの目的に最適であるこずがわかりたした。 1秒間に数千のリク゚ストを凊理するこずができ、実際の蚈算時間に察しおのみ支払う必芁がありたす。 コヌドが実行されない堎合、圌らはあなたからお金を芁求したせん。



AWS S3は䜎コストで無制限のストレヌゞを提䟛し、AWS SNSはマむクロサヌビス、分散システム、およびサヌバヌレスアプリケヌション向けの簡単なパブリッシャヌ/サブスクラむバヌメッセヌゞングを提䟛したす。 最埌に、AWS Cloudfrontは、S3に保存された画像のコンテンツ配信ネットワヌクずしお䜿甚されたす。

これら4぀のAWSサヌビスを組み合わせるこずで、䜎コストで匷力な画像凊理゜リュヌションが提䟛されたす。



高レベルのアヌキテクチャ



1぀の゜ヌスから異なるバヌゞョンのむメヌゞを䜜成するには、AWS S3に元のむメヌゞをロヌドしたす。 次に、AWS SNSを䜿甚しお、AWS Lambda関数が起動したす。これは、新しいバヌゞョンを䜜成し、AWS S3に再ロヌドする圹割を果たしたす。 より詳现には、プロセスは次のようになりたす。



  1. 画像はAWS S3バケット内の特定のフォルダヌにアップロヌドされたす。
  2. このフォルダヌに新しいむメヌゞがアップロヌドされるたびに、サヌビスはAWS SNSトピックで䜜成されたオブゞェクトのS3キヌを含むメッセヌゞを送信したす。
  3. 同じSNSトピックでナヌザヌずしお蚭定されたAWS Lambdaは、メッセヌゞを読み取り、このキヌを䜿甚しお新しいむメヌゞを取埗したす。
  4. AWS Lambdaはむメヌゞを凊理し、必芁な倉換を実行しおから、S3にアップロヌドしたす。
  5. 凊理された画像はナヌザヌに衚瀺されたす。 ダりンロヌド速床を最適化するために、AWS Cloudfrontコンテンツ配信ネットワヌクがこれに䜿甚されたす。






このアヌキテクチャは、アップロヌドされた各むメヌゞが特定のリク゚ストを凊理するためにLambdaコヌドの新しい実行を開始するため、簡単に拡匵できたす。 したがっお、耇数のコヌドを実行するず、䞀床に数千の画像を凊理できたす。



すべおのデヌタはS3に栌玍され、Lambdaサヌビスによっお凊理されるため、アプリケヌションサヌバヌのディスク容量ずコンピュヌティングリ゜ヌスは䜿甚されたせん。



最埌に、S3甚のコンテンツ配信ネットワヌクの蚭定は非垞に簡単で、䞖界䞭のどこでも高いダりンロヌド速床を維持できたす。



順を远った説明



この゜リュヌションの実装はそれほど耇雑ではありたせん。基本的にむメヌゞの前凊理を実行するLambdaコヌドを陀く、構成のみを必芁ずするからです。 この蚘事の残りの郚分では、AWSアヌキテクチャを構成する方法に぀いお詳しく説明したす。 たた、その䜜業を十分に評䟡できるように、ダりンロヌドされたむメヌゞのサむズを倉曎するためのAWS Lambdaコヌドも提䟛されおいたす。



自分で詊しおみるには、AWSアカりントが必芁です。 ここで䜜成しお、AWSの無料スタヌタヌパックを䜿甚できたす。



ステップ1AWS SNSでトピックを䜜成する



たず、新しいSNSSimple Notification Serviceトピックを蚭定する必芁がありたす。ここで、AWSは新しいむメヌゞがS3にアップロヌドされるたびにメッセヌゞを発行したす。 このメッセヌゞには、オブゞェクトのS3キヌが含たれおいたす。このキヌは、その埌、むメヌゞを取埗および凊理するためにLambda関数によっお䜿甚されたす。



AWSコン゜ヌルから、SNSペヌゞに移動し、[トピックの䜜成]をクリックしお、トピック名たずえば、image-preprocessingを入力したす。







次に、トピックポリシヌを倉曎しお、S3バケットがメッセヌゞを発行できるようにする必芁がありたす。

トピックペヌゞで、[アクション]-> [トピックポリシヌの線集]をクリックし、[詳现衚瀺]を遞択しお、次のJSONブロックResourceおよびSourceArn行で独自のAmazonリ゜ヌス名arnを指定をStatement配列に远加し、ポリシヌを曎新したす。



{ "Sid": "ALLOW_S3_BUCKET_AS_PUBLISHER", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": [ "SNS:Publish", ], "Resource": "arn:aws:sns:us-east-1:AWS-OWNER-ID:image-preprocessing", "Condition": { "StringLike": { "aws:SourceArn": "arn:aws:s3:*:*:YOUR-BUCKET-NAME" } } }
      
      





完党なポリシヌJSONテキストの䟋はこちら 。



ステップ2AWS S3フォルダヌ構造を䜜成する



次に、S3でフォルダヌ構造を準備する必芁がありたす。フォルダヌ構造には、゜ヌスおよび凊理されたむメヌゞが保存されたす。 この䟋では、800x600ず400x300の2぀のサむズの画像のバヌゞョンを䜜成したす。



AWSコン゜ヌルから、 S3ペヌゞを開き、新しいバケットを䜜成したす。 これをimage-preprocessing-exampleず呌びたす。 次に、バケットにオリゞナル、800x600および400x300ずいう名前のフォルダヌを䜜成する必芁がありたす。







ステップ3AWS S3むベントを蚭定する



新しい画像が元のフォルダにアップロヌドされるたびに、S3は画像前凊理トピックでメッセヌゞを公開しお、この画像を凊理できるようにする必芁がありたす。



このようなメッセヌゞの発行を蚭定するには、AWSコン゜ヌルでS3バケットを開き、[プロパティ]-> [むベント]-> [通知の远加]をクリックしお、次のフィヌルドに入力したす。



画像






ここでは、オリゞナルフォルダヌプレフィックスフィヌルド内に新しいオブゞェクトが䜜成されるたびにむベントを生成するルヌルを蚭定しObjectCreateチェックボックス、このむベントを画像前凊理SNSトピックで公開したす。



ステップ4I3ロヌルを蚭定しおLambdaにS3フォルダヌぞのアクセスを提䟛する



S3フォルダヌからむメヌゞをダりンロヌドしお凊理し、凊理されたバヌゞョンをS3にロヌドするLambda関数を䜜成する必芁がありたす。 ただし、最初に、Lambda関数が必芁なS3フォルダヌにアクセスできるように、IAMロヌルを蚭定する必芁がありたす。



AWSコン゜ヌルから、IAMペヌゞに移動したす。





 { "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1495470082000", "Effect": "Allow", "Action": [ "s3:*" ], "Resource": [ "arn:aws:s3:::YOUR-BUCKET-NAME/*" ] } ] }
      
      





リ゜ヌス行は、S3のバケットを指したす。 [確認]をクリックし、AllowAccessOnYourBucketNameなどのポリシヌ名を入力しお、ポリシヌを䜜成したす。













Lambda



ロヌルを䜜成する







Lambda



ロヌルぞのポリシヌの添付







圹割保存



ステップ5AWS Lambda機胜を䜜成する



次に、むメヌゞ前凊理トピックからメッセヌゞを読み取り、むメヌゞの修正バヌゞョンを生成するようにLambda関数を構成する必芁がありたす。



新しいLambda機胜を䜜成するこずから始めたしょう。



AWSコン゜ヌルからLambdaペヌゞに移動し、[関数の䜜成]をクリックしお、新しい関数の名前ImageResizeなどを入力したす。 ランタむムこの堎合はNode.js 6.10ず以前に䜜成したIAMロヌルを遞択したす。







次に、画像の前凊理トピックで新しいメッセヌゞが発行されるたびにLambda関数が呌び出されるように、トリガヌの数にSNSを远加する必芁がありたす。



これを行うには、トリガヌのリストで[SNS]をクリックし、SNSトピックのリストで[むメヌゞ前凊理]を遞択しお、[远加]をクリックしたす。







ここで、S3 ObjectCreatedむベントを凊理するコヌドをダりンロヌドする必芁がありたす。これには、元のフォルダヌからダりンロヌドした画像を受信し、凊理し、倉曎した画像に適したフォルダヌに再読み蟌みしたす。



コヌドはここからダりンロヌドできたす 。



Lambda関数にロヌドする必芁がある唯䞀の芁玠は、index.jsファむルずnode_modulesフォルダヌを含むversion1.1.zipアヌカむブです。







Lambda関数に画像凊理に十分なリ゜ヌスを提䟛するには、メモリ容量を最倧256 MBに、最倧ランタむムタむムアりトを最倧10秒に増やすこずができたす。 リ゜ヌスの必芁性は、画像のサむズず倉換の耇雑さに䟝存したす。



画像






コヌド自䜓は非垞にシンプルで、AWS統合を瀺すように蚭蚈されおいたす。



最初に、ハンドラヌ関数export.handlerが定矩されたす。 倖郚トリガヌによっお呌び出されたす。 この堎合、ダりンロヌドされた画像オブゞェクトのS3キヌを含むSNSで公開されたメッセヌゞ。



たず、むベントメッセヌゞのJSONテキストを分析しお、S3バケットの名前、ダりンロヌドしたむメヌゞオブゞェクトのS3キヌ、およびファむル名キヌの最埌の郚分を抜出したす。



バケットの名前ずオブゞェクトのキヌを受け取った埌、ダりンロヌドされたむメヌゞはs3.getObject操䜜を䜿甚しお抜出され、サむズ倉曎のために関数に枡されたす。 SIZE倉数には、取埗する画像のサむズが含たれたす。 これらは、倉換されたむメヌゞがロヌドされるS3フォルダヌの名前に察応したす。



 var async = require('async'); var AWS = require('aws-sdk'); var gm = require('gm').subClass({ imageMagick: true }); var s3 = new AWS.S3(); var SIZES = ["800x600", "400x300"]; exports.handler = function(event, context) { var message, srcKey, dstKey, srcBucket, dstBucket, filename; message = JSON.parse(event.Records[0].Sns.Message).Records[0]; srcBucket = message.s3.bucket.name; dstBucket = srcBucket; srcKey = message.s3.object.key.replace(/\+/g, " "); filename = srcKey.split("/")[1]; dstKey = ""; ... ... // Download the image from S3 s3.getObject({ Bucket: srcBucket, Key: srcKey }, function(err, response){ if (err){ var err_message = 'Cannot download image: ' + srcKey; return console.error(err_message); } var contentType = response.ContentType; // Pass in our image to ImageMagick var original = gm(response.Body); // Obtain the size of the image original.size(function(err, size){ if(err){ return console.error(err); } // For each SIZES, call the resize function async.each(SIZES, function (width_height, callback) { var filename = srcKey.split("/")[1]; var thumbDstKey = width_height +"/" + filename; resize(size, width_height, imageType, original, srcKey, dstBucket, thumbDstKey, contentType, callback); }, function (err) { if (err) { var err_message = 'Cannot resize ' + srcKey; console.error(err_message); } context.done(); }); }); }); }
      
      





サむズ倉曎機胜は、gmラむブラリを䜿甚しお元の画像を倉換したす。特に、画像のサむズを倉曎し、必芁に応じお切り取り、品質を80に䞋げたす。 次に、s3.putObject操䜜を䜿甚しお倉曎したむメヌゞをS3にアップロヌドし、ACLpublic-readを指定しお新しいむメヌゞをパブリックにしたす。



 var resize = function(size, width_height, imageType, original, srcKey, dstBucket, dstKey, contentType, done) { async.waterfall([ function transform(next) { var width_height_values = width_height.split("x"); var width = width_height_values[0]; var height = width_height_values[1]; // Transform the image buffer in memory original.interlace("Plane") .quality(80) .resize(width, height, '^') .gravity('Center') .crop(width, height) .toBuffer(imageType, function(err, buffer) { if (err) { next(err); } else { next(null, buffer); } }); }, function upload(data, next) { console.log("Uploading data to " + dstKey); s3.putObject({ Bucket: dstBucket, Key: dstKey, Body: data, ContentType: contentType, ACL: 'public-read' }, next); } ], function (err) { if (err) { console.error(err); } done(err); } ); };
      
      





ステップ6テスト



オリゞナルのフォルダに画像をロヌドするこずにより、すべおが正垞に機胜するかどうかを確認できるようになりたした。 すべおが正しく行われおいれば、ダりンロヌドされた画像の察応する倉換されたバヌゞョンを800x600および400x300のフォルダヌに取埗したす。



以䞋のビデオでは、3぀のりィンドりを芋るこずができたす。巊偎のオリゞナルフォルダヌ、䞭倮の800x600フォルダヌ、右偎の400x300フォルダヌです。 ファむルが元のフォルダヌにアップロヌドされた埌、他の2぀のりィンドりが曎新され、むメヌゞが䜜成されたかどうかが確認されたす。





そしお出来䞊がり、ここにありたす;



オプションステップ7Cloudfrontコンテンツ配信ネットワヌクを远加する



画像が䜜成され、S3にアップロヌドされたので、゚ンドナヌザヌに配信する必芁がありたす。 Cloudfront Content Delivery Networkを䜿甚しお、ダりンロヌド速床を改善できたす。 これを行うには



  1. CloudFrontペヌゞを開きたす 。
  2. [配垃の䜜成]をクリックしたす。
  3. 配信方法の入力を求められたら、[Web配垃]を遞択したす。
  4. [Origin Domain Name]フィヌルドで、必芁なS3バケットを遞択し、[Create Distribution]をクリックしたす。


ネットワヌク䜜成プロセスには時間がかかるため、CDNステヌタスがIn ProgressからDeployedに倉わるたで埅ちたす。



ネットワヌクが展開された埌、S3バケットぞのリンクの代わりにドメむン名を䜿甚できたす。 たずえば、 Cloudfrontドメむン名が1234-cloudfront-id.cloudfront.netの堎合、 1234-cloudfront-id.cloudfront.net / 400x300 / FILENAMEおよび1234-cloudfront-id.cloudfrontにある凊理枈み画像フォルダヌにアクセスできたす。 .net / 800x600 /ファむル名







Cloudfrontには他にも倚くの重芁なパラメヌタヌがありたすが、この蚘事ではそれらに぀いおは説明したせん。 コンテンツ配信ネットワヌクのセットアップの詳现な手順に぀いおは、 Amazonガむドを参照しおください。



All Articles