kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Amazon Elasticsearch Service で Elasticsearch 2.3.2 にレストランデータを投入して遊んだ

Amazon Elasticsearch Service を試してみた

近々導入する可能性もあって,検証も兼ねて,先月に Elasticsearch 2 系に対応した Amazon Elasticsearch Service を試してみた.

Elasticsearch domain を作成する

作成完了までのステップは計4個ある.

  • Step 1: Define domain
  • Step 2: Configure cluster
  • Step 3: Set up access policy
  • Step 4: Review

今回は以下のスペックで作成した.実際に運用する環境なら Node を増やして,Storage は gp2 以上にして,インスタンスタイプはユースケースに応じて考える必要がある.

  • Domain Name
    • Elasticsearch domain name
      • kakakakakku
  • Version
    • Elasticsearch version
      • 2.3
  • Node configuration
    • Instance count
      • 1
    • Instance type
      • t2.micro.elasticsearch (Free tier eligible)
  • Storage configuration
    • Storage type
      • EBS
    • EBS volume type
      • Magnetic
    • EBS volume size
      • 10

実際に起動 (Configuration state: Active) されるまでに10分程度待った.

起動後の状態を確認する

Elasticsearch 2.3.2 になっていた.

$ curl https://search-kakakakakku-xxx.ap-northeast-1.es.amazonaws.com/
{
  "name" : "Ringleader",
  "cluster_name" : "354924239642:kakakakakku",
  "version" : {
    "number" : "2.3.2",
    "build_hash" : "0944b4bae2d0f7a126e92b6133caf1651ae316cc",
    "build_timestamp" : "2016-05-20T07:46:04Z",
    "build_snapshot" : false,
    "lucene_version" : "5.5.0"
  },
  "tagline" : "You Know, for Search"
}

Amazon Elasticsearch Service の制約として,任意のプラグインをインストールすることはできないけど,analysis-kuromoji と kibana は入っていた.head 系は入ってないんだなぁ...!

$ curl https://search-kakakakakku-xxx.ap-northeast-1.es.amazonaws.com/_cat/plugins
Ringleader analysis-icu        2.3.2 j
Ringleader analysis-kuromoji   2.3.2 j
Ringleader cloud-aws           2.3.2 j
Ringleader elasticsearch-jetty 2.2.0 j
Ringleader kibana              2.3.2 s /_plugin/kibana/

ドキュメントを登録する

試しに適当なドキュメントを登録してみた.普通に動いた.

$ curl -X PUT https://search-kakakakakku-xxx.ap-northeast-1.es.amazonaws.com/blog/articles/1 -d '
quote> {
quote>   "title": "xxx",
quote>   "body": "yyy",
quote>   "tags": ["z1", "z2"]
quote> }
quote> ' | jq .
{
  "_index": "blog",
  "_type": "articles",
  "_id": "1",
  "_version": 1,
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "created": true
}

$ curl https://search-kakakakakku-xxx.ap-northeast-1.es.amazonaws.com/blog/articles/1 | jq .
{
  "_index": "blog",
  "_type": "articles",
  "_id": "1",
  "_version": 1,
  "found": true,
  "_source": {
    "title": "xxx",
    "body": "yyy",
    "tags": [
      "z1",
      "z2"
    ]
  }
}

レストランデータをバルクで投入する

去年個人的に作った Elasticsearch ハンズオン資料に沿って,レストランデータをバルクで投入してみた.詳しくはハンズオン資料を参照で!

github.com

まず,マッピングを登録する.登録したマッピングは管理コンソールから確認することができる.

$ curl -X POST https://search-kakakakakku-xxx.ap-northeast-1.es.amazonaws.com/gourmet -d @mappings/restaurants.json
{"acknowledged":true}%

f:id:kakku22:20160824212959p:plain

加工したデータをバルクで投入したところエラーになった.ハンズオン資料に書いてある通り,独自構築の Elasticsearch なら elasticsearch.ymlhttp.max_content_length を広げることで対応できるけど,Amazon Elasticsearch Service の場合はインスタンスタイプによって制限されていた.

