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

Post on 20-Jun-2015

29.489 views 0 download

description

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

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

Elasticsearch+ DynamoDB

+Node.jsで作る全社基盤

http://www.flickr.com/photos/67810830@N07/8015511503/sizes/l/

あいのや なおき

相野谷 直樹 ainoya2013. 09~ リクルートテクノロジーズAWS 上でのシステム開発運用・検討など

アジェンダ

• 背景• システム構成• Elasticsearch の使い方• ログ可視化・モニタリングへの活用• まとめ

スマホアプリのための Push 通知基盤を作った話

Push 通知

スマホアプリのための Push 通知基盤

社員     API

Push!Push!

スマートデバイスへのプッシュ通知を実現するシステム

• Push 通知の典型的な機能– 全デバイス指定配信

– デバイス指定

– 条件指定

• リクルートの全アプリを対象

• 社内のビックデータ基盤とスムーズに連携させるために自分たちで開発

Push通知

社員     API

Push!

システム構成

全体のシステム構成

•AWS

インフラ•E

lastic Beanstalk

デプロイ

•Cloudformation

構成管理

•Node.js

開発言語

•DynamoDB

DB

•Elasticsearch

検索

DynamoDB

Elasticsearchクラスタ

デバイス登録  リクエスト

APNs/GCMサーバ

登録 API

データ登録

Push 配信 リクエスト

配信者

配信worker

SQS

SQS登録worker

配信者側 Web アプリ

システム管理・操作用Web UI管理 API

プッシュ配信基盤システム構成

データ参照

DynamoDB

Elasticsearchクラスタ

デバイス登録  リクエスト

APNs/GCMサーバ

登録 API

データ登録

Push 配信 リクエスト

配信者

配信worker

SQS

SQS登録worker

配信者側 Web アプリ

システム管理・操作用Web UI管理 API

プッシュ配信基盤システム構成

データ参照

スマホアプリが自社 SDK 経由でプッシュ配信基盤にデバイス情報を登録

DynamoDB

Elasticsearchクラスタ

デバイス登録  リクエスト

APNs/GCMサーバ

登録 API

データ登録

Push 配信 リクエスト

配信者

配信worker

SQS

SQS登録worker

配信者側 Web アプリ

システム管理・操作用Web UI管理 API

プッシュ配信基盤システム構成

データ参照

デバイス情報をDynamoDB( マスターデータ ) とElasticsearch クラスタに登録

DynamoDB

Elasticsearchクラスタ

デバイス登録  リクエスト

APNs/GCMサーバ

登録 API

データ登録

Push 配信 リクエスト

配信者

配信worker

SQS

SQS登録worker

配信者側 Web サーバ

システム管理・操作用Web UI管理 API

プッシュ配信基盤システム構成

データ参照

配信者 or 配信側 Web サーバがPush 配信リクエスト

DynamoDB

Elasticsearchクラスタ

デバイス登録  リクエスト

APNs/GCMサーバ

登録 API

データ登録

Push 配信 リクエスト

配信者

配信worker

SQS

SQS登録worker

配信者側 Web サーバ

システム管理・操作用Web UI管理 API

プッシュ配信基盤システム構成

配信者 or 配信側 Web サーバがPush 配信リクエスト

配信タイプに応じてDynamoDB or Elasticsearchのデバイス情報を参照対象デバイスに Push 配信

DynamoDB

Elasticsearchクラスタ

デバイス登録  リクエスト

APNs/GCMサーバ

登録 API

データ登録

Push 配信 リクエスト

配信者

配信worker

SQS

SQS登録worker

配信者側 Web サーバ

システム管理・操作用Web UI管理 API

プッシュ配信基盤システム構成

① 配信者 or 配信側 Web サーバがPush 配信リクエスト

② 配信タイプに応じてDynamoDB or Elasticsearchのデバイス情報を参照対象デバイスに Push 配信

③• 全件指定配信• ID 指定配信

時にデータ参照

④条件検索指定配信

時にデータ参照

条件指定 Push の実現アプリごとに指定されたタグで対象デバイスを検索して Push

プッシュ配信 API

管理用 Web UI Push 配信条件を指定 ✔ 対象アプリ : アプリB   ✔起動回数 : 10 回以上 ✔ 年齢 : 18 歳以上

デバイス登録 API

Bアプリ B

{ “ アプリ起動回数” : 120, “ 好きなジャンル” : “ お笑い” , “ 年齢” :”18”}

付加情報 !

Elasticsearch が必要な理由

• DynamoDB は KVS → 検索が苦手• 検索エンジンが別途必要

• 多数アプリからの大規模な利用• 高速・スケーラブル

• アプリごとに自由な付加情報• スキーマレス

Elasticsearch の使い方

Elasticsearch で条件指定配信するために

クラスタ構成

性能• Scan• Node.jsとの組み合わせ• 更新

リストア

Elasticsearch クラスタ構成

