我在 Heroku 上建立了一个基于 Rails 的网站,该网站通常在大约 90% 的内存使用情况下运行良好。
通过 Scout,我在我的 Rails 应用程序中隔离了一个问题,其中我的 comments#create-controller 有时会分配 860k 的内存,这会在随后的超时等情况下长时间关闭我的应用程序。大多数情况下,分配的内存只是其中的一小部分,因此问题是间歇性的。
评论功能本身并不是很重要,但我仍然需要它。我相信它的三个不同部分可能会导致此内存问题:
内容字符串(即评论本身)太长。例如,如果垃圾邮件发送者发布超长文本。我认为这不是问题,因为我上一次的内存峰值是由普通用户引起的,发表了非常简短的评论。
我的 rakismet-gem ( https://github.com/joshfrench/rakismet ) 和垃圾邮件检查。我正在使用最新版本(1.5.4)。这很可能是一个问题,因为我真的不知道在使用时加载到内存中的是什么。
我在代码中的通知程序调用。
我能做些什么来捕捉内存问题并在控制器中进行救援,所以如果有任何“坏”评论,它们不会破坏整个网站?
您在代码中看到任何可能导致这种怪物内存分配的东西吗?
下面的代码:
评论#创建:
def create
require 'memory_profiler'
report = MemoryProfiler.report do
@comment = Comment.new(comment_params)
spam_features = %w(\xA cialis informative the that this buy href)
unless @current_administrator.present?
if spam_features.any? {|str| @comment.content.include? str}
logger.info "L: Comment include spam features"
redirect_to article_path(Article.find('din-kommentar-har-inte-sparats')) and return
elsif @comment.author.size > 40 || @comment.author_email.size > 40
logger.info "L: Comment author name or email too long (suspicious)"
redirect_to article_path(Article.find('din-kommentar-har-inte-sparats')) and return
end
end
# This shouldn't be here (but don't know how to put it in the model)
if !@comment.blog_post_id.blank? # This is a comment on a blog post
return_to_path = blog_post_path(BlogPost.find(@comment.blog_post_id))
elsif !@comment.gift_id.blank? # This is a comment on a gift
return_to_path = gift_path(Gift.find(@comment.gift_id))
elsif !@comment.contest_id.blank? # This is a comment on a contest
return_to_path = contest_path(Contest.find(@comment.contest_id))
elsif !@comment.christmas_fair_id.blank? # This is a comment on a christmas fair
return_to_path = christmas_fair_path(ChristmasFair.find(@comment.christmas_fair_id))
elsif @comment.tmp_julrim # This is a comment on a christmas fair
return_to_path = rhymes_path
else
raise ActionController::RoutingError.new('Not Found')
end
return_to_path << "#comments"
@comment.status_id = 3
@comment.user_ip = request.remote_ip
@comment.user_agent = request.env['HTTP_USER_AGENT']
@comment.marked_as_spam = @comment.spam? # Using rakismet to check for spam
#if !@comment.marked_as_spam || @current_administrator.present?
respond_to do |format|
#@comment.status_id = 1 if @comment.contest_id == 44
if @comment.save
Notifier.new_comment(@comment).deliver if Rails.env == 'production' unless @comment.marked_as_spam
format.html { redirect_to return_to_path, notice: 'Din kommentar har registrerats och kommer att ses över innan den godkänns.' }
# format.json { render action: 'show', status: :created, location: @comment }
else
format.html { render action: 'new' }
format.json { render json: @comment.errors, status: :unprocessable_entity }
end
end
end