$ curl -X POST https://search-kakakakakku-xxx.ap-northeast-1.es.amazonaws.com/_bulk --data-binary @bulk_restaurants.json
{"Message":"Request size exceeded 10485760 bytes"}%

ドキュメントだと Maximum size of HTTP request payloads の部分に書いてあって,t2.micro.elasticsearch の場合だと 10 MB になっていた.もしバッチで大量のバルクをする可能性があるならインスタンスタイプの設計時に考慮しておくと良さそう.

docs.aws.amazon.com

今回はデータ量を100件に減らして投入することができた.

$ curl -X POST https://search-kakakakakku-xxx.ap-northeast-1.es.amazonaws.com/_bulk --data-binary @bulk_restaurants_100.json

レストランデータにクエリを投げてみる

普通にクエリを投げたら「application/x-www-form-urlencoded の場合はクエリストリングを使えないよ」とエラーになった.調べたら elasticsearch-rubyElastica など各言語の Elasticsearch ライブラリに類似の Issues が出ていた.ふむ.

$ curl https://search-kakakakakku-xxx.ap-northeast-1.es.amazonaws.com/gourmet/restaurants/_search\?pretty -d '
quote> {
quote>   "query": {
quote>     "match": { "name": "焼肉" }
quote>   }
quote> }
quote>
quote> '
{"message":"When Content-Type:application/x-www-form-urlencoded, URL cannot include query-string parameters (after '?'): '/gourmet/restaurants/_search?pretty'"}%

今回は application/x-www-form-urlencoded ではなく,意図的に application/json を指定して回避した.ワークアラウンド的な気もする.ちゃんとレストラン名に「焼肉」を含んでいる結果を取得することができた.

$ curl -H 'Content-Type:application/json' https://search-kakakakakku-xxx.ap-northeast-1.es.amazonaws.com/gourmet/restaurants/_search\?pretty -d '
{
  "query": {
    "match": { "name": "焼肉" }
  }
}
'
{
  "took" : 77,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 0.79930615,
    "hits" : [ {
      "_index" : "gourmet",
      "_type" : "restaurants",
      "_id" : "20",
      "_score" : 0.79930615,
      "_source" : {
        "id" : "20",
        "name" : "焼肉フランス人",
        "property" : null,
        "alphabet" : null,
        "name_kana" : "やきにくふらんすじん",
        "pref_id" : "13",
        "area_id" : "7",
        "station_id1" : "3289",
        "station_time1" : "3",
        "station_distance1" : "220",
        "station_id2" : "8918",
        "station_time2" : "10",
        "station_distance2" : "772",
        "station_id3" : "2778",
        "station_time3" : "11",
        "station_distance3" : "848",
        "category_id1" : "402",
        "category_id2" : "0",
        "category_id3" : "0",
        "category_id4" : "0",
        "category_id5" : "0",
        "zip" : null,
        "address" : "港区六本木3-10-9ABIC六本木ビル3F",
        "north_latitude" : "35.39.36.421",
        "east_longitude" : "139.44.11.411",
        "description" : null,
        "purpose" : null,
        "open_morning" : "0",
        "open_lunch" : "0",
        "open_late" : "0",
        "photo_count" : "0",
        "special_count" : "0",
        "menu_count" : "0",
        "fan_count" : "0",
        "access_count" : "1452",
        "created_on" : "2000-09-10 11:22:02",
        "modified_on" : "2011-04-22 02:00:15",
        "closed" : "1"
      }
    } ]
  }
}

N-Gram と形態素解析を確認する

全文検索をするなら必須の日本語処理も確認してみた.

N-Gram

今回は 2Gram と 3Gram でマッピングを定義していて,正常に動いた.

