|
| 1 | +# インターン課題 |
| 2 | +ピクシブ百科事典に表示される広告の最適化 |
| 3 | + |
| 4 | +## 概要 |
| 5 | +- ピクシブ百科事典の記事 (place) ごとに,各広告の表示回数 (impression) とコンバージョン数 (conversion) を保持して,コンバージョン率が最適になる広告を 3 つ求めるバンディット問題と考える |
| 6 | +- [Amazon API Gateway]( https://goo.gl/ha1f1a ) でリクエストを受け取り,[AWS Lambda]( http://goo.gl/avy4al ) を使って,DynamoDB に保存された情報を利用・更新して最適な広告を選んでいく |
| 7 | +- [Serverless Framework]( https://goo.gl/vMO6PI ) を使って,Amazon Gateway API から Amazon Lambda を利用している |
| 8 | + |
| 9 | + |
| 10 | +## エンドポイント一覧 |
| 11 | +パラメータの渡し方は Tool の項目を参考に. |
| 12 | +- /ads |
| 13 | + - GET |
| 14 | + - 概要: 広告の選択 |
| 15 | + - input: {place_id} |
| 16 | + - output: {3 つの広告の情報} (現在は JSONP で返却) |
| 17 | +- /conversion |
| 18 | + - GET |
| 19 | + - 概要: conversion を行ったことを記録 |
| 20 | + - input: {place_id, ads_id} |
| 21 | + - POST |
| 22 | + - 概要: conversion を行ったことを記録 |
| 23 | + - input: {place_id, ads_id} (JSON. body で指定する) |
| 24 | +- /admin |
| 25 | + - /ads |
| 26 | + - GET |
| 27 | + - 概要: 広告の一覧取得 |
| 28 | + - output: {すべての広告の情報} |
| 29 | + - /{ads_id} |
| 30 | + - DELETE |
| 31 | + - 概要: 表示する広告の削除 |
| 32 | + - input: {ads_id (pathで指定する)} |
| 33 | + - GET |
| 34 | + - 概要: 広告の情報を取得 |
| 35 | + - input: {ads_id (pathで指定する)} |
| 36 | + - outpu: 広告の情報 |
| 37 | + - PUT |
| 38 | + - 概要: 広告の新規登録・更新 |
| 39 | + - input: {ads_id (pathで指定する), ads_info (JSON. body で指定する)} |
| 40 | + - /places (これは現状ほとんど使わない) |
| 41 | + - /{place_id} |
| 42 | + - DELETE |
| 43 | + - 概要: 記事の削除 |
| 44 | + - input: {place_id (pathで指定する)} |
| 45 | + - PUT |
| 46 | + - 概要: 記事の追加 (存在する場合はなにもしない)./ads が代わりに追加してくれる |
| 47 | + - input: {place_id (pathで指定する)} |
| 48 | + |
| 49 | + |
| 50 | + |
| 51 | +## デプロイまで |
| 52 | +このレポジトリは Serverless の 1 つのプロジェクトとして作成している. |
| 53 | + |
| 54 | +### Serverless のセットアップ |
| 55 | +参考: [Serverless の基本的な使い方](http://qiita.com/susieyy/items/1c2af0ef7b88b742c37a) |
| 56 | + |
| 57 | +まずは,Serverless をインストールする. |
| 58 | + |
| 59 | +``` |
| 60 | +npm install serverless -g |
| 61 | +``` |
| 62 | + |
| 63 | +AWS でユーザ作成を行い,適切なポリシーを与えたグループにそのユーザを追加するか,ユーザに適切なポリシーを付与する. |
| 64 | +ユーザ作成時には,SERVERLESS_ADMIN_AWS_ACCESS_KEY_ID, SERVERLESS_ADMIN_AWS_SECRET_ACCESS_KEY を記録しておく. |
| 65 | + |
| 66 | +**(適切なポリシーを与えるところは大変でした…)** |
| 67 | + |
| 68 | +参考: |
| 69 | +- [IAMユーザを作成]( http://goo.gl/2D2cGT ) |
| 70 | +- [ユーザと管理グループの作成・ひも付け](http://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/getting-started_create-admin-group.html) |
| 71 | + - これはすべての権限を与える例なので非推奨ですが参考に |
| 72 | + |
| 73 | +適当なフォルダに移動して,Serverless の project を作成する. |
| 74 | + |
| 75 | +``` |
| 76 | +sls project create |
| 77 | +``` |
| 78 | + |
| 79 | +**(sls は serverless のエイリアス)** |
| 80 | + |
| 81 | +すると,以下のように対話的な項目の設定画面が現れる. |
| 82 | + |
| 83 | +``` |
| 84 | + _______ __ |
| 85 | +| _ .-----.----.--.--.-----.----| .-----.-----.-----. |
| 86 | +| |___| -__| _| | | -__| _| | -__|__ --|__ --| |
| 87 | +|____ |_____|__| \___/|_____|__| |__|_____|_____|_____| |
| 88 | +| | | The Serverless Application Framework |
| 89 | +| | serverless.com, v0.5.5 |
| 90 | +`-------' |
| 91 | +
|
| 92 | +Serverless: Initializing Serverless Project... |
| 93 | +Serverless: Enter a name for this project: (serverless-rkbtki) [プロジェクト名 (例: pixiv)] |
| 94 | +Serverless: Enter a new stage name for this project: (dev) [ステージ名 (例: dev)] |
| 95 | +Serverless: For the "dev" stage, do you want to use an existing Amazon Web Services profile or create a new one? |
| 96 | + Existing Profile |
| 97 | + > Create A New Profile [先ほど作成した新しいユーザを紐付けるのでこちら] |
| 98 | +Serverless: Please enter the ACCESS KEY ID for your Admin AWS IAM User: [記録した SERVERLESS_ADMIN_AWS_ACCESS_KEY_ID] |
| 99 | +Serverless: Enter the SECRET ACCESS KEY for your Admin AWS IAM User: [記録した SERVERLESS_ADMIN_AWS_SECRET_ACCESS_KEY] |
| 100 | +Serverless: Enter the name of your new profile: (pixiv_dev) [このユーザのプロファイル名 (例: pixiv)] |
| 101 | +Serverless: Creating stage "dev"... |
| 102 | +Serverless: Select a new region for your stage: |
| 103 | + us-east-1 |
| 104 | + us-west-2 |
| 105 | + eu-west-1 |
| 106 | + eu-central-1 |
| 107 | + > ap-northeast-1 [Tokyo リージョンはここ] |
| 108 | +Serverless: Creating region "ap-northeast-1" in stage "dev"... |
| 109 | +Serverless: Deploying resources to stage "dev" in region "ap-northeast-1" via Cloudformation (~3 minutes)... |
| 110 | +``` |
| 111 | + |
| 112 | +これで現在のフォルダに [プロジェクト名] のフォルダができる. |
| 113 | + |
| 114 | +### レポジトリのクローンからデプロイまで |
| 115 | +適当なフォルダで以下を実行. |
| 116 | +``` |
| 117 | +git clone git@github.com:pixiv/lambda-pudding.git |
| 118 | +``` |
| 119 | +上記で作成したプロジェクトの中身をすべて,このフォルダにコピー. |
| 120 | + |
| 121 | +フォルダの中にある s-resource-cf.json を編集して,IAM のポリシーを設定する. |
| 122 | +現在,以下のようになっているところを, |
| 123 | +``` |
| 124 | + "Resource": "arn:aws:dynamodb:[リージョン]:[アカウントID]:table/*" |
| 125 | +``` |
| 126 | +AWSアカウントのIDを基に変更して,テーブルへのアクセス権限を作る. |
| 127 | + |
| 128 | +アカウントID を知るためには,例えば,AWSコンソールのサービス一覧で IAM を選択し, |
| 129 | +[IAM users sign-in link:] の |
| 130 | + |
| 131 | +``` |
| 132 | +https://[アカウントID].signin.aws.amazon.com/console |
| 133 | +``` |
| 134 | + |
| 135 | +からわかる. |
| 136 | + |
| 137 | +変更したら |
| 138 | +``` |
| 139 | +sls resources deploy |
| 140 | +``` |
| 141 | +を行ってアップデートする. |
| 142 | + |
| 143 | +これで設定ができたのでデプロイする.以下のコマンドを実行. |
| 144 | +``` |
| 145 | +sls dash deploy |
| 146 | +``` |
| 147 | +すると,以下のように選べるので,必要なfunction&endpoint を選んでデプロイ. |
| 148 | +``` |
| 149 | +Serverless: Select the assets you wish to deploy: |
| 150 | + delete_item |
| 151 | + > function - delete_item |
| 152 | + endpoint - admin/ads/{ads_id} - DELETE |
| 153 | + show_item |
| 154 | + function - show_item |
| 155 | + endpoint - admin/ads/{ads_id} - GET |
| 156 | + show_items |
| 157 | + function - show_items |
| 158 | + endpoint - admin/ads - GET |
| 159 | + update_item |
| 160 | + function - update_item |
| 161 | + endpoint - admin/ads/{ads_id} - PUT |
| 162 | + add_place |
| 163 | + function - add_place |
| 164 | + endpoint - admin/places/{place_id} - PUT |
| 165 | + delete_place |
| 166 | + function - delete_place |
| 167 | + endpoint - admin/places/{place_id} - DELETE |
| 168 | + ads |
| 169 | + function - ads |
| 170 | + endpoint - ads - GET |
| 171 | + conversion |
| 172 | + function - conversion |
| 173 | + endpoint - conversion - POST |
| 174 | + - - - - - |
| 175 | + Deploy |
| 176 | + Cancel |
| 177 | +``` |
| 178 | + |
| 179 | +## API を叩く |
| 180 | +- URL/ endpoint名 |
| 181 | +- URLは例えば `https://************.execute-api.ap-northeast-1.amazonaws.com/dev/conversion` (conversionの場合) |
| 182 | + |
| 183 | + |
| 184 | +## テーブル構成 |
| 185 | + |
| 186 | +### テーブル一覧 |
| 187 | +使うテーブルは現状 3 つ. |
| 188 | +- ads_ids |
| 189 | + - 広告の id 一覧を持つテーブル |
| 190 | +- ads_contents |
| 191 | + - 広告の内容を持つテーブル |
| 192 | +- counter |
| 193 | + - 記事ごとの広告の表示回数などを持つテーブル |
| 194 | + |
| 195 | +### ads_ids |
| 196 | +広告の ID 一覧を 1 項目として持つテーブル |
| 197 | +- Partition key: dummy (Number) |
| 198 | + - 0 の 1 つだけがある |
| 199 | +- 属性 |
| 200 | + - ads の ID の一覧 (StringSet) |
| 201 | + |
| 202 | +### ads_contents |
| 203 | +広告の情報をもつテーブル |
| 204 | +- Partition key: ads_id (String) |
| 205 | +- 属性 |
| 206 | + - 広告の情報 |
| 207 | + |
| 208 | +### counter |
| 209 | +記事ごとに,広告の表示・コンバージョン回数をもつテーブル |
| 210 | +- Partition key: place_id (String) |
| 211 | +- 属性 |
| 212 | + - impression (Number) |
| 213 | + - ads (Map<ads_id, ads_count> |
| 214 | + - ads_count |
| 215 | + - c (Number) |
| 216 | + - i (Number) |
| 217 | + |
| 218 | + |
| 219 | +## Tool |
| 220 | +- tool/ 以下にテスト用の Ruby のスクリプトを入れてある |
| 221 | + |
| 222 | +### rest.rb |
| 223 | +サンプルとして数行記述してあるが,[REST Client]( https://goo.gl/VXLi32 ) を使って,リクエストを作成している. |
| 224 | + |
| 225 | + |
| 226 | +## TODO |
| 227 | +- Item の更新などのリクエストに認証を付ける |
| 228 | + - Header に認証用の Token を入れるという話だったがまだできていない |
| 229 | +- リファクタリング |
| 230 | + - 同じような関数の共通化をしたい |
| 231 | + - Response の値を正しくする |
| 232 | +- 不要な広告の削除 (compaction) |
| 233 | + - 要らなくなった広告は現状 ads_ids テーブルから項目を消すことで対処しているが,counter からも消したほうが良い |
| 234 | + - NOTE: この処理は,counter のすべての項目から属性 (ads) を削除する必要があるため,あまり頻度を多くしたくない |
| 235 | + - NOTE: この処理をしないと,counter テーブルの項目が大きくなった時に,料金が高くなる |
| 236 | + - 1 項目について,write は 1KB 単位,read は 4KB 単位で課金額が線形に伸びる |
| 237 | +- キャッシュ |
| 238 | + - 取得した項目をキャッシュしておきたい |
| 239 | + - NOTE: DynamoDB では操作する項目の数に比例した課金体系であるので,多くの項目に触ることはできるだけ減らしたほうが良い |
0 commit comments