web-dev-qa-db-fra.com

EsRejectedExecutionException dans elasticsearch pour la recherche parallèle

Je demande à elasticsearch plusieurs requêtes parallèles à l'aide d'une seule instance de client de transport dans mon application.

J'ai eu l'exception ci-dessous pour l'exécution parallèle. Comment surmonter le problème.

org.elasticsearch.common.util.concurrent.EsRejectedExecutionException: rejected execution (queue capacity 1000) on org.elasticsearch.search.action.SearchServiceTransportAction$23@5f804c60
    at org.elasticsearch.common.util.concurrent.EsAbortPolicy.rejectedExecution(EsAbortPolicy.Java:62)
    at Java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.Java:821)
    at Java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.Java:1372)
    at org.elasticsearch.search.action.SearchServiceTransportAction.execute(SearchServiceTransportAction.Java:509)
    at org.elasticsearch.search.action.SearchServiceTransportAction.sendExecuteScan(SearchServiceTransportAction.Java:441)
    at org.elasticsearch.action.search.type.TransportSearchScanAction$AsyncAction.sendExecuteFirstPhase(TransportSearchScanAction.Java:68)
    at org.elasticsearch.action.search.type.TransportSearchTypeAction$BaseAsyncAction.performFirstPhase(TransportSearchTypeAction.Java:171)
    at org.elasticsearch.action.search.type.TransportSearchTypeAction$BaseAsyncAction.start(TransportSearchTypeAction.Java:153)
    at org.elasticsearch.action.search.type.TransportSearchScanAction.doExecute(TransportSearchScanAction.Java:52)
    at org.elasticsearch.action.search.type.TransportSearchScanAction.doExecute(TransportSearchScanAction.Java:42)
    at org.elasticsearch.action.support.TransportAction.execute(TransportAction.Java:63)
    at org.elasticsearch.action.search.TransportSearchAction.doExecute(TransportSearchAction.Java:107)
    at org.elasticsearch.action.search.TransportSearchAction.doExecute(TransportSearchAction.Java:43)
    at org.elasticsearch.action.support.TransportAction.execute(TransportAction.Java:63)
    at org.elasticsearch.action.search.TransportSearchAction$TransportHandler.messageReceived(TransportSearchAction.Java:124)
    at org.elasticsearch.action.search.TransportSearchAction$TransportHandler.messageReceived(TransportSearchAction.Java:113)
    at org.elasticsearch.transport.netty.MessageChannelHandler.handleRequest(MessageChannelHandler.Java:212)
    at org.elasticsearch.transport.netty.MessageChannelHandler.messageReceived(MessageChannelHandler.Java:109)
    at org.elasticsearch.common.netty.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.Java:70)
    at org.elasticsearch.common.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.Java:564)
    at org.elasticsearch.common.netty.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendUpstream(DefaultChannelPipeline.Java:791)
    at org.elasticsearch.common.netty.channel.Channels.fireMessageReceived(Channels.Java:296)
    at org.elasticsearch.common.netty.handler.codec.frame.FrameDecoder.unfoldAndFireMessageReceived(FrameDecoder.Java:462)
    at org.elasticsearch.common.netty.handler.codec.frame.FrameDecoder.callDecode(FrameDecoder.Java:443)
    at org.elasticsearch.common.netty.handler.codec.frame.FrameDecoder.messageReceived(FrameDecoder.Java:303)
    at org.elasticsearch.common.netty.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.Java:70)
    at org.elasticsearch.common.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.Java:564)
    at org.elasticsearch.common.netty.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendUpstream(DefaultChannelPipeline.Java:791)
    at org.elasticsearch.common.netty.OpenChannelsHandler.handleUpstream(OpenChannelsHandler.Java:74)
    at org.elasticsearch.common.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.Java:564)
    at org.elasticsearch.common.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.Java:559)
    at org.elasticsearch.common.netty.channel.Channels.fireMessageReceived(Channels.Java:268)
    at org.elasticsearch.common.netty.channel.Channels.fireMessageReceived(Channels.Java:255)
    at org.elasticsearch.common.netty.channel.socket.nio.NioWorker.read(NioWorker.Java:88)
    at org.elasticsearch.common.netty.channel.socket.nio.AbstractNioWorker.process(AbstractNioWorker.Java:108)
    at org.elasticsearch.common.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.Java:318)
    at org.elasticsearch.common.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.Java:89)
    at org.elasticsearch.common.netty.channel.socket.nio.NioWorker.run(NioWorker.Java:178)
    at org.elasticsearch.common.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.Java:108)
    at org.elasticsearch.common.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.Java:42)
    at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1145)
    at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:615)
    at Java.lang.Thread.run(Thread.Java:745)
