Rails - Elasticsearch (бонсай) с Heroku - Проблемы производительности

Я использую Elasticsearch - Bonsai в одном из моих проектов Ruby on Rails. Так что все шло очень гладко. Но в тот момент, когда мы запустили это приложение для конечных пользователей, и люди начали приходить, мы заметили, что для ответа на один запрос asticsearch требуется 5-7 секунд (для нас это очень плохо) - хотя у нас 8-2x Web Динос на месте.

Итак, мы решили обновить надстройку Bonsai до Bonsai 10, а также добавили надстройку NewRelic (чтобы следить за тем, сколько времени требуется для ответа на один запрос)

Ниже приведены наши настройки среды:

Ruby: 2.2.4
Rails: 4.2.0
elasticsearch: 1.0.15
elasticsearch-model: 0.1.8

Итак, мы снова импортировали данные в Elasticsearch и вот наше состояние кластера ElasticSearch:

pry(main)> Article.__elasticsearch__.client.cluster.health
=> {"cluster_name"=>"elasticsearch",
    "status"=>"green",
    "timed_out"=>false,
    "number_of_nodes"=>3,
    "number_of_data_nodes"=>3,
    "active_primary_shards"=>1,
    "active_shards"=>2,
    "relocating_shards"=>0,
    "initializing_shards"=>0,
    "unassigned_shards"=>0,
    "delayed_unassigned_shards"=>0,
    "number_of_pending_tasks"=>0,
    "number_of_in_flight_fetch"=>0}

и ниже данные NewRelic о вызовах ES ES вызывает данные в NewRelic

Что указывает на серьезную причину для беспокойства.

Моя модель article.rb ниже:

class Article < ActiveRecord::Base
  include Elasticsearch::Model

  after_commit on: [:create] do
    begin
      __elasticsearch__.index_document
    rescue Exception => ex
      logger.error "ElasticSearch after_commit error on create: #{ex.message}"
    end
  end

  after_commit on: [:update] do
    begin
      Elasticsearch::Model.client.exists?(index: 'articles', type: 'article', id: self.id) ? __elasticsearch__.update_document :     __elasticsearch__.index_document
    rescue Exception => ex
      logger.error "ElasticSearch after_commit error on update: #{ex.message}"
    end
  end

  after_commit on: [:destroy] do
    begin
      __elasticsearch__.delete_document
    rescue Exception => ex
      logger.error "ElasticSearch after_commit error on delete: #{ex.message}"
    end
  end

  def as_indexed_json(options={})
    as_json({
      only: [ :id, :article_number, :user_id, :article_type, :comments, :posts, :replies, :status, :fb_share, :google_share, :author, :contributor_id, :created_at, :updated_at ],
      include: {
        posts: { only: [ :id, :article_id, :post ] },
      }
    })
  end
end

Теперь, если я посмотрю на план Hero ku BONSAI 10, он даст мне 20 шардов, но с текущим статусом кластера, он использует только 1 активный первичный шард и 2 активных шарда. Несколько вопросов вдруг возникли у меня в голове:

  1. Поможет ли здесь увеличение количества осколков до 20?
  2. Может быть возможно кэшировать запросы ES - Вы также предлагаете то же самое? - Есть ли у нее плюсы и минусы?

Пожалуйста, помогите мне найти способы, с помощью которых я могу сократить время и сделать работу ES более эффективной.

ОБНОВИТЬ

Вот небольшой фрагмент кода https://jsfiddle.net/puneetpandey/wpbohqrh/2/, который я создал (в качестве ссылки), чтобы точно показать, почему мне нужно так много вызовов ElasticSearch

В приведенном выше примере я показываю несколько отсчетов (перед каждым элементом флажка). Чтобы показать эти цифры, мне нужно получить числа, которые я получаю, нажимая ES

Итак, после прочтения комментариев и поиска хорошей статьи здесь: Как настроить кластер asticsearch на одном сервере, чтобы получить лучшую производительность при поиске, я думаю, у меня достаточно для реструктуризации

Лучший,

Puneet

2 ответа

Ник с бонсай здесь. Если вы обратитесь в нашу службу поддержки по адресу support@bonsai.io, мы всегда будем рады ответить на вопросы о производительности и получить доступ к гораздо более подробным журналам, чтобы помочь с этим. В то же время я думаю, что могу поделиться некоторыми достаточно общими советами здесь...

В этом случае интересная статистика в вашем отчете New Relic - "Среднее количество звонков (за тонну): 109". Если я правильно понимаю, похоже, ваше приложение в среднем выполняет более 100 вызовов Elasticsearch за веб-запрос. Это кажется необычно высоким.

Если эти 3000 мс усредняются по всем 100+ запросам, то это около 30 мс на запрос к Elasticsearch. Это также немного медленнее, чем обычно, но гораздо более разумно, чем 3000 мс для одного запроса. (Мы можем поделиться с вами более конкретными номерами через более частную переписку службы поддержки.)

Вы можете сосредоточиться на уменьшении количества запросов Elasticsearch. Если вы не можете уменьшить общее количество запросов, вы можете подумать о том, чтобы объединить их, чтобы сэкономить на каждом запросе и накладных расходах на соединение. Bonsai также поддерживает HTTP keep-alive, так что вы можете повторно использовать соединения между запросами, помогая уменьшить накладные расходы на первоначальное рукопожатие TLS.

Для консолидации обновлений вы можете использовать Bulk API. Также есть Multi Search API для поиска и Multi Get API для запросов на получение одного документа.

Если сокращение и консолидация невозможны, у вас может быть другой вариант использования, который важен для выполнения всех этих поисков по отдельности. Если это так, я бы рекомендовал использовать Ajax в пользовательском интерфейсе для пост-загрузки этих поисков. Таким образом, ваше приложение может дать быстрый начальный ответ и показать некоторый прогресс пользователю, постепенно заполняя остальное.

У вас есть 3 узла ES, для оптимальной производительности требуется как минимум один шард на узел. Heroku, вероятно, сообщает что-то еще. Осколки - это свойства определенного индекса внутри ES, а не самого кластера ES, поэтому проверьте, сколько у вас есть индекса. Но даже с одним осколком ваш запрос не должен быть таким медленным, возможно, документы были проиндексированы неправильно. Вы предоставили слишком мало информации о вашем индексе, ваших запросах, вашей загрузке.

Кэширование может помочь, как и в любой системе хранения, минусы и плюсы всегда одинаковы.

Другие вопросы по тегам