ruby-on-rails - 在 HTML POST 之后 Rails 偶尔会冻结 - 极长的活动记录时间
问题描述
我有一个 Rails 4 应用程序,它有时会一次冻结多达 5 分钟,使任何人都无法访问该网站。有时,当启动来自 /plays 的 HTTP POST 时,服务器将完全锁定并变得无响应。
根据下面的这个来源,应该谨慎使用 ActiveRecord,并减少 .all 和 find_in_batches 的使用
https://chaione.com/blog/dealing-massive-data-rails/ActiveRecord
我怀疑 PlaysController 中的 set_plays 可能是罪魁祸首,但现在我更倾向于滥用 rails 缓存功能,因为这个问题不定期发生并且难以重现。
下面是播放控制器的片段。
class PlaysController < ApplicationController
helper PlaysHelper
load_and_authorize_resource
before_action :set_plays, only: [:index, :create]
before_action :set_play, only: [:show, :edit, :update, :destroy]
respond_to :html, :json
layout "layouts/tabs"
before_filter :title
before_filter :set_links
def new
@play = Play.new
respond_with(@play)
end
def create
@play = Play.new(play_params)
@play.show ||= @play.get_show(current_user)
if pbn = params[:playbox_number]
@play.playbox_number = pbn
end
if @play.save
begin
report_play_to_shoutcast(@play) if Rails.env.production?
rescue StandardError => e
flash[:error] = "Unable to report play to SHOUTcast #{e.inspect}\n#{e.backtrace[0]}"
end
begin
report_play_to_tunein(@play) if Rails.env.production?
rescue StandardError => e
flash[:error] = "Unable to report play to tunein #{e.inspect}\n#{e.backtrace[0]}"
end
# clear the cache of anything with play information in it
clear_plays_cache
# go ahead and reset the last_play cache, because we already have the value in hand
set_last_play(@play)
@play = Play.new
render(action: :index)
else
respond_with(@play)
end
end
private
def set_play
@play = Play.find(params[:id])
end
def set_plays
@plays = Play.all.paginate(page: params[:page], per_page: 50, total_entries: plays_count() ).order('created_at DESC').preload(:show,:playbox)
end
def play_params
params.require(:play).permit(:artist, :album, :track, :show_id)
end
end
以及应用程序助手的一部分
module ApplicationHelper
def set_last_play(play)
Rails.cache.write("plays__last_play", play, expires_in: 5.minutes, race_condition_ttl: 10.seconds)
end # set_last_play
def last_play
@last_play ||= Rails.cache.fetch("plays__last_play", expires_in: 5.minutes, race_condition_ttl: 10.seconds) do
Play.order("created_at").includes(:show).last || Play.new(album: "", artist: "", track: "", show: nil)
end
end # last_play
def plays_count
# only one 1 underscore (_) in order to avoid being eliminated by clear_plays_cache
@plays_count ||= Rails.cache.fetch("plays_count", expires_in: 5.hours, race_condition_ttl: 10.seconds) do
Play.count
end
end
def clear_plays_cache
Rails.cache.delete_matched('plays__')
end # clear_plays_cache
end
这是日志文件中的问题示例
I, [2019-06-19T08:25:37.659021 #5772] INFO -- : Started POST "/plays" for 127.0.0.1 at 2019-06-19 08:25:37 -0400
I, [2019-06-19T08:25:37.659021 #5772] INFO -- : Processing by PlaysController#create as HTML
I, [2019-06-19T08:25:37.659021 #5772] INFO -- : Parameters: {"utf8"=>"✓", "authenticity_token"=>"REDACTED", "playbox_number"=>"", "play"=>{"artist"=>"Band", "track"=>"Song", "album"=>"Single", "show_id"=>"720"}, "commit"=>"Create Play"}
I, [2019-06-19T08:26:07.209014 #5772] INFO -- : Rendered plays/_playbox_requirements.html.erb (15.7ms)
I, [2019-06-19T08:26:07.209014 #5772] INFO -- : Rendered plays/_form.html.erb (15.7ms)
I, [2019-06-19T08:26:07.255871 #5772] INFO -- : Rendered plays/_table.html.erb (46.9ms)
I, [2019-06-19T08:26:07.255871 #5772] INFO -- : Rendered plays/index.html.erb within layouts/tabs (62.5ms)
I, [2019-06-19T08:26:07.255871 #5772] INFO -- : Rendered plays/_lastwidget.html.erb (0.0ms)
I, [2019-06-19T08:26:07.255871 #5772] INFO -- : Rendered application/_login.overlay.html.erb (0.0ms)
I, [2019-06-19T08:26:07.255871 #5772] INFO -- : Rendered layouts/application.html.erb (0.0ms)
I, [2019-06-19T08:26:07.255871 #5772] INFO -- : Rendered layouts/bootstrap.html.erb (0.0ms)
I, [2019-06-19T08:26:07.255871 #5772] INFO -- : Rendered layouts/bootstrap-wide.html.erb (0.0ms)
I, [2019-06-19T08:26:07.255871 #5772] INFO -- : Completed 200 OK in 276754ms (Views: 66.8ms | ActiveRecord: 35996.5ms)
解决方案
推荐阅读
- python - tensorflow 数据集在过滤后无法计算出 epoch 中的训练步数
- android - 当我收到意图时额外丢失
- c++ - 如何在我的 C++ 程序中链接和使用远程 cplex
- java - 单例 bean 是否与 Spring 中的所有用户共享数据?
- python-3.x - 如何将 def common_stats 集成到类 Data_Load 中?
- flutter - 如何在 Flutter 中将字符串转换为对象?
- reactjs - 如何在鼠标悬停的情况下显示/隐藏antd卡中的额外部分?
- python - 在 python 虚拟环境中 AWS S3 访问被拒绝
- batch-file - 如何使delphi VCL应用程序从命令行运行
- javascript - 不同表中的 Hilghligth 列和行