やりたいこと
画像がS3にアップロードされたときに、SNS + SQSのファンアウト構成でサイズ毎のサムネイル画像を並列処理で作成する。
SNSトピックを作成
SQSを作成
fanout-test-small
というSQSキューを作成し、fanout-test
トピックにサブスクライブします。
同様に、fanout-test-large
というSQSキューを作成し、fanout-test
トピックにサブスクライブします。
S3バケットを作成
S3バケットfanout-test-20231119
を作成し、original
small
large
フォルダをあらかじめ作成しておきます。
SNSのアクセスポリシーを編集
イベント通知の送信先にSNSトピックを選択する場合、送信先のSNSのアクセスポリシーの編集が必要なので
SNSトピック fanout-test
に対して、下記のようなポリシーを追加します。
{
"Sid": "S3-policy",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "SNS:Publish",
"Resource": "arn:aws:sns:ap-northeast-1:<account id>:fanout-test",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:s3:::fanout-test-20231119"
}
}
}
イベント通知を作成
original
フォルダにファイルがアップロードされたときにSNSトピックfanout-test
に通知を送るような
イベント通知を作成します。
ECRにイメージをpush
詳しくは下記を参照してください。
FROM amazon/aws-lambda-ruby:latest
# EPELリポジトリを追加
RUN yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
# remiレポジトリを追加
RUN yum install -y https://rpms.remirepo.net/enterprise/remi-release-7.rpm
# libvipsとlibvipsを使うために必要なパッケージをインストール
RUN yum install -y install vips make gcc
COPY Gemfile Gemfile.lock ${LAMBDA_TASK_ROOT}
COPY lambda_function.rb ${LAMBDA_TASK_ROOT}
# /usr/local/bundleにGemをインストールする
ENV GEM_HOME=/usr/local/bundle
RUN bundle install
CMD [ "lambda_function.lambda_handler" ]
source 'https://rubygems.org'
gem 'image_processing'
require 'image_processing/vips'
require 'aws-sdk-s3'
require 'json'
def lambda_handler(event:, context:)
sizes = {
"small" => 200,
"large" => 600
}
# 画像データ取得
s3_client = Aws::S3::Client.new(:region => 'ap-northeast-1')
body = JSON.parse(event['Records'][0]['body'])
message = JSON.parse(body["Message"])
key = message["Records"][0]["s3"]["object"]["key"]
uploaded_data = s3_client.get_object(:bucket => ENV['BUCKET_NAME'], :key => key).body.read
# 画像リサイズ
uploaded_file = Vips::Image.new_from_buffer(uploaded_data, '')
size = sizes[ENV["SIZE"]]
resized_file_path = ImageProcessing::Vips.source(uploaded_file).resize_to_limit!(size, size).path
# アップロード実行
s3_resource = Aws::S3::Resource.new()
s3_resource.bucket(ENV['BUCKET_NAME']).object("#{ENV["SIZE"]}/#{File.basename(key)}").upload_file(resized_file_path)
end
Lambdaを作成
ECRのイメージから createSmallThumbnail
関数を作成します。
Lambdaの実行ロールにSQSFullAccessとS3FullAccessを追加します。
トリガーをSQSfanout-test-small
に設定します。
同様にcreateLargeThumbnail
関数も作成します。
S3に画像をアップロード
originalディレクトリに画像をアップロードすると、smallディレクトリ、largeディレクトリにサムネイル画像がアップロードされます。