ElasticSearchで java.lang.OutOfMemoryError のエラーが出た対応です。
検証のため、メモリ4Gのサーバーに72MのデータをBulkでアップデートした際にでたエラーの対応履歴となります。
OSはCentOS7系です。
実際に行ったのは以下のURLにある設定でマッピングまでを行いました。
https://colabmix.co.jp/tech-blog/elasticsearch-6-2/
1 2 3 4 |
$ curl -H "Content-Type: application/json" -X PUT 'http://XXX.XXX.XXX.XXX:9200/restaurant?pretty' -d @kuromoji_setting.json $ curl -H "Content-Type: application/json" -X PUT 'http://XXX.XXX.XXX.XXX:9200/restaurant/_mapping/type?pretty' -d @mapping_restaurant.json |
上記までは問題なく実行を行い、大きめのファイルのbulkでのアップデートを行った際に、クライアント側は以下のエラーとなりました。
1 2 3 4 5 6 7 8 9 10 11 |
$ time curl -H "Content-Type: application/json" -XPOST 'http://XXX.XXX.XXX.XXX:9200/restaurant/type/_bulk?pretty' --data-binary @restaurant_data.json > /dev/null % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 51 72.0M 0 0 51 37.0M 0 4567k 0:00:16 0:00:08 0:00:08 2841k curl: (56) Recv failure: Connection reset by peer real 0m8.399s user 0m0.048s sys 0m0.309s |
サーバー側では以下のログが出ています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
[2018-09-30T20:24:13,487][WARN ][o.e.x.s.t.n.SecurityNetty4HttpServerTransport] [R_oU9mA] caught exception while handling client http traffic, closing connection [id: 0x53b5beff, L:/153.126.148.224:9200 - R:/219.113.186.241:62293] java.lang.OutOfMemoryError: Java heap space at io.netty.util.internal.PlatformDependent.allocateUninitializedArray(PlatformDependent.java:200) ~[netty-common-4.1.16.Final.jar:4.1.16.Final] at io.netty.buffer.PoolArena$HeapArena.newByteArray(PoolArena.java:676) ~[netty-buffer-4.1.16.Final.jar:4.1.16.Final] at io.netty.buffer.PoolArena$HeapArena.newChunk(PoolArena.java:686) ~[netty-buffer-4.1.16.Final.jar:4.1.16.Final] at io.netty.buffer.PoolArena.allocateNormal(PoolArena.java:244) ~[netty-buffer-4.1.16.Final.jar:4.1.16.Final] at io.netty.buffer.PoolArena.allocate(PoolArena.java:226) ~[netty-buffer-4.1.16.Final.jar:4.1.16.Final] at io.netty.buffer.PoolArena.allocate(PoolArena.java:146) ~[netty-buffer-4.1.16.Final.jar:4.1.16.Final] at io.netty.buffer.PooledByteBufAllocator.newHeapBuffer(PooledByteBufAllocator.java:307) ~[netty-buffer-4.1.16.Final.jar:4.1.16.Final] at io.netty.buffer.AbstractByteBufAllocator.heapBuffer(AbstractByteBufAllocator.java:162) ~[netty-buffer-4.1.16.Final.jar:4.1.16.Final] at io.netty.buffer.AbstractByteBufAllocator.heapBuffer(AbstractByteBufAllocator.java:153) ~[netty-buffer-4.1.16.Final.jar:4.1.16.Final] at io.netty.buffer.AbstractByteBufAllocator.ioBuffer(AbstractByteBufAllocator.java:135) ~[netty-buffer-4.1.16.Final.jar:4.1.16.Final] at io.netty.channel.DefaultMaxMessagesRecvByteBufAllocator$MaxMessageHandle.allocate(DefaultMaxMessagesRecvByteBufAllocator.java:80) ~[netty-transport-4.1.16.Final.jar:4.1.16.Final] at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:122) [netty-transport-4.1.16.Final.jar:4.1.16.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:645) [netty-transport-4.1.16.Final.jar:4.1.16.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKeysPlain(NioEventLoop.java:545) [netty-transport-4.1.16.Final.jar:4.1.16.Final] at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:499) [netty-transport-4.1.16.Final.jar:4.1.16.Final] at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459) [netty-transport-4.1.16.Final.jar:4.1.16.Final] at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858) [netty-common-4.1.16.Final.jar:4.1.16.Final] at java.lang.Thread.run(Thread.java:748) [?:1.8.0_181] [2018-09-30T20:24:13,472][ERROR][o.e.b.ElasticsearchUncaughtExceptionHandler] [] fatal error in thread [Thread-5], exiting java.lang.OutOfMemoryError: Java heap space at io.netty.util.internal.PlatformDependent.allocateUninitializedArray(PlatformDependent.java:200) ~[?:?] at io.netty.buffer.PoolArena$HeapArena.newByteArray(PoolArena.java:676) ~[?:?] at io.netty.buffer.PoolArena$HeapArena.newChunk(PoolArena.java:686) ~[?:?] at io.netty.buffer.PoolArena.allocateNormal(PoolArena.java:244) ~[?:?] at io.netty.buffer.PoolArena.allocate(PoolArena.java:226) ~[?:?] at io.netty.buffer.PoolArena.allocate(PoolArena.java:146) ~[?:?] at io.netty.buffer.PooledByteBufAllocator.newHeapBuffer(PooledByteBufAllocator.java:307) ~[?:?] at io.netty.buffer.AbstractByteBufAllocator.heapBuffer(AbstractByteBufAllocator.java:162) ~[?:?] at io.netty.buffer.AbstractByteBufAllocator.heapBuffer(AbstractByteBufAllocator.java:153) ~[?:?] at io.netty.buffer.AbstractByteBufAllocator.ioBuffer(AbstractByteBufAllocator.java:135) ~[?:?] at io.netty.channel.DefaultMaxMessagesRecvByteBufAllocator$MaxMessageHandle.allocate(DefaultMaxMessagesRecvByteBufAllocator.java:80) ~[?:?] at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:122) ~[?:?] at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:645) ~[?:?] at io.netty.channel.nio.NioEventLoop.processSelectedKeysPlain(NioEventLoop.java:545) ~[?:?] at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:499) ~[?:?] at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459) ~[?:?] at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858) ~[?:?] at java.lang.Thread.run(Thread.java:748) [?:1.8.0_181] |
気になるのは以下の行。
1 2 3 |
java.lang.OutOfMemoryError: Java heap space |
そこで諸々対応してみました。
JVMのヒープサイズの最大値と最小値を変更
Java関連のエラーということで設定の変更を実施します。
公式ドキュメントでは以下となります。
https://www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html
以下の記述があるので物理メモリの2GBに設定をします。
Set Xmx to no more than 50% of your physical RAM, to ensure that there is enough physical RAM left for kernel file system caches.
1 2 3 4 |
-Xms2g -Xmx2g |
topコマンドなどで確認すると常に2Gのメモリが割り当てられるようになりました。(デフォルトは1G)
こちらで実施した結果も、前よりも長くは接続ができましたが結局同じエラーで終了してしまいました。
/etc/elasticsearch/elasticsearch.ymlの設定をする
設定ファイルと言えば上記ファイルなので変更をしてみます。
同じような事例か以下にありましたので設定を変更してみます。
★ EC2に立てたElasticsearchクラスタの設定を見直してみた(何度も落ちるので・・・)
設定を入れたのは以下の2つです。(リンクのものは一部設定で起動しなかったので)
https://www.elastic.co/guide/en/elasticsearch/reference/current/setup-configuration-memory.html
1 2 3 4 |
indices.fielddata.cache.size: 75% bootstrap.memory_lock: true |
こちら設定実施後も状況は変わらずでした。
今回は登録系なので field data cache は該当しなかったということでしょうか。
SortやAggregation(集計) で OutOfMemoryError だと有効そうですが。
★ Elasticsearchへのクエリが突然Failし始めた時の対処(fielddata cacheがデフォルト無限で泣いた話)
★ ElasticSearchのfield data cacheについて
システム系の設定の見直し
公式ドキュメントではシステム系の設定についても記載あるので変更してみました。
https://www.elastic.co/guide/en/elasticsearch/reference/current/setting-system-settings.html
結果的に設定しましたが状況変わりませんでした。
結論として
色々試しましたが、JVMのヒープサイズを3Gに変更したらアップができました。
身もふたもないですがメモリをあげるしかないようでした。
バルク自体がかなりメモリを使うようですので、あまり大きなサイズのアップは危険ということがわかりました。
もともとbulkで試すのに推奨されるのが5M - 15Mのようでしたのでファイル的に大きすぎたというコトで。
https://www.elastic.co/guide/en/elasticsearch/guide/current/bulk.html
このブログは株式会社CoLabMixによる技術ブログです。
GCP、AWSなどでのインフラ構築・運用や、クローリング・分析・検索などを主体とした開発を行なっています。
Ruby on RailsやDjango、Pythonなどの開発依頼などお気軽にお声がけください。
開発パートナーを増やしたいという企業と積極的に繋がっていきたいです。