【问题标题】:Rails & ActionCable 1.8hr network request time on localhost / High Response Time on HerokuRails 和 ActionCable 本地主机上的 1.8 小时网络请求时间 / Heroku 上的高响应时间
【发布时间】:2020-04-16 08:46:04
【问题描述】:

Chrome 中的“网络”选项卡显示 /cable 请求在 localhost 上的秒和 小时 之间波动:

...然后是这个疯狂的多米诺骨牌堆栈“待处理”请求:

在带有 Puma 服务器和 512 MB dyno 的 Heroku 上,我在 /cable 端点上收到高响应时间警告。以下是日志条目的示例:

25 Dec 2019 14:13:31.061299 <158>1 2019-12-25T22:13:28.421009+00:00 heroku router - - at=info method=GET path="/cable" host=www.######.com request_id=#### fwd="####" dyno=web.1 connect=1ms service=531114ms status=101 bytes=174 protocol=https High Response Time

在所有情况下,我都是唯一使用该应用程序的人。我已经看到最多 3-4 个其他人在使用 ActionCable 时遇到此问题,但他们似乎都没有任何解决方案,而我束手无策。我研究了 AnyCable 和 Iodine,但 AnyCable 不起作用,而且 Iodine 也不能解决我的问题。还有什么可能导致这种情况?

预期行为: /cable 请求应在几毫秒内处理完毕。

实际行为:一些 /cable 请求在 80 年后被处理,然后数百个其他请求被困在 pending 状态。

系统配置: Ruby 版本:2.5.0,Rails 版本:5.2.0,Puma 版本:4.3.1

channels/application_cable/channel.rb

module ApplicationCable
 class Channel < ActionCable::Channel::Base
 end
end

channels/application_cable/connection.rb

module ApplicationCable
 class Connection < ActionCable::Connection::Base
  identified_by :current_user

  def connect
   self.current_user = find_verified_user
   logger.add_tags 'ActionCable', current_user.username
  end

  protected
  def find_verified_user
   if verified_user = User.find_by(id: cookies.signed['user.id'])
    verified_user
   else
    reject_unauthorized_connection
   end  
  end
 end
end

channels/messages_channel.rb

class MessagesChannel < ApplicationCable::Channel
 def subscribed
  stream_from "user_#{current_user.id}_messages_channel"
 end

 def unsubscribed
  stop_all_streams
 end

 def speak(data)
  Message.create! body: data['message'], conversation_id: data['conversation_id'], user_id: current_user.id
 end
end

javascripts/channels/messages.coffee

App.messages = App.cable.subscriptions.create "MessagesChannel",
 connected: ->
  console.log 'Connected'

 disconnected: ->
  console.log 'Disconnected'

 received: (data) ->
  console.log 'Received'
  $("[data-conversation-id='" + data.conversation_id + "']").append(data.message)
  console.log 'Received'
  $("#messages").append(data.message)

 speak: (message, conversation_id) ->
  @perform 'speak', message: message, conversation_id: conversation_id

$(document).on 'turbolinks:load', ->
 submit_message()
 scroll_bottom()

submit_message = () ->
 $('#response').on 'keydown', (event) ->
  if event.keyCode is 13
   message = event.target.value
   conversation_id = $("#messages").data("conversation-id")
   App.messages.speak(message, conversation_id)
   event.target.value = ""
   event.preventDefault()

scroll_bottom = () ->
 if $('#messages').length > 0
 $('#messages').scrollTop($('#messages')[0].scrollHeight)

models/messages.rb

class Message < ApplicationRecord
 after_create_commit { MessageBroadcastWorker.perform_async self.id }
end

workers/message_broadcast_worker.rb

class MessageBroadcastWorker
 include Sidekiq::Worker

 def perform(message_id)
  message = Message.find message_id
  user = message.user
  ActionCable.server.broadcast("user_#{user.id}_messages_channel", message: render_message(message, user))
 end

 private
 def render_message(message, user)
  ApplicationController.renderer.render(partial: 'messages/message', locals: { message: message, user: user })
 end
end

【问题讨论】:

  • 在我之前的工作中,我们很快就放弃了 AC,转而选择了 phoenix。要让它在当今高标准的聊天应用程序中表现得体面,工作量太大了。话虽如此,如果没有看到任何代码,就不可能知道为什么您的响应时间很慢,这可能是无数问题。虽然,我听说 Actioncable 的许多与性能相关的问题已经在 rails 6 中得到解决(未验证),但是当他们放弃 CoffeeScript 时,它需要大量的重构才能将 rails 5 AC 应用程序转换为 rails 6 AC。可能不是你想听到的......但是是的。
  • 我会切换到 AnyCable,性能完全不同,您可以保留 ActionCable 代码库。作为一个有偏见的替代方案,我还建议使用 iodine WebSocket 服务器 (Ruby),它提供了一个远远优于 AC 方法的自定义 pub/sub 层。
  • 谢谢!你说得对。我不敢相信没有太多关于 ActionCable 的抱怨。数百个教程,但没有一个提到性能。过去几天我一直在设置 AnyCable。目前在设置它时遇到了一些问题(AnyCable 在环境中没有看守),但我认为我走在正确的道路上
  • @Myst 感谢您制作碘!!我正在尝试设置它,但在堆栈跟踪中获取它以获得高响应时间警报:2020-04-13 09:46:01.063 161 &lt;190&gt;1 2020-04-13T09:45:58.224726+00:00 app web.1 - - bundler: failed to load command: puma (/app/vendor/bundle/bin/puma) 2020-04-13 09:46:01.063 241 &lt;190&gt;1 2020-04-13T09:45:58.224772+00:00 app web.1 - - Gem::Exception: can't find executable puma for gem puma. puma is not currently included in the bundle, perhaps you meant to add it to your Gemfile? 我的puma.rb 被删除,我的 Procfile 中有bundle exec iodine -p $PORT -t 16 -w 4
  • 设置时我还需要做些什么吗?出于某种原因,我的应用在应该寻找碘时却在寻找 puma

标签: ruby-on-rails heroku puma actioncable


【解决方案1】:

解决方案是关闭 Heroku logentries 上的警报。 /cable 请求轮询服务器以获取更新,它建立单个请求然后保持打开状态直到用户退出或离开站点。

【讨论】:

  • 我可以为此提供证据吗?您的回答听起来很合理,但应该在官方文档中的某处提及
猜你喜欢
  • 2017-12-23
  • 2021-10-17
  • 1970-01-01
  • 2017-06-15
  • 2015-09-14
  • 1970-01-01
  • 2015-11-18
  • 2017-10-14
  • 2015-05-19
相关资源
最近更新 更多