Elasticsearch+nodejs+dynamodbで作る全社システム基盤

52,057 views

Published on

2/7にリクルートテクノロジーズで行われた、elasticsearch勉強会での資料です。

Published in: Technology

Elasticsearch+nodejs+dynamodbで作る全社システム基盤

  1. 1. tp://www.flickr.com/photos/67810830@N07/8015511503/sizes/l/ Elasticsearch + DynamoDB +Node.js で作る全社基盤
  2. 2. あいのや なおき 相野谷 直樹 ainoya 2013. 09~ リクルートテクノロジーズ AWS上でのシステム開発運用・検討など
  3. 3. アジェンダ • • • • • 背景 システム構成 Elasticsearchの使い方 ログ可視化・モニタリングへの活用 まとめ
  4. 4. スマホアプリのためのPush通知基盤を 作った話
  5. 5. スマホアプリのためのPush通知基盤 Push通知 社員 API Push! Push!
  6. 6. スマートデバイスへのプッシュ通知を実現するシステム • Push通知の典型的な機能 – 全デバイス指定配信 – デバイス指定 Push 通知 Push ! – 条件指定 • リクルートの全アプリを対象 社員 API • 社内のビックデータ基盤とスムーズに連携させるために 自分たちで開発
  7. 7. システム構成
  8. 8. 全体のシステム構成 インフラ • AWS デプロイ • Elastic Beanstalk 構成管理 • Cloudformation 開発言語 • Node.js DB 検索 • DynamoDB • Elasticsearch
  9. 9. デバイス登録 リクエスト データ登録 登録API SQS 登録worker DynamoDB データ参照 APNs/GCM サーバ 配信worker SQS プッシュ配信基盤 システム構成 Elasticsearch クラスタ システム管理・操作用 Web UI 管理API Push配信 リクエス ト 配信者側Webアプリ 配信者
  10. 10. デバイス登録 リクエスト データ登録 登録API SQS 登録worker スマホアプリが 自社SDK経由で プッシュ配信基盤に デバイス情報を登録 APNs/GCM サーバ データ参照 配信worker SQS プッシュ配信基盤 システム構成 DynamoDB Elasticsearch クラスタ システム管理・操作用 Web UI 管理API Push配信 リクエス ト 配信者側Webアプリ 配信者
  11. 11. デバイス登録 リクエスト データ登録 登録API SQS 登録worker DynamoDB デバイス情報を DynamoDB(マスターデータ)と Elasticsearchクラスタに登録 データ参照 APNs/GCM サーバ 配信worker SQS プッシュ配信基盤 システム構成 Elasticsearch クラスタ システム管理・操作用 Web UI 管理API Push配信 リクエス ト 配信者側Webアプリ 配信者
  12. 12. デバイス登録 リクエスト データ登録 登録API SQS 登録worker DynamoDB データ参照 APNs/GCM サーバ 配信worker Elasticsearch クラスタ SQS システム管理・操作用 Web UI 管理API 配信者or配信側Webサーバが Push配信リクエスト プッシュ配信基盤 システム構成 Push配信 リクエス ト 配信者側Webサーバ 配信者
  13. 13. デバイス登録 リクエスト データ登録 配信タイプに応じて DynamoDB or Elasticsearch のデバイス情報を参照 対象デバイスにPush配信 SQS 登録worker 登録API APNs/GCM サーバ DynamoDB 配信worker Elasticsearch クラスタ SQS システム管理・操作用 Web UI 管理API 配信者or配信側Webサーバが Push配信リクエスト プッシュ配信基盤 システム構成 Push配信 リクエス ト 配信者側Webサーバ 配信者
  14. 14. デバイス登録 リクエスト ③ •全件指定配信 •ID指定配信 データ登録 時にデータ参照 ②配信タイプに応じて DynamoDB or Elasticsearch のデバイス情報を参照 対象デバイスにPush配信 SQS 登録worker 登録API APNs/GCM サーバ 配信worker SQS DynamoDB ④ 条件検索指定配信 時にデータ参照 Elasticsearch クラスタ システム管理・操作用 Web UI 管理API ①配信者or配信側Webサーバが Push配信リクエスト プッシュ配信基盤 システム構成 Push配信 リクエス ト 配信者側Webサーバ 配信者
  15. 15. 条件指定Pushの実現 アプリごとに指定されたタグで対象デバイスを検索してPush ! 付加情報 B { “アプリ起動回数”: 120, “好きなジャンル”: “お笑い”, “年齢”:”18” } アプリB デバイス登録API プッシュ配信API 管理用Web UI Push配信条件を指定 ✔ 対象アプリ:アプリB ✔ 起動回数: 10回以上 ✔ 年齢: 18歳以 上
  16. 16. Elasticsearchが必要な理由 • DynamoDBはKVS → 検索が苦手 • 検索エンジンが別途必要 • 多数アプリからの大規模な利用 • 高速・スケーラブル • アプリごとに自由な付加情報 • スキーマレス
  17. 17. Elasticsearchの使い方
  18. 18. Elasticsearchで条件指定配信するために クラスタ構成 性能 • Scan • Node.jsとの組み合わせ • 更新 リストア
  19. 19. Elasticsearchクラスタ構成 – クラスタリング • ec2プラグイン – Auto scaling Group • min-size = max-sizeで台数を一定化 – MultiAZ構成 Internal ELB • 2AZに配置 • Replica数 – AZ障害を想定 – ceil(n/2) » 4台構成なら2 Availability Zone 1 Availability Zone 2 Auto scaling Group
  20. 20. 性能 • Scan • Node.jsとの組み合わせ • 更新
  21. 21. このシステムでの検索の特徴 •条件指定Push •条件にヒットした全端末にPush •検索結果をすべて取得 •ページングが必要 •Scanを使用
  22. 22. search_type : scan • scan/scroll – 検索時にソートしないのでDeep scrollingに強い – ページング時のデータ抜けも防げる • 簡単な使い方 Search_type=scanでリクエストを送るとscroll_idが返る curl -XGET 'localhost:9200/_search?search_type=scan&scroll=10m&size=50' –d $query レスポンス: Elasticsearchが内部で作ったScroll { "hits": {…},…, "_scroll_id": "c2Nhbjs5…NzA0MDMxOw==‚ } objectのid scroll_idを指定して検索結果セット(scroll object)をscrollしていく curl -XGET 'localhost:9200/_search/scroll?scroll=10m' –d $scroll_id リクエスト毎にsize分だけの検索結果が返る {‚hits‛: {…},…}
  23. 23. Scan/scroll利用時のオプションなど 最初のscanでscroll objectを生成する時 ‘localhost:9200/hoge_index/_search?search_type=scan&scroll=10m&size=50’ –d $query scroll=10m Elasticsearch内部でScroll Objectを保持する期間 size=50 1回のscrollリクエストで取り出す検索結果数 ※ Elasticsearch内部ではshard*sizeの件数ぶんだけ結果を引くので ドキュメント数が多い場合やサーバのメモリが少ない場合は注意 Scroll時: Index指定のScrollでもroot pathへのリクエストであることに注 意 curl -XGET 'localhost:9200/_search/scroll?scroll=10m' –d $scroll_id http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-search-type.html#scan
  24. 24. 性能 • Scan • Node.jsとの組み合わせ • 更新
  25. 25. Node.jsからElasticsearchを使う • Elastical client https://github.com/ramv/node-elastical var client = new elastical.Client('example.com', {port: 1234}); client.search({query: 'welcome'}, function (err, results, res) { do_something(); }); • 独自のスキーマ構成を反映したWrapperを用意 Wrapper側に用意した„deviceIndex‟のスキーマで フィールドの型をjsの型にマッピング var deviceIndex = exports.elasticSearch.indexes.deviceIndex; deviceIndex.search(searchInfo.appId, query, options, function(err, total, hits) { if (err) { hitsオブジェクトを return cb(err); 型付きの状態でそのまま利用できる } →煩雑な型定義からの解放 cb(null, total, hits); });
  26. 26. Node.jsのStreamで検索結果処理 検索からpush通知までの一連を非同期I/Oで実装して処理高速化 ➜Stream APIを使って簡潔に記述 Stream : データの流れを抽象化したインタフェース 配信リクエスト アプリID:xxx 配信タイプ: 全件/ID指定/ 条件指定 配信メッセージ:hogehoge 各処理のStreamを繋いでパイプライン化 対象を抽出しつつ配信を行う データ抽出Stream Push配信Queue 配信Stream データ形式変換 Stream 配信処理レポート Stream 条件指定 全件 ID指定 Push ! Push !
  27. 27. Node.jsのStreamで検索結果処理 各処理のStreamを繋いでパイプライン化 対象を抽出しつつ配信を行う var searchStream = new SearchStream(query); // scan/scroll処理のstream実装 //検索結果を解釈して、Push配信を行い、配信結果を保存する SearchStream.pipe(transferStream) .pipe(resultStream) .pipe(resultStream); //データ変換用stream //Push配信stream //結果格納用のstream
  28. 28. 性能 • Scan • Node.jsとの組み合わせ • 更新
  29. 29. データ更新時の負荷平滑化 EC2のCPU使用率に応じ オートスケール CloudWatc h Queueのメッセージ数に応じ オートスケール CloudWatc h DynamoDB ELB 登録API Auto scaling Group 多数デバイスからの 同時リクエスト デバイス登録 Queue 登録Worker Auto scaling Group Elasticsearch リクエスト負荷が Elasticsearchの更新性能を超え る場合も安定稼働
  30. 30. リストア
  31. 31. DynamoDBからのリストア • マスターデータはあくまでDynamoDB • Elasticsearchはいつ落ちても復旧できるようにしておく DynamoDB Elasticsearc h 復旧スクリプト
  32. 32. まとめ
  33. 33. まとめ • AWS上でElasticsearchを使った検索機能 ✔ ec2 plugin ✔ Internal ELB ✔ Auto scaling group ➜ 簡単にクラスタ構築して利用可 能
  34. 34. まとめ • Node.jsからElasticsearchを使う – JSON Objectを扱いやすい • JSONレスポンスの階層が深く結果の取り出しが若干大変 – Streamで検索結果を効率よく処理 ➜ 相性良いです
  35. 35. ありがとうございました
  36. 36. 採用募集

×