Slide 1

Slide 1 text

2016 Fuller, Inc. All Rights Reserved. Mobile App Transformation with ECS 1 2016/12/14

Slide 2

Slide 2 text

2016 Fuller, Inc. All Rights Reserved. Introduction 2

Slide 3

Slide 3 text

2016 Fuller, Inc. All Rights Reserved. 3

Slide 4

Slide 4 text

2016 Fuller, Inc. All Rights Reserved. Takahiro Fujiwara (@wutali) 4

Slide 5

Slide 5 text

2016 Fuller, Inc. All Rights Reserved. About Joren 5

Slide 6

Slide 6 text

Fuller, Inc. All Rights Reserved ネットだろうとリアルだろうと、サービスをやっている人な ら誰もが思うこと。それは、「お客様には一見さんではな く、常連さんになってもらいたい。」 そんな願いを叶えるために、Joren(ジョウレン)は生まれま した。 私たちは、”ジョウレン”という言葉を世界中に広げ、世界中 のサービス提供者と利用者の距離を限りなく縮めることを目 指しています。

Slide 7

Slide 7 text

2016 Fuller, Inc. All Rights Reserved. 7 Jorenは、ウェブサイトのURLを入れるだけで、 魔法のようにアプリをつくれるサービスです。 ウェブサイトをスマホアプリに一発変換!

Slide 8

Slide 8 text

Fuller, Inc. All Rights Reserved Our Customers 8 パーソナルブログ ニュースメディア 音楽メディア テックメディア スポーツチーム コミュニティへの情報発信 大規模イベント ライフスタイルメディア Rockshot (UK) VScripts (India) J-POP SUMMIT (US) Lamar (US) Greenz ルーター芸人ブログ アルビレックス BB Rabbits Lifenet Journal

Slide 9

Slide 9 text

Fuller, Inc. All Rights Reserved 9 Optimised user experience by each platforms

Slide 10

Slide 10 text

Fuller, Inc. All Rights Reserved 10 Not web view

Slide 11

Slide 11 text

Fuller, Inc. All Rights Reserved Joren system architecture 11 Joren 管理ツール Android ( Java ) Joren System iOS ( Swift ) ③データ送信 Not web view 対象ウェブサイト ②アクセス コンテンツ取得 ①アプリ化したい  サイトのURLを入力 コンテンツ デザイン プッシュ通知

Slide 12

Slide 12 text

Fuller, Inc. All Rights Reserved 12

Slide 13

Slide 13 text

2016 Fuller, Inc. All Rights Reserved. AWS and Joren 13

Slide 14

Slide 14 text

Fuller, Inc. All Rights Reserved 14 Joren = + +

Slide 15

Slide 15 text

Fuller, Inc. All Rights Reserved AWS services for Joren 15 1. ECS (with Golang) -> APIとSQSのConsumerは全てECS上で管理 2. SQS -> クローラーの管理やDBアップデートに利用 3. DynamoDB -> 全てのデータをAPI毎にDynamoDBで管理 4. S3 -> クローリングしたコンテンツを保存 5. Lambda (with Python) -> 小さなバッチ処理に利用 6. ALB -> ECSでAPIを提供するために利用 7. SNS -> プッシュを送るために利用 8. CloudFormation -> 全てのAWSの構成を管理 9. CloudFront -> 静的サイトのホスティングに利用 10. CloudWatch Logs -> ECSのログ管理に利用

Slide 16

Slide 16 text

Fuller, Inc. All Rights Reserved ECS services 16 合計で17のサービスが起動・AWSと連携 -> RESTful APIs -> Crawling Workers -> Database Syncing Workers -> Push Notification Senders -> Web Structure Analysers

Slide 17

Slide 17 text

2016 Fuller, Inc. All Rights Reserved. Problems 17

Slide 18

Slide 18 text

Fuller, Inc. All Rights Reserved 18 What kind of tech problems we have when we started the project?

Slide 19

Slide 19 text

2016 Fuller, Inc. All Rights Reserved. Problems we wanna solve … (1) 19 インフラとWeb APIは全て一人で対応する -> インフラ管理 -> Web API開発 -> クローラー開発 -> 自動ビルド連携

Slide 20

Slide 20 text

2016 Fuller, Inc. All Rights Reserved. Problems we wanna solve … (2) 20 小さなチームから初めて、大きく育てたい -> チームメンバーの増加 -> アプリ数の増加 -> トラフィックの増加

Slide 21

Slide 21 text

2016 Fuller, Inc. All Rights Reserved. Problems we wanna solve … (3) 21 多くの外部システムと連携する -> App Storeの情報更新と監視 -> Google Playの情報更新と監視 -> iOSとAndroidの自動ビルド -> Zendeskとの連携 -> Push Notificationの送信

Slide 22

Slide 22 text

