【发布时间】:2018-06-24 21:19:26
【问题描述】:
我有一个 Rails 应用程序,其中一个操作永远不会完成然后超时。 查找下图以获得更好的说明。
- 我的 rails apps 操作被调用
- 该操作将一些数据发布到另一个应用程序
- 另一个应用程序需要一些东西来完成计算并调用与第一个 Rails 应用程序不同的操作
- 其他应用收到响应并完成计算
- 其他应用响应 Rails 应用的 POST 请求
- 相应地呈现视图
现在的问题:其他应用永远不会得到主应用的响应。然而,在 Rails 应用程序请求超时后,会发送响应(当然为时已晚),所以我认为它以某种方式被暗示了。
我不明白如何解决这个问题。我使用应该能够处理并行调用的 rails 5 和 Puma。这也不是本地问题,在产品中也会发生同样的情况。
我使用 Heroku 推荐的 puma.rb 配置
workers Integer(ENV['WEB_CONCURRENCY'] || 2)
threads_count = Integer(ENV['RAILS_MAX_THREADS'] || 5)
threads threads_count, threads_count
preload_app!
rackup DefaultRackup
port ENV['PORT'] || 3000
environment ENV['RACK_ENV'] || 'development'
on_worker_boot do
# Worker specific setup for Rails 4.1+
# See: https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#on-worker-boot
ActiveRecord::Base.establish_connection
end
我该怎么做才能解决这个提示?
控制器:
# New method
def live_preview_page
preview_locale = params[:preview_locale]
date = params[:date] # The date to preview
page_id = params[:id]
return if locale.nil? || locale =~ /not/ || date.nil?
all_templates = Template.all.order('name ASC') # Maybe move to render_live_editor_page
if date == "all"
active_modules = @page.page_modules.order(rank: :asc)
else
active_modules = @page.page_modules.order(rank: :asc).to_a.valid_for(date: date.to_date)
puts "Active modules: #{active_modules.count}"
end
active_modules_json = active_modules.each do |content_module|
content_module.body = YAML.load(content_module.body).to_json
end
response = helpers.render_preview(active_modules, all_templates, preview_locale)
renderer = ContentRenderer.new
actionController = ActionController::Base.new
rendered_helper = actionController.render_to_string(
partial: '/pages/preview-helper-snippet', locals: {
all_templates: all_templates, # For select when creating new modules
modulesData: active_modules_json, # For rendering the JSON containing the data for the editor
current_page: @page.id,
localeLinks: renderer.generateStgPreviewURLs(SettingService.get_named_locales, @page.id),
locale: preview_locale,
all_locales: SettingService.locales_for_live_editor,
all_sites_and_locales: SettingService.get_sites_and_locales
})
proxy_service = ProxyService.new
proxy_service.get_page do |error, page_wrapper|
# Note: Issue is that Vapor app generates warnings inline template : encountered \r in middle of line, treated as a mere space
rendered_body_with_helper = response.body.force_encoding("UTF-8") + rendered_helper
decorated_page = page_wrapper.gsub("__WIDGET__", rendered_body_with_helper)
render inline: decorated_page
return
end
end
助手
def render_preview(active_modules, all_templates, preview_locale)
req = Request.new
preview_body = {
modules: active_modules,
templates: all_templates,
sites: SettingService.get_sites,
configuration: {
locale: preview_locale,
site: "DE"
}
}
req.send_request(
url: "#{ENV["RENDER_SERVICE_URL"]}/preview",
body: preview_body,
options: {
type: :post,
json: true,
username: ENV["RENDER_SERVICE_BASIC_AUTH_USERNAME"],
password: ENV["RENDER_SERVICE_BASIC_AUTH_PASSWORD"]
}
) do |response_code, response|
return response
end
end
请求只是一个薄包装
require "uri"
require "net/http"
class Request
# Yields resonse_code (int), response
# Parameters besides url: are optional
def send_request(url:, body: {}, header: {}, options: {})
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
if options.key? :type
case options[:type]
when :get
request = Net::HTTP::Get.new(uri.request_uri, header)
when :post
request = Net::HTTP::Post.new(uri.request_uri, header)
end
else
# Default is GET
request = Net::HTTP::Get.new(uri.request_uri, header)
end
if options.key?(:username) && options.key?(:password)
request.basic_auth options[:username], options[:password]
end
unless body.class == String
body = body.to_json.to_s
end
request.body = body unless body.empty?
puts request.body
# SSL is default
if options.key? :ssl
http.use_ssl = options[:ssl]
else
http.use_ssl = Rails.configuration.force_ssl
#http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
if options.key? :json
request.add_field("Content-Type", "application/json")
end
response = http.request(request)
yield response.code.to_i, response
end
end
【问题讨论】:
-
问题不太可能出在 Puma 配置中。您能否粘贴负责处理与其他应用程序通信的控制器/服务的代码
-
@KartikeyTanna 编辑了问题
-
我认为这是我的问题:github.com/puma/puma/issues/1433 但我不知道如何解决它:( 我怎样才能转移到另一个工人或其他什么?
-
尝试增加工人的数量。将它们设置为 5 或其他值。它可能会减少出错的机会
标签: ruby-on-rails concurrency puma