$ curl -H 'Content-Type:application/json' https://search-kakakakakku-xxx.ap-northeast-1.es.amazonaws.com/gourmet/_analyze\?tokenizer\=ngram_tokenizer\&pretty -d '東京都渋谷区で勤務しています' | grep token
  "tokens" : [ {
    "token" : "東京",
    "token" : "東京都",
    "token" : "京都",
    "token" : "京都渋",
    "token" : "都渋",
    "token" : "都渋谷",
    "token" : "渋谷",
    "token" : "渋谷区",
    "token" : "谷区",
    "token" : "谷区で",
    "token" : "区で",
    "token" : "区で勤",
    "token" : "で勤",
    "token" : "で勤務",
    "token" : "勤務",
    "token" : "勤務し",
    "token" : "務し",
    "token" : "務して",
    "token" : "して",
    "token" : "してい",
    "token" : "てい",
    "token" : "ていま",
    "token" : "いま",
    "token" : "います",
    "token" : "ます",

形態素解析

analysis-kuromoji を使った形態素解析も正常に動いた.

$ curl -H 'Content-Type:application/json' https://search-kakakakakku-xxx.ap-northeast-1.es.amazonaws.com/gourmet/_analyze\?tokenizer\=kuromoji\&pretty -d '東京都渋谷区で勤務しています' | grep token
  "tokens" : [ {
    "token" : "東京",
    "token" : "",
    "token" : "渋谷",
    "token" : "",
    "token" : "",
    "token" : "勤務",
    "token" : "",
    "token" : "",
    "token" : "",
    "token" : "ます",

Kibana を試してみた

Amazon Elasticsearch Service には Kibana もデフォルトで同梱されていて,普通に使うことができた.バージョンは Kibana Version 4.1.2-es-2.0 となっていた.

f:id:kakku22:20160824211707p:plain

運用面を考える

稼働中のクラスタも Configure cluster でインスタンスタイプやディスクサイズを変更することができる.CloudSearch と違って自動スケールはしないため,CloudWatch でモニタリングしながら判断する必要がある.実際にインスタンスタイプを t2.micro.elasticsearch から t2.small.elasticsearch に変更してみたら,起動時と同様に10分程度待たされたけど,変更できた.

ちなみにインスタンスタイプの変更中も定期的にクエリを投げてみて 5xx 系が返ってくることは無かった.Amazon Elasticsearch Service は無停止でインスタンスタイプの変更ができるという理解で良いのだろうか?(追記 : FAQ にダウンタイムが無いと記載されていた)

Q: Amazon Elasticsearch ドメインをスケーリングするにはダウンタイムが必要ですか? いいえ。インスタンスおよびストレージボリュームの追加または変更による Amazon Elasticsearch ドメインのスケーリングはオンライン操作であり、ダウンタイムは必要ありません。

aws.amazon.com

CloudWatch で取得できるメトリクスは充実してて良さそうだった.

f:id:kakku22:20160824212629p:plain

その他はドキュメントにまとまっている.Amazon Elasticsearch Service のドキュメントは現時点だと日本語に翻訳されてなかった.

docs.aws.amazon.com

まとめ

Maximum size of HTTP request payloadsURL cannot include query-string parameters に少しハマったけど,普通にフルマネージドな Elasticsearch になっていて良かった.個人的に Elasticsearch は仕様や運用面で複雑だなと感じるところもあって,クラスタ運用を AWS に任せられるのはメリットだと思う.Reindex API などはまだ使えないらしく,今後のアップデートに期待したいところ.

あと個人的に作った Elasticsearch ハンズオン資料が便利だった(自画自賛).バージョンは 1.7 想定で作ってるけど,特にバージョンに依存しないような機能だけを使ってるので,今後 Elasticsearch に入門しようと思ってる人がいたら是非!

github.com

Black Belt

Amazon Elasticsearch Service の Black Belt 資料も合わせて読んでみた.

  • Dedicated Master Nodes
    • Split-brain を考慮して3台構成に
  • Zone Awareness を ON にする
    • クラスタを AZ に分散できる
  • CloudSearch と Elasticsearch Service の比較
  • Elasticsearch 2.3 だと Doc Values がデフォルトで有効になっている

www.slideshare.net

あと去年の AWS re:Invent 2015 の資料もあった.

www.slideshare.net

関連記事

dev.classmethod.jp