– クラスタリング• ec2 プラグイン

– Auto scaling Group• min-size = max-size で台数を一定

化–MultiAZ 構成

• 2AZ に配置• Replica 数

– AZ 障害を想定– ceil(n/2)

» 4 台構成なら 2

Auto scaling Group

Availability Zone 1

Availability Zone 2

Internal ELB

性能• Scan• Node.jsとの組み合わせ• 更新

このシステムでの検索の特徴

•条件指定 Push•条件にヒットした全端末に Push•検索結果をすべて取得•ページングが必要•Scan を使用

search_type : scan• scan/scroll– 検索時にソートしないので Deep scrolling に強い– ページング時のデータ抜けも防げる

• 簡単な使い方Search_type=scan でリクエストを送ると scroll_id が返る

{ "hits": {…},…, "_scroll_id": "c2Nhbjs5…NzA0MDMxOw==“}

Elasticsearch が内部で作った Scroll objectの id

レスポンス :

curl -XGET 'localhost:9200/_search?search_type=scan&scroll=10m&size=50' –d $query

scroll_id を指定して検索結果セット (scroll object) を scroll していく

curl -XGET 'localhost:9200/_search/scroll?scroll=10m' –d $scroll_id

リクエスト毎に size 分だけの検索結果が返る{“hits”: {…},…}

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-search-type.html#scan

Scan/scroll 利用時のオプションなど最初の scan で scroll object を生成する時

‘localhost:9200/hoge_index/_search?search_type=scan&scroll=10m&size=50’ –d $query

scroll=10m

size=50

Elasticsearch 内部で Scroll Object を保持する期間

1 回の scroll リクエストで取り出す検索結果数※ Elasticsearch 内部では shard*size の件数ぶんだけ結果を引くので      ドキュメント数が多い場合やサーバのメモリが少ない場合は注意

Scroll 時 :

curl -XGET 'localhost:9200/_search/scroll?scroll=10m' –d $scroll_id

Index 指定の Scroll でも root path へのリクエストであることに注意

性能• Scan• Node.jsとの組み合わせ• 更新

Node.js から Elasticsearch を使う

• Elastical client

• 独自のスキーマ構成を反映した Wrapper を用意

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();});

var deviceIndex = exports.elasticSearch.indexes.deviceIndex;

deviceIndex.search(searchInfo.appId, query, options, function(err, total, hits) { if (err) { return cb(err); } cb(null, total, hits);});

Wrapper 側に用意した‘ deviceIndex’ のスキーマで       フィールドの型を js の型にマッピング

hits オブジェクトを 型付きの状態でそのまま利用できる     →煩雑な型定義からの解放

データ抽出 Stream

データ形式変換Stream

配信 Stream

配信処理レポートStream

Node.js の Stream で検索結果処理

Stream : データの流れを抽象化したインタフェース

検索から push 通知までの一連を非同期 I/O で実装して処理高速化           ➜ Stream API を使って簡潔に記述

Push 配信 Queue

条件指定

全件

ID指定

アプリ ID:xxx配信タイプ : 全件 /ID指定 /条件指定配信メッセージ :hogehoge

配信リクエスト

Push!

Push!

各処理の Stream を繋いでパイプライン化     対象を抽出しつつ配信を行う

各処理の Stream を繋いでパイプライン化        対象を抽出しつつ配信を行う

var searchStream = new SearchStream(query);              // scan/scroll 処理の stream 実装

// 検索結果を解釈して、 Push 配信を行い、配信結果を保存する SearchStream.pipe(transferStream) // データ変換用 stream .pipe(resultStream) //Push 配信 stream .pipe(resultStream); // 結果格納用の stream

Node.js の Stream で検索結果処理

性能• Scan• Node.jsとの組み合わせ• 更新

データ更新時の負荷平滑化

Auto scaling Group

Auto scaling Group

CloudWatch

CloudWatch

登録 API 登録 Workerデバイス登録

QueueELB

DynamoDB

Elasticsearch

EC2の CPU使用率に応じオートスケール

Queueのメッセージ数に応じオートスケール

リクエスト負荷がElasticsearch の更新性能を超え

る場合も安定稼働多数デバイスからの同時リクエスト

リストア

DynamoDB からのリストア• マスターデータはあくまで DynamoDB• Elasticsearch はいつ落ちても復旧できるようにしてお

DynamoDB

Elasticsearch

復旧スクリプト

まとめ

まとめ  • AWS 上で Elasticsearch を使った検索機

能   ✔ ec2 plugin   ✔ Internal ELB   ✔ Auto scaling group

➜ 簡単にクラスタ構築して利用可能

• Node.js から Elasticsearch を使う– JSON Object を扱いやすい

• JSON レスポンスの階層が深く結果の取り出しが若干大変– Stream で検索結果を効率よく処理             相性良いです➜

まとめ

ありがとうございました

採用募集