しゅがーブログ

技術ネタとか書いていけたらな…

Elasticsearch 6.8.X に上げるときの注意点

最近書いてなかったので、久しぶりに投稿

TL; DR

  • ヒープサイズのデフォルト値が2GBから1GBに変更になりました。
    • itamaeでjvm.optionsを管理している方は要注意。
    • デフォルト値の指定で書き換えを行っていると、書き換えされずデフォルト値のままElasticsearchが起動されます。
  • like_textからlikeへの変更
  • elasticsearch-railsのmongoidのimport処理で障害になった
    • importo処理を実行する
    • countクエリが走る
    • メタ情報で帰ってこないから素直にカウントしにいく

はじめに

EOLを向かえた5.X系から6.X系の最新までバージョンを上げました。 その時の注意点やクラスタの入れ替え方法をまとめました。

変更概要

ヒープサイズがデフォルト1GBに変更

Elasticsearch 5系のインストール時のデフォルトサイズは2GBとなっています。 しかし6系からデフォルト値は1GBに変更されています。

6系のリファレンスだとこんな感じです。

By default, Elasticsearch tells the JVM to use a heap with a minimum and maximum size of 1 GB. When moving to production, it is important to configure heap size to ensure that Elasticsearch has enough heap available.

基本的にクラスタを組んで一括で管理している方が多数だと思います。(itamaeやchefなどで) そういった方でデフォルト値から書き換えている方は注意してください。 sedで置き換えておりましたが、変更されていることに気づかず1台1GBのクラスタを組んでしまいました。

more_like_thislike_textがサポートされなくなった

シンプルにlike_textがなくなり、likeになりました。

[400] {"error":{"root_cause":[{"type":"parsing_exception","reason":"[mlt] query does not support [like_text]","line":1,"col":96}],"type":"parsing_exception","reason":"[mlt] query does not support [like_text]","line":1,"col":96},"status":400}

公式リファレンスでは見つけられず、そのままクラスタの入れ替えをしてしまいました。 後々GitHub上のIssueで発見しました。(ググっても見つけられなかった、というかページが見つからなかった)

resqueで非同期処理を実行していて、そちらで処理がコケていました。 また、残念なことにエラー検知システムの方でアラートが上がらず、発見したのが翌日でした。 幸いなことに致命的な処理ではなかったので、再実行すれば問題ありませんでした。

elasticsearch-railsのmongoidのimport処理で障害になった

シンプルにこんな処理を流してElasticsearchクラスタにDBにデータを流し込む処理を実行しました。

Hogehoge.__elasticsearch__.import

すると、数分の間にslow queryカウントが急激に増加し、webサーバが処理しきれなくなりサービスが完全ダウンしかけました。

scope.no_timeout.each_slice(batch_size) do |items|
  yield (preprocess ? self.__send__(preprocess, items) : items)
end

このeach_sliceってカウントクエリが走ります。 そのため、メタ情報でカウントが帰ってこない数え方だと純粋に数えに行きレスポンスが帰ってこなくなります。 データ量もそこそこあるcollectionだったので、余計遅くなりサービスダウンの障害となりました。

items = []
scope.no_timeout.each do |item|
  items << item
  if items.count >= batch_size
  yield (preprocess ? self.__send__(preprocess, items) : items)
    items.clear
  end
end

yield (preprocess ? self.__send__(preprocess, items) : items) if items.present?

最終的にはこんな感じのモンキーパッチを当てて対応しました。 バッチのデフォルトサイズ1000件まで配列に追加して、そのままyieldに投げ込むやり方に変更しました。

最後に

Beaking Changeは読みましょう!(読んでいたけど・・) どこで障害に起こっているかわからないため、エラー検知だけを信じず見れるところは見ましょう。