52
Vipin

Elasticsearch dispose d'un pool de threads et d'une file d'attente pour la recherche par nœud. Un pool de threads aura un nombre N de travailleurs prêts à traiter les demandes. Quand une demande arrive et si un travailleur est libre, cela est géré par le travailleur. Maintenant, par défaut, le nombre de travailleurs est égal au nombre de cœurs de cette CPU. Lorsque les travailleurs sont pleins et qu'il y a plus de demandes de recherche, la demande est mise en file d'attente. La taille de la file d'attente est également limitée. Si la taille par défaut est, par exemple, de 100 et que s'il y a plus de demandes parallèles, ces demandes seraient alors rejetées, comme vous pouvez le constater dans le journal des erreurs.

Solutions:

  1. La solution immédiate serait d’augmenter la taille de la file d’attente de recherche. Nous pouvons également augmenter la taille du pool de threads, mais cela pourrait affecter gravement les performances des requêtes individuelles. Donc, augmenter la file d'attente pourrait être une bonne idée. Mais souvenez-vous que cette file d’attente est résidente en mémoire et qu’augmenter sa taille peut entraîner des problèmes de mémoire insuffisante. ( plus d'infos )

  2. Augmenter le nombre de nœuds et de réplicas - N'oubliez pas que chaque nœud a son propre thread/pool de recherche. En outre, la recherche peut se produire sur un fragment principal OR réplica.

73
Vineeth Mohan

Cela peut sembler étrange, mais vous devez réduire le nombre de recherches parallèles. À cette exception près, Elasticsearch vous indique que vous le surchargez. Des limites (au niveau du nombre de threads) sont définies dans Elasticsearch et, la plupart du temps, les valeurs par défaut de ces limites constituent la meilleure option. Ainsi, si vous testez votre cluster pour voir quelle charge il peut supporter, cela indique que certaines limites ont été atteintes.

Si vous voulez vraiment changer la valeur par défaut, vous pouvez essayer d’augmenter taille de la file pour que les recherches tiennent compte de la demande de simultanéité, mais n'oubliez pas que plus la taille de la file est grande, plus vous mettez de pression. cluster qui, à la fin, causera une instabilité.

5
Andrei Stefan

J'ai vu la même erreur parce que j'envoyais beaucoup de demandes d'indexation à ES en parallèle. Depuis que j'écris une migration de données, il était assez facile de les rendre en série, ce qui a résolu le problème.

3
Darth Egregious

Je ne sais pas quelle était votre configuration de noeud, mais la taille de votre file d'attente (1 000) est déjà plus élevée. Comme d'autres l'ont déjà expliqué, vos demandes de recherche sont mises en file d'attente dans la file d'attente du pool de threads Elasticsearch. Même après une taille de file d'attente aussi élevée, si vous recevez des rejets, cela donne à penser que vous devez revoir votre modèle de requête.

Comme dans de nombreux autres modèles, même dans ce cas, il n’existe pas de solution unique. J'ai trouvé this est un très bon article sur le fonctionnement de cette file d'attente et sur les différentes façons d'effectuer un test de performance pour déterminer ce qui convient le mieux à votre cas d'utilisation.

HTH!

0
avp