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

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

Итак, мы решили обновить надстройку 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

введите здесь описание изображения

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

Моя модель 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

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

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

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

ОБНОВЛЕНИЕ

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

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

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

Лучший,

Пунит


person Puneet Pandey    schedule 05.03.2016    source источник


Ответы (2)


Ник с бонсай здесь. Если вы свяжетесь с нашей службой поддержки по адресу [email protected], мы всегда будем рады помочь с вопросами о производительности, и у нас есть доступ к гораздо более подробным журналам, чтобы помочь с этим. А пока я думаю, что могу поделиться здесь некоторыми достаточно общими советами…

В этом случае интересной статистикой в ​​вашем отчете 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 в пользовательском интерфейсе для пост-загрузки этих поисков. Таким образом, ваше приложение может предоставить быстрый первоначальный ответ и показать пользователю некоторый прогресс, постепенно заполняя остальные.

person Nick Zadrozny    schedule 06.03.2016
comment
Спасибо за быстрый ответ @Nick.. Я полностью согласен с вами, что с каждым веб-запросом я нажимаю ES более 100 раз, чтобы получить записи для каждого атрибута на странице. Сокращение общего количества вызовов, безусловно, помогает здесь, и я также рассматриваю ваш третий вариант, в котором я могу использовать/вызывать запросы AJAX. - person Puneet Pandey; 06.03.2016
comment
Если вы когда-либо работали над проблемой запроса N+1 в своих вызовах базы данных, похоже, вы создали для себя аналогичную ситуацию здесь с Elasticsearch :-) - person Nick Zadrozny; 08.03.2016
comment
К сожалению, @nick-zadrozny, я не вижу возможности уменьшить количество обращений к ES. Вот небольшой фрагмент фрагмент кода . Как вы увидите, чтобы отобразить количество для каждого атрибута в расширенном поиске, мне придется запросить ElasticSearch. Дайте мне знать, если это объяснимо! - person Puneet Pandey; 08.03.2016
comment
Привет Пунит, то, что вы пытаетесь сделать, это именно то, что Агрегации предназначены для - person Nick Zadrozny; 08.03.2016
comment
Вот еще одна статья, которую я нашел очень полезной: stackoverflow.com/questions/23269280/ - person Puneet Pandey; 10.03.2016

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

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

person xeye    schedule 05.03.2016