Rails - 使用Heroku的Elasticsearch(Bonsai) - 性能问题

时间:2016-03-05 10:04:47

标签: ruby-on-rails heroku elasticsearch elasticsearch-model bonsai-elasticsearch

我在 Ruby on Rails 项目中使用了 Elasticsearch - Bonsai 。 所以,事情进展顺利。但是,当我们向最终用户和人们开始使用此应用程序时,我们注意到单个弹性搜索查询需要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 电话数据 ES calls data in 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

现在,如果我查看 Heroku 的BONSAI 10计划,它会给我 20 Shards 但是当前状态为群集,它只使用1个活动主分片和2个活动分片。我突然想到几个问题:

  1. 将分片数增加到20会有帮助吗?
  2. 可以缓存ES查询 - 您是否也建议相同? - 它有任何优点和缺点吗?
  3. 请帮助我找到减少时间并提高ES工作效率的方法。

    更新

    以下是我创建的小代码段https://jsfiddle.net/puneetpandey/wpbohqrh/2/(作为参考),以准确显示为什么我需要这么多调用 ElasticSearch

    在上面的例子中,我显示了一些计数(在每个复选框元素的前面)。为了显示这些数量,我需要通过点击ES来获取我得到的数字

    好的,所以看完评论后发现了一篇好文章:How to config elasticsearch cluster on one server to get the best performace on search我觉得我已经有足够的重新构建了

    最佳,

    普尼特

2 个答案:

答案 0 :(得分:1)

尼克和盆景在这里。如果您通过support@bonsai.io与我们的支持团队取得联系,我们将始终乐于帮助解决性能问题,并且可以访问更详细的日志来帮助解决这些问题。与此同时,我想我可以在这里分享一些足够通用的建议......

在这种情况下,New Relic报告中有趣的统计信息是&#34;平均呼叫(每txn):109。&#34;如果我正确理解,您的应用看起来每个网络请求平均有超过100次调用Elasticsearch。这似乎非常高。

如果在所有100多个请求中平均3,000毫秒,则每个请求到Elasticsearch大约30毫秒。这也比我们通常的平均值慢一点,但对于单个请求来说要比3,000毫秒更合理。 (我们可以通过更多私人支持信函与您分享更具体的数字。)

您可能希望专注于减少Elasticsearch请求的数量。如果您无法减少总请求数,则可以考虑将它们组合起来以节省每个请求和每个连接的开销。 Bonsai还支持HTTP keep-alive,因此您可以重用请求之间的连接,有助于减少初始TLS握手的开销。

要合并更新,您可以使用Bulk API。还有Multi Search API用于搜索,Multi Get API用于单文档获取请求。

如果缩减和合并都不可能,那么您可能还有一些其他用例对于单独进行所有这些搜索非常重要。如果是这种情况,我建议在UI中使用Ajax来加载这些搜索。这样,您的应用可以提供快速的初始响应,并向用户显示一些进展,同时逐渐填补其余部分。

答案 1 :(得分:0)

您有3个ES节点,最佳性能要求每个节点至少有一个分片。 Heroku可能会报告其他内容。碎片是ES内部特定索引的属性,而不是ES群集本身的属性,因此请检查索引具有多少碎片。但即使使用一个分片,您的查询也不应该太慢,可能文档的编写方式错误。您提供的关于索引,查询和负载的信息太少。

缓存可能与任何存储系统一样有用,缺点和优点也始终相同。