Slide 1

Slide 1 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 1/56 AWS と KOTLIN で作るクローラー AWS と KOTLIN で作るクローラー azihsoyn 2019/02/26 scouty Crawler Night 2019

Slide 2

Slide 2 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 2/56 趣味 釣り アニメ 今期はかぐや様は告らせたい 上野さんは不器用 業務ではサーバーサイドエンジニア Go Kotlin っていうポッドキャストやってます 自己紹介 自己紹介 ふそやん@azihsoyn rehash.fm

Slide 3

Slide 3 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 3/56

Slide 4

Slide 4 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 4/56 もあります! グノスポ

Slide 5

Slide 5 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 5/56

Slide 6

Slide 6 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 6/56 テックブログもあるので是非読んでみてください 導入編 AppSync 編 デザイン編 サーバー編 インフラ編

Slide 7

Slide 7 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 7/56 今回話すこと 今回話すこと グノスポで作ったクローラーのレシピ クローラーの知見

Slide 8

Slide 8 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 8/56 今回話すクローラーの定義 今回話すクローラーの定義 クローラーは提携メディアのフィードを定期的 にクロール 提携メディアはグノスポが定めたフォーマット (Atom/RSS2.0) でフィードを作成 (google bot みたいに無差別にクロールするわけでは ない)

Slide 9

Slide 9 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 9/56 グノスポのサーバーサイドのアーキテクチャ グノスポのサーバーサイドのアーキテクチャ

Slide 10

Slide 10 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 10/56 クローラーはこれだけ クローラーはこれだけ

Slide 11

Slide 11 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 11/56 使っているライブラリ 使っているライブラリ

Slide 12

Slide 12 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 12/56 使っているライブラリ 使っているライブラリ XML PARSER + HTTP CLIENT XML PARSER + HTTP CLIENT

Slide 13

Slide 13 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 13/56 XML PARSER + HTTP CLIENT XML PARSER + HTTP CLIENT RETROFIT + JAXB RETROFIT + JAXB

Slide 14

Slide 14 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 14/56 XML PARSER + HTTP CLIENT XML PARSER + HTTP CLIENT retrofit 公式のconverter がある retrofit-conberers/jaxb

Slide 15

