LoginSignup
0
0

SNS + SQS + Lambdaのファンアウト構成でサムネイルを作成する

Posted at

やりたいこと

画像がS3にアップロードされたときに、SNS + SQSのファンアウト構成でサイズ毎のサムネイル画像を並列処理で作成する。

スクリーンショット 2023-12-04 3.08.26.png

SNSトピックを作成

fanout-test というトピックを作成します。
スクリーンショット 2023-11-19 17.01.45.png

SQSを作成

fanout-test-small というSQSキューを作成し、fanout-testトピックにサブスクライブします。
スクリーンショット 2023-11-19 17.03.43.png

同様に、fanout-test-large というSQSキューを作成し、fanout-testトピックにサブスクライブします。

S3バケットを作成

S3バケットfanout-test-20231119を作成し、original small largeフォルダをあらかじめ作成しておきます。
スクリーンショット 2023-11-19 17.21.34.png

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 に通知を送るような
イベント通知を作成します。
スクリーンショット 2023-11-19 17.23.58.png
スクリーンショット 2023-11-19 17.24.04.png

ECRにイメージをpush

詳しくは下記を参照してください。

Dockerfile
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" ]
Gemfile
source 'https://rubygems.org'
gem 'image_processing'
lambda_function.rb
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を追加します。
スクリーンショット 2023-12-04 3.02.31.png

トリガーをSQSfanout-test-smallに設定します。
スクリーンショット 2023-12-04 3.02.05.png

同様にcreateLargeThumbnail関数も作成します。

S3に画像をアップロード

originalディレクトリに画像をアップロードすると、smallディレクトリ、largeディレクトリにサムネイル画像がアップロードされます。

スクリーンショット 2023-12-04 3.05.17.png

スクリーンショット 2023-12-04 3.05.26.png

スクリーンショット 2023-12-04 3.07.52.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0