2016 Fuller, Inc. All Rights Reserved. Joren System Architecture 22

Slide 23

Slide 23 text

Fuller, Inc. All Rights Reserved 23 $POTPMF "1* $POTPMF 1SFWJFX "QQ $SBXMFS "1* "OBMZ[FS "1* 4UPSF "1* "QQT "1* #JUSJTF "OESPJE #VJME "1* $VTUPNFS "QQT $VTUPNFS "QQT &OEVTFS "QQT 6TFS 8FC4JUFT 6TFS 8FC4JUFT $VTUPNFS 8FC4JUFT #JUSJTF J04 J5VOFT $POOFDU (PPHMF 1MBZ $SBXMFS 8PSLFS $SBXMFS 8PSLFS $SBXMFS 8PSLFS "OBMZ[FS 8PSLFS "OBMZ[FS 8PSLFS "OBMZ[FS 8PSLFS &OEVTFS $VTUPNFS

Slide 24

Slide 24 text

Fuller, Inc. All Rights Reserved 24 $POTPMF "1* $POTPMF 1SFWJFX "QQ $SBXMFS "1* "OBMZ[FS "1* 4UPSF "1* "QQT "1* USJTF ESPJE #VJME "1* "QQT "QQT "QQT 6TFS 6TFS 6TFS USJTF 04 5VOFT POOFDU PHMF MBZ $SBXMFS 8PSLFS $SBXMFS 8PSLFS $SBXMFS 8PSLFS "OBMZ[FS 8PSLFS "OBMZ[FS 8PSLFS "OBMZ[FS 8PSLFS

Slide 25

Slide 25 text

Fuller, Inc. All Rights Reserved 25 過去のシステムの話

Slide 26

Slide 26 text

Fuller, Inc. All Rights Reserved When our project started … 26 * API毎にインスタンスが起動 -> APIとワーカーは同じEC2インスタンスで管理、複数のサービスが走る状態 * インスタンスは独自のスクリプトで管理 -> Pythonとboto3、cloud-intの仕組みを使って、初期化・スタート * デプロイ時にはインスタンスを丸ごと置き換える -> インスタンスを丸ごと置き換える処理をPythonのスクリプトに書く * Internal APIの連携はVPCとRoute 53を活用 -> VPCの設定とRoute53のPrivateなDNSレコードを作って連携

Slide 27

Slide 27 text

Fuller, Inc. All Rights Reserved 27 現在のシステムの話

Slide 28

Slide 28 text

Fuller, Inc. All Rights Reserved 28 $POTPMF "1* $POTPMF 1SFWJFX "QQ $SBXMFS "1* "OBMZ[FS "1* 4UPSF "1* "QQT "1* USJTF ESPJE #VJME "1* "QQT "QQT "QQT 6TFS 6TFS 6TFS USJTF 04 5VOFT POOFDU PHMF MBZ $SBXMFS 8PSLFS $SBXMFS 8PSLFS $SBXMFS 8PSLFS "OBMZ[FS 8PSLFS "OBMZ[FS 8PSLFS "OBMZ[FS 8PSLFS

Slide 29

Slide 29 text

Fuller, Inc. All Rights Reserved Our project for now! 29 * 全てECSクラスタ上で管理 -> 17のサービスが起動 * CircleCI上でecs-deployを実行・自動デプロイ -> GithubにPushすると、自動でDockerイメージをビルド・デプロイ * APIの設定とECSなどの構成の置き換えはCFnで行う -> ステージングと本番環境を切り替えられるCFn定義ファイルを用意 * Internal APIの連携はALBを活用 -> API毎に個別にポートを割り振り、Internal ALBがネットワークを管理

Slide 30

Slide 30 text

Fuller, Inc. All Rights Reserved CFn Setting Example (YAML) 30 Mappings: EnvToConfigs: staging: AccessToken: “staging-token” CrawlerApiPort: “3030” CrawlingLimit: “3” S3Bucket: “stg-bucket” production: AccessToken: “production-token” CrawlerApiPort: “3030” CrawlingLimit: “10” S3Bucket: “prd-bucket”

Slide 31

Slide 31 text

Fuller, Inc. All Rights Reserved CFn Setting Example (YAML) 31 Resources: TaskDefinition: Type: AWS::ECS::TaskDefinition Properties: ContainerDefinitions: - Name: CrawlerAPI Image: !Sub "${AWS::AccountId}.dkr.ecr.us-east-1.amazonaws.com/fuller-inc/walker:latest" Cpu: 50 Memory: 50 Command: - webapi Environment: - Name: PORT Value: !FindInMap [EnvToConfigs, !Ref Env, CrawlerApiPort] - Name: LIMIT Value: !FindInMap [EnvToConfigs, !Ref Env, CrawlerLimit]

Slide 32

Slide 32 text

Fuller, Inc. All Rights Reserved 32 1. クローラーの実装と管理 2. アプリストアとの連携 3. iOSとAndroidのアプリをビルド

Slide 33

Slide 33 text

Fuller, Inc. All Rights Reserved 33 クローラーの実装と管理

Slide 34

Slide 34 text

Fuller, Inc. All Rights Reserved About Our Crawler Project 34 * Crawlerも全てGolangで実装 -> GolangはWebとの親和性が非常に高い、クローラーの実装も容易 * 管理するRESTful APIとWorkerを同じリポジトリで管理 -> リポジトリが増えないようにWorkerとAPIは同じプロジェクトとして管理 * API間は全てJSONでやり取り -> データのやり取りがわかりやすく、実装しやすいJSONフォーマットで * Restful APIのインターフェースはGolangの公開パッケージ -> Console APIにCrawler APIの依存関係を作る -> そうすることで、インターフェース変更時にバグることが少なくなった

Slide 35

Slide 35 text

Fuller, Inc. All Rights Reserved Gaoling Code Example 35 import ( “http”, “github.com/fuller-inc/nwatch”, ) func main() { data := &nwatch.HookData{ URL: “https://google.com/”,
 Status: “succeed”, } if err := WebHook(); err != nil { panic(err)
 }
 } func WebHook(data *nwatch.HookData) error { _, err := http.Post(“http://joren.internal:8051/v1/hooks/data”, “application/json”, data) return err }

Slide 36

Slide 36 text

Fuller, Inc. All Rights Reserved 36 アプリストアとの連携

Slide 37

Slide 37 text

Fuller, Inc. All Rights Reserved About Our Store API 37 * CrawlerのRESTful APIと同じ構成 -> Golangで実装、JSONインターフェースを持ったRestful APIを実装 * ECSクラスタ上に、Chrome Driverを起動 -> ストアの情報入力やSubmitを全てこのChrome Driverにやらせる * Chrome DriverとStore APIもJSONでやり取り -> Golangから、JSON Wired ProtocolでChrome Driverを操作

Slide 38

Slide 38 text

Fuller, Inc. All Rights Reserved 38 アプリビルドの話

Slide 39

Slide 39 text

Fuller, Inc. All Rights Reserved About Our App Building 39 * Build APIも全てGolangで実装 -> Bitriseの状態を管理するシンプルな実装 * Store APIとBitrise間もJSONフォーマットで連携 -> シンプルなフォーマットでビルドリクエストをBitrise APIに投げる -> Bitriseから成功・失敗のCallbackを状態管理用のAPIで受け取る * Bitriseは便利 -> Mac OSが走るのでBitriseを使っている -> Workflowを複数定義できるので、複雑な処理をするのに便利

Slide 40

Slide 40 text

Fuller, Inc. All Rights Reserved 40 + 開発メンバーが増えた話 + 機能追加の話

Slide 41

Slide 41 text

Fuller, Inc. All Rights Reserved Team Building & Service Enhancement 41 * ドメイン = リポジトリ -> ドメインをアプリリリースで必要な作業毎に定義 -> さらにドメイン = リポジトリにすることで、チームメンバーの作業を明確化 -> 現在、サーバーサイドだけで6リポジトリを運用 * 開発メンバーが増えると、1リポジトリ毎に作業を分担 -> 開発開始時から2名、サーバーサイドのエンジニアが増えた -> 現在、Analyzer APIとStore APIは別のメンバーが開発・改善 * シンプルに始めて、少しずつ改善 -> Analyzer APIは始め、DBに保存されたクローラーの定義ファイルを返していだけ -> 今はサイトを解析して、クローラーの定義ファイルを自動生成 -> そもそも、始めは全てのドメインをチームメンバーが手作業で行っていた

Slide 42

Slide 42 text

Fuller, Inc. All Rights Reserved 42 $POTPMF "1* $POTPMF 1SFWJFX "QQ $SBXMFS "1* "OBMZ[FS "1* 4UPSF "1* "QQT "1* #JUSJTF "OESPJE #VJME "1* $VTUPNFS "QQT $VTUPNFS "QQT &OEVTFS "QQT 6TFS 8FC4JUFT 6TFS 8FC4JUFT 6TFS 8FC4JUFT #JUSJTF J04 J5VOFT $POOFDU (PPHMF 1MBZ $SBXMFS 8PSLFS $SBXMFS 8PSLFS $SBXMFS 8PSLFS "OBMZ[FS 8PSLFS "OBMZ[FS 8PSLFS "OBMZ[FS 8PSLFS

Slide 43

Slide 43 text

Fuller, Inc. All Rights Reserved 43 $POTPMF "1* $POTPMF 1SFWJFX "QQ $SBXMFS "1* "OBMZ[FS "1* 4UPSF "1* "QQT "1* #JUSJTF "OESPJE #VJME "1* $VTUPNFS "QQT $VTUPNFS "QQT &OEVTFS "QQT 6TFS 8FC4JUFT 6TFS 8FC4JUFT 6TFS 8FC4JUFT #JUSJTF J04 J5VOFT $POOFDU (PPHMF 1MBZ $SBXMFS 8PSLFS $SBXMFS 8PSLFS $SBXMFS 8PSLFS "OBMZ[FS 8PSLFS "OBMZ[FS 8PSLFS "OBMZ[FS 8PSLFS

Slide 44

Slide 44 text

Fuller, Inc. All Rights Reserved 44

Slide 45

Slide 45 text

Fuller, Inc. All Rights Reserved 45 $POTPMF "1* $POTPMF 1SFWJFX "QQ $SBXMFS "1* "OBMZ[FS "1* 4UPSF "1* "QQT "1* #JUSJTF "OESPJE #VJME "1* $VTUPNFS "QQT $VTUPNFS "QQT &OEVTFS "QQT 6TFS 8FC4JUFT 6TFS 8FC4JUFT 6TFS 8FC4JUFT #JUSJTF J04 J5VOFT $POOFDU (PPHMF 1MBZ $SBXMFS 8PSLFS $SBXMFS 8PSLFS $SBXMFS 8PSLFS "OBMZ[FS 8PSLFS "OBMZ[FS 8PSLFS "OBMZ[FS 8PSLFS

Slide 46

Slide 46 text

Fuller, Inc. All Rights Reserved 46 $POTPMF "1* $POTPMF 1SFWJFX "QQ $SBXMFS "1* "OBMZ[FS "1* 4UPSF "1* "QQT "1* #JUSJTF "OESPJE #VJME "1* $VTUPNFS "QQT $VTUPNFS "QQT &OEVTFS "QQT 6TFS 8FC4JUFT 6TFS 8FC4JUFT 6TFS 8FC4JUFT #JUSJTF J04 J5VOFT $POOFDU (PPHMF 1MBZ $SBXMFS 8PSLFS $SBXMFS 8PSLFS $SBXMFS 8PSLFS "OBMZ[FS 8PSLFS "OBMZ[FS 8PSLFS "OBMZ[FS 8PSLFS

Slide 47

Slide 47 text

Fuller, Inc. All Rights Reserved 47 $POTPMF "1* $POTPMF 1SFWJFX "QQ $SBXMFS "1* "OBMZ[FS "1* 4UPSF "1* "QQT "1* #JUSJTF "OESPJE #VJME "1* $VTUPNFS "QQT $VTUPNFS "QQT &OEVTFS "QQT 6TFS 8FC4JUFT 6TFS 8FC4JUFT 6TFS 8FC4JUFT #JUSJTF J04 J5VOFT $POOFDU (PPHMF 1MBZ $SBXMFS 8PSLFS $SBXMFS 8PSLFS $SBXMFS 8PSLFS "OBMZ[FS 8PSLFS "OBMZ[FS 8PSLFS "OBMZ[FS 8PSLFS

Slide 48

Slide 48 text

Fuller, Inc. All Rights Reserved 48

Slide 49

Slide 49 text

Fuller, Inc. All Rights Reserved 49

Slide 50

Slide 50 text

2016 Fuller, Inc. All Rights Reserved. Summary & Next Step 50

Slide 51

Slide 51 text

Fuller, Inc. All Rights Reserved Today’s summary 51 1. Golangがマイクロサービスと相性○ -> Golangだけで気軽に簡単にRESTful APIを作れる 2. Golang + ECSでさらに相性◎ -> RESTful APIを気軽にGolangで作って、気軽にECSにデプロイできる 3. 各APIの作業範囲を作業ベースで決める -> 多くのリポジトリを作らずに開発・運用できる 4. YAML対応したCFnは非常に便利 -> APIの設定値の環境毎の設定・変更が非常にわかりやすく書けるようになった 5. マイクロサービスを意識して設計すると作業を分担しやすい -> 機能追加・改善を少しずつ行える

Slide 52

Slide 52 text

Fuller, Inc. All Rights Reserved We wanna develop and solve more things. 52 1. アプリストア操作の自動化 -> 紹介したけど、絶賛開発中。あと少し。 2. CloudFormationの自動更新 -> CFnをGitでPushした時に自動で更新するようにしたい。CodeBuildを使いたい。 3. Joren Analyticsを実装 -> CloudWatch Logs上のログ解析をそろそろ始めたい。 4. クローラーのスケーリング -> アプリ数が増えてきたので、クローラーを自動スケーリングさせたい。 5. Jorenの常連を増やす -> 当たり前にサービス利用者とアプリ数を増やしたい。増やす準備はできた!

Slide 53

Slide 53 text

2016 Fuller, Inc. All Rights Reserved. ありがとうございましたm(_ _)m 53