Slide 15 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 15/56 XML PARSER + HTTP CLIENT XML PARSER + HTTP CLIENT private val retrofit: Retrofit by lazy { Retrofit.Builder() .baseUrl("https://dummy.gunosy.sport/") .addConverterFactory(JaxbConverterFactory.create() .addCallAdapterFactory(RxJava2CallAdapterFactory.c .build() interface FeedClient { @GET fun getRSS(@Url url: String): Observable @GET fun getAtom(@Url url: String): Observable }

Slide 16

Slide 16 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 16/56 XML PARSER + HTTP CLIENT XML PARSER + HTTP CLIENT data class でxml の構造を定義 @XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement @JaxbPojo // noarg用annotation data class RSS( @XmlAttribute val version: String, @JaxbPojo val channel: Channel )

Slide 17

Slide 17 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 17/56 NOARG とは NOARG とは kotlin のdata class にデフォルト引数を書かなくて済 むようになるplugin no-arg-compiler-plugin

Slide 18

Slide 18 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 18/56 XML PARSER + HTTP CLIENT XML PARSER + HTTP CLIENT 呼び出し retrofit.create(FeedClient::class.java).getRSS(url).subscribe( /* 処理 */ }, { error -> error.printStackTrace() })

Slide 19

Slide 19 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 19/56 その他検討した XML PARSER その他検討した XML PARSER 最近 になった 一部のxml がパースできなかったため不採用 javax.xml.parsers 一部のxml がパースできなかったため不採用 retrofit-converter-simplexml FasterXML/jackson-module-kotlin

Slide 20

Slide 20 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 20/56 HTML PARSER HTML PARSER

Slide 21

Slide 21 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 21/56 HTML PARSER HTML PARSER これはほぼ一択 特にハマることもなく使えた html 内の画像のパスを書き換えたりするのに利用 JSOUP JSOUP

Slide 22

Slide 22 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 22/56 HTML PARSER HTML PARSER // 本文内 画像 val doc = Jsoup.parse(rawArticle.content, "UTF-8") doc.select("img").map { img -> try { val image = uploadImage(img.attr("src").toString()) img.attr("src", image.url) img.attr("data-gs-width", image.width.toString()) img.attr("data-gs-height", image.height.toString()) } catch (e: Exception) { e.printStackTrace() } }

Slide 23

Slide 23 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 23/56 ファイル形式検出 ファイル形式検出

Slide 24

Slide 24 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 24/56 ファイル形式検出 ファイル形式検出 画像のファイル識別に利用 アプリが対応している画像だけをサーバーに保 存 メディアが間違えておかしなファイルを指定 してしまったときに弾く MIME-UTIL MIME-UTIL

Slide 25

Slide 25 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 25/56 使ってる AWS サービス 使ってる AWS サービス

Slide 26

Slide 26 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 26/56 クローリング編 クローリング編

Slide 27

Slide 27 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 27/56 LAMBDA LAMBDA クロールする処理をlambda 関数として実行 java 8 ランタイム メトリクスも自動で取れるので監視などが楽

Slide 28

Slide 28 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 28/56 REKOGNITION REKOGNITION 画像をアプリのリストに表示する際に選手の顔 がちゃんと表示されるようにする 認識に1 秒もかからないぐらい早い

Slide 29

Slide 29 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 29/56 DYNAMODB DYNAMODB クロールした各種情報の保存 提携メディアのfeed テーブル クロールした記事のarticle テーブル 試合情報 チーム情報 …etc

Slide 30

Slide 30 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 30/56 DYNAMODB DYNAMODB 現在lambda から気軽に使えるデータ永続化サー ビスは実質DynamoDB しか選択肢がない Data API for Aurora Serverless が東京リージョンに きたら一部乗り換える予定 参考: https://dev.classmethod.jp/cloud/aws/amazon- aurora-serverless-avaible-http-endpoint/

Slide 31

Slide 31 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 31/56 DYNAMODB DYNAMODB DynamoDB を使う上で問題になるのはどうやって ユニークなID を発番するか article ごとに一意なキーが必要 今回は をカスタマイズして利用 snowflake

Slide 32

Slide 32 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 32/56 SNOWFLAKE とは SNOWFLAKE とは twitter が採用している( いた?) id 生成ロジック グノスポではtimestamp 部 + feed_id 部 + incr 部か ら生成 lambda は必ずfeed_id 毎に実行 同じfeed_id でlambda が同時に走らないことが 前提

Slide 33

Slide 33 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 33/56 S3 S3 画像や記事本文を保存 CLOUDWATCH LOGS CLOUDWATCH LOGS lambda のログはすべてcloudwatch logs に流す が出たのでとても便利 CloudWatch Logs Insight

Slide 34

Slide 34 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 34/56 スケジューリング編 スケジューリング編

Slide 35

Slide 35 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 35/56 CLOUDWATCH EVENTS CLOUDWATCH EVENTS クローラー毎に異なるスケジュールを設定 コンテンツの特性に合わせる 試合中の情報は1 分( 最短) 間隔 試合のスケジュールは1 時間 記事の更新は10 分 とか

Slide 36

Slide 36 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 36/56 SQS SQS 同じlambda を異なるパラメータで同時に実行し たいときに利用 feed 毎の記事の収集 試合中のデータの更新 cludwatch events → lambda( ジョブをキューイン グ) → SQS → lambda( クロール) を使うと が できる Amazon SQS FIFO メッセージ重複排除

Slide 37

Slide 37 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 37/56 作り方終わり 作り方終わり

Slide 38

Slide 38 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 38/56 知見の話 知見の話

Slide 39

Slide 39 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 39/56 クローラー、肥大化してませんか? クローラー、肥大化してませんか?

Slide 40

Slide 40 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 40/56 サービスに新しい機能やコンテンツを サービスに新しい機能やコンテンツを 追加するためにクローラーは改修が多 追加するためにクローラーは改修が多 くなりがち くなりがち

Slide 41

Slide 41 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 41/56 増えるif 文 増えるフラグ 増えるエンティティ 増える依存関係 増えるデータベース …etc

Slide 42

Slide 42 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 42/56 管理できていれば問題ない 管理できていれば問題ない

Slide 43

Slide 43 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 43/56 今流行りのクリーンアーキテクチャ

Slide 44

Slide 44 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 44/56 いい本なので読みましょう いい本なので読みましょう ( クリーンアーキテクチャでクローラーを作りまし ょうという話じゃないです)

Slide 45

Slide 45 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 45/56 責務を分ける 責務を分ける

Slide 46

Slide 46 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 46/56 もう一度サーバーサイドのアーキテクチャの確認 もう一度サーバーサイドのアーキテクチャの確認

Slide 47

Slide 47 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 47/56 こうしてしまいがち こうしてしまいがち

Slide 48

Slide 48 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 48/56 全部クローラー!! 全部クローラー!!

Slide 49

Slide 49 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 49/56 今回設計の段階でクロールした生データとアプ リケーションから参照されるデータは別にしよ うというルールにした ( 深く考えていたわけではないがAppSync を使う 上でこうなった) アプリケーションから参照されるデータはpre process というフローで生成する クローラーはxml をパースして画像をS3 にアップ ロードしてDynamoDB にデータを保存することに 専念する

Slide 50

Slide 50 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 50/56 クローラーは XML をパースして画像を クローラーは XML をパースして画像を S3 にアップロードして DYNAMODB にデ S3 にアップロードして DYNAMODB にデ ータを保存することに専念する ータを保存することに専念する

Slide 51

Slide 51 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 51/56 シンプル!! シンプル!!

Slide 52

Slide 52 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 52/56 まとめ まとめ

Slide 53

Slide 53 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 53/56 使ってるライブラリ 使ってるライブラリ Retrofit + JAXB Jsoup mime-util noarg

Slide 54

Slide 54 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 54/56 使ってる AWS サービス 使ってる AWS サービス lambda SQS CloudWatch Events CloudWatch Logs S3 DynamoDB rekognition

Slide 55

Slide 55 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 55/56 責務を分ける 責務を分ける

Slide 56

Slide 56 text

2019/2/26 AWS とKotlin で作るクローラー http://localhost:10000/?print-pdf#/ 56/56 THANKS! THANKS!