8
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

サーバーレスなDropboxアプリの構築例 "LightFile for Dropbox"

Last updated at Posted at 2018-10-04

LightFile for Dropbox

Jpeg画像を劣化を感じない範囲でいい感じに再圧縮してDropboxの空き容量を稼ごうぜ、という処理を自動で行うDropboxサーバーアプリです。

LightFile for Dropbox
screenshot.png

Dropboxアプリというとスマホクライアントアプリを想像しますが、豊富なAPIを使ってDropboxをファイルシステムとするサーバーアプリも独自に開発することができます。

LightFile for Dropboxではこれをサーバーレスクラウドネイティブに構築しました。

急にユーザーが増えたら自動的にインフラが拡張されるし、誰も使わなければコストがかからない。しかも僕らは何も保守しなくていいともうエンジニアをダメにする楽ちんさです。

ほとんど定石ではあるんですが、利用技術を紹介します。Dropbox上のファイルを自動処理するアプリや、サーバーレスなWebアプリを設計する上での参考になれば幸いです。

利用技術

処理の概要

大まかな処理の流れです。

ログイン

OAuth2によるごく普通の認証・認可のフローです。Dropbox側にアプリケーションを登録し、アプリのIDとシークレットを用意する必要があります。

login-flow.png

ファイルの変更検知と処理

ファイルの変更はWebhooksで受信できます。後述しますが、Webhooks通知には速攻でレスポンスする必要があるので、時間のかかるファイル処理はSNSを経由して別のLambdaプロセスを起動します。

file-flow.png

インフラ

AWSのマネージドサービスのみで構成されています。

いわゆるLAMPと対比するとこんな感じです。

  • Linux → AWS
  • Apache → API Gateway
  • MySQL → DynamoDB
  • PHP → Lambda + NodeJS
  • cron(非同期処理) → SNS

処理系 Lambda

言わずと知れたFaaS、サーバーレスアプリケーションの実行環境です。
プログラムを書いてデプロイすれば後は勝手に運用してくれる楽ちんさは麻薬的です。

Webゲートウェイ API Gateway

Lambda自体はOSでいうスクリプト言語に相当する処理系なので、HTTP経由でそれを公開するにはApacheやCGIのようなレイヤーが必要です。
それに該当するのがAPI Gatewayです。

REST APIの提供が主要な目的となるのでApacheといろいろ異なりますが、カスタムドメイン機能を用いてWebサーバー的な使い方もできます。

LambdaAPI Gatewayの操作は、Serverlessフレームワークがいい感じにやってくれます。

DNS Route53

AWSのDNSです。
任意のドメインからAPI Gatewayのカスタムドメインへのエイリアスを貼ることで、独自ドメインでのサービス展開が可能になります。

SSL証明書 Certificate Manager

AWSで稼働するサービス向けに、無償でSSL証明書を準備してくれます。
API Gatewayでカスタムドメインを用意するときに証明書が必要になります。
最終的にサービスを提供する独自ドメインをコモンネームとした証明書を取得します。

データベース DynamoDB

AWSが提供するスケーラブルなNoSQLです。今回のアプリでは、次の用途に使っています。

  • DropboxのユーザーIDとアクセストークンの保管
  • 処理済みファイルの再処理を防止したり変更を検知するためのリビジョンの保管

サーバーレスとはいえ、アクセストークンの保存に何らかのデータストアが必要です。

ファイル変更検知 Dropbox Webhooks

Dropbox上で予めURLを登録しておくと、ユーザーによるファイル操作を通知を受けることができます。
これをAPI Gatewayで受信し、Lambdaのプログラムを起動します。

非同期処理のためのメッセージング SNS

API Gateway経由でLambdaを実行する場合は、タイムアウトが30秒間という制約を受けます。
画像ファイルの処理に30秒間は心許なく、Dropboxにフォルダを追加されたときなどは大量のタスクが発生することがあります。

また、それ以前に(出典を失念してしまいましたが)Dropbox Webhooks側にも時間的な制約がありました。

更にはDropbox側でもWebhooksの送信先URLのヘルスチェックを実施しているようで、Webhooks URLが何度か応答しないと通知が停止される使用になっているようです。
実際に開発中に通知がこないなーと思ったら停止されていたことがありました。もちろんユーザー向けの管理画面から再度、有効にすることができます。

以上の理由で、Webhooksの受信時は速攻で応答しなければなりません。

そこで今回、実際にファイル操作を行う処理は、SNSを経由して非同期に起動することにしました。SNSのメッセージを通して、実際にファイルの変換処理を行うLambdaファンクションを起動します。

最近、LambdaがSQSにも対応したのでそちらでもよいと思います。

JavaScript

実行環境 Node.js

AWS Labmdaが伝統的にサポートするJavaScriptNode.jsを利用します。

自分がPythonにあまり詳しくないだけで、もちろん選択肢としてありです。むしろDropbox SDKのサポートはPythonの方が充実しているかもしれません。

Dropbox SDK dropbox

その名もdropboxというNPMモジュールが提供されています。

ユーザーのログインにより認証と認可を行うOAuth2の処理は他のモジュールで頑張らなければならないかなと思っていたら、その辺の処理もしっかりサポートしてくれます(リダイレクト先のURLやcodeからのアクセストークンの取得など)。便利!

このモジュールを利用してDropbox上のファイルのダウンロードや、処理したファイルのアップロードを行います。

Webアプリケーションフレームワーク Express

Node.jsでお馴染みのWebアプリケーションフレームワークです。

LambdaAPI GatewayでHTTPアクセスには対応できるのですが、往年のCGIのようなプリミティブさしかありません。

ヘッダーが、Cookieが、ファイルアップロードが、HTMLテンプレートが、といった処理を自力で頑張るのはしんどいし危険な香りがします。なのでExpressを利用します。

テンプレートエンジン Pug

これは好みですが、テンプレートエンジンには記述量が少ないPugを使用します。EJSなどでももちろん問題ありません。

#サーバーレスフレームワーク Serverless

権限管理、イベント設定、コードの継続的なデプロイなど、Lambdaを使うには付随して必要なことや手間が多く意外と大変です。

ユースケースをCloudFormationに落とし込んでまるっとサポートしてくれるのがサーバーレスフレームワークServerlessです。

最近はSAMの方がトレンドなんですかね、ちょっとキャッチアップできていませんが。

開発用Webサーバ serverless-offline

Serverlessのプラグインです。
API Gatewayの動作をシミュレートする簡易的なWebサーバーを立ち上げてくれます。開発時に必須のプラグインです。

Expressバインド serverless-express

Expressのミドルウェアが期待する入出力と、API Gateway + Lambdaのそれは大きく異なります。その変換を行う仕組みが必要です。

言ってもオブジェクト間のマッピングなので自分で頑張ることもできますが、既存のモジュールを使った方がよいでしょう。

このモジュールを使うと、Expressアプリケーションをラッピングした、API Gateway向けのLambdaハンドラを自動生成することができます。それをエクスポートするだけなので、Lambdaファンクションのハンドラファイルはかなりシンプルに記述できます。

8
9
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
8
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?