class: right, middle # APIGateway + Lambda で # マイクロサービスしてみた ###### [JAWS-UG アーキテクチャ専門支部 クラウドネイティブ分科会 CDP議論会 #10](http://jawsug-arch.connpass.com/event/34201/) ###### 2016.07.14 Fumihiko Hata --- # whoami ```Clojure {:name "畑史彦" :company "Stylerecipe, Inc" :services [{:name "スタレピ" :description "プロのスタイリストにコーディネートを相談!" :android true :ios true}] :langs [:java :ruby :clojure] :likes [:scrum :aws] } ``` --- # whoami ```Clojure {:name "畑史彦" :company "Stylerecipe, Inc" :services [`{:name "スタレピ"` `:description "プロのスタイリストにコーディネートを相談!"` `:android true` `:ios true}`] ;↑もともと外注だった。 :langs [:java :ruby :clojure] :likes [:scrum :aws] } ``` -- 自分は内製化のタイミングで入社。 * インフラ:EC2, RDS, S3, CloudSearch * サーバサイド:PHP * アプリ:Titanium --- * サーバサイドのすべてのアプリケーションがモノリシックに結合した構成 1. アプリ用API 2. Web用HTML 3. スタイリストさん用CMSサーバ 4. 内部向け管理画面 × 2種 -- * このリポジトリ内にはバッチのコードも同梱。 -- * ある変更が予期せぬ別の場所に影響する。 (※モノリスなことだけが原因ではない) --- class: middle ### 機能追加は、できるだけコードベースやアーキテクチャを分離したい。 ### (でも、サーバの管理コストが増えるの嫌...) --- class: middle ### サーバレス(APIGateway & Lambda)がまさに全部解決してくれるらしいという噂 -- ### 試してみた。 --- # Case 1 「某EC(A社)のデータ使えるようになるから、API叩いて商品をリコメンドしたい」 -- ### やること * 日次でAPIを叩いて、DBのリコメンド商品一覧を更新 するだけ。 --- background-image: url(img/recommend.jpg) # Case 1 --- # Case 1 ### バッチは、Lambdaで作れないだろうか。 -- スケジューラがあるみたいだし・・・ -- ### 検証・・・ --- # Case 1 ### 結果 見送り。 -- ### 分かったこと 0. RDS(VPC内)へアクセスするには、設定に1工夫必要だった。 0. 上記に関係するのか、RDSへのアクセスが遅いことがたまにある?。 0. 実際に実行されるLambdaの各プロセスは独立しているので、都度コネクションがはられるっぽい。 →コネクションプーリングなどの概念はない。 0. Lambdaの処理時間は5分でタイムアウト。 → 長いバッチ処理に適用するなら、工夫が必要。 --- --- # Case 2 「コーディネート・レシピのページをShareすると、画像が切れちゃっているんですが・・」 -- ### 原因 * ogp や twitter card の meta タグで指定してる画像が、規定の縦横比になっていない。 → FacebookやTwitter側で上下が切り取られてしまう。。 --- background-image: url(img/share.jpg) # Case 2 --- # Case 2 ### 対策案 1. 既存の画像数千枚を正しい縦横比に変換し 2. レシピを登録する機能(それ以外の画像UL処理のところにも)に画像変換を挿しこんでいく実装・・・ -- 面倒くさい・・・ --- # Case 2 ### 対策案その2 1. Share用の画像URLを APIGateway + Lambda へ向けて 2. リクエストされた時に、on the fly で画像を変換してレスポンス 3. Share用の画像は**SNS側でキャッシュされる**ので、こちらに要求されるスループットはゆるい。 -- とても、うまくいきました。 --- background-image: url(img/img-converter.jpg) --- # Case 2 サーバ側のコード修正はこれだけ。 ```php $ogp_img_url = $recipe['image'] ``` ↓ ```php $ogp_img_url = $converter_url . '?url=' . rawurlencode($recipe['image']) ``` --- # Case 2 * LambdaのNode.jsは、**ImageMagick**がデフォで使えた。 -- * Nodeのバージョンが4.3.2なので、ES6は部分的なサポート。(Babel使おう) -- * APIGatewayは、バイナリ(画像)をレスポンスできなかった。 → 生成した画像をS3において`302`でS3のURLへ動的にリダイレクトさせた。 -- * APIGatewayが受け取ったデータをどうLambdaに流すかの設定が、ちょっと独特の記法。 --- # Case 2 * 正常系として複数のステータスコードを使うことができなかった。 1. `200 OK`で生成した画像の情報をJsonで返す 2. `302 Found`で生成した画像のURLにリダイレクト → `302`のほうは、**生成した画像のURLをエラーメッセージとして**APIGatewayに返して `Location: integration.response.body.errorMessage` というマッピングで実現。(もっとまともな方法がありそう) --- # Case 2 * メモリを結構割り当てないと、処理に時間がかかり過ぎた(特に、デプロイ後の初回のリクエスト) 結局、**1024MB**、**Timeout15秒**の設定で稼働中。 --- # Case 3 「提携アパレルECサイトの商品クローリングを、アドホックに行える機能作って」 -- ### 理由 * 提携しているアパレルさんの商品データを、日次でクローリングしているが、このバッチが不安定。。 --- # Case 3 ### 実装案 1. クローリング・バッチのリプレースも見据えて、**スクレイピングのロジックはLambdaに分離**。 2. APIGatewayをかぶせて、API化 3. 管理画面は、このAPIを叩くだけ。 -- うまくいきました。 --- background-image: url(img/scraping.jpg) --- # Case 3 * 今回は、NodeではなくClojureで実装してみた。 -- * デプロイ後の初回起動がいっそう遅い。。。JVMだから? -- * APIGatewayをローカルでモックする良い手段が無かった。 (使ってないけど、NodeにはLibraryがある) --- # まとめと感想 -- * 👍 サーバ作るの手軽すぎて、もはや「サーバーサイドエンジニアレス」になってきてる気がする・・・ -- * 👍 安い。特にアクセスが少ない場合。 -- * 👍 サーバ管理から解放される。 -- * 👍 キャパシティ・プランニングから解放される。 -- * 👻 ハマりどころは結構ある。 各種制限、timeout設定、最初のリクエストだけ遅い件、インテグレーション、ローカル・テスト環境、etc... -- * 👻 decentralized なサービス以外とは相性悪いっぽい。コネクションの問題。 * ✅: RDS, ElastiCache... * ❎: DynamoDB, S3, CloudSearch?... --- class: center, middle はまりどころもあるけどサーバレス構成便利! --- class: center, middle Thanks for listening! ---