我们已经在Heroku上使用ActionCable已有一段时间了,总的来说效果很好。但是,我们每天都会多次看到H15 Idle Connection错误。他们总是有path=/cable和很长的service时间,因此连接肯定存在一段时间并且很健康。

Dec 2016 08:32:22.057 heroku router - - at=error code=H15 desc="Idle connection"
method=GET path="/cable" host=<our host> dyno=web.2 connect=1ms service=928755ms status=503

我相信我们的设置非常标准,并且紧跟ActionCable的Rails文档:
module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = find_verified_user
    end

    protected

    def find_verified_user
      if current_user = User.find_by(id: cookies.signed[:user_id])
        current_user
      else
        # reject_unauthorized_connection
      end
    end
  end
end

我们有三个简单的 channel ,如下所示:
class ActivitiesChannel < ApplicationCable::Channel

  def subscribed
    stream_from "activities_#{current_user.id}" if current_user
  end
end

编辑以添加-Javascript代码:
app/assets/javascripts/channels/setup.js:
//= require cable

this.App || (this.App = {});
App.cable = ActionCable.createConsumer();
app/assets/javascripts/channels/notifications.js:
App.notifications = App.cable.subscriptions.create('NotificationsChannel', {
  received: function(data) {
      return this.showMessage(data);
  },
  showMessage: function(data) {
      showNotice(data.message);
  }
});

我对ActionCable和WebSockets比较陌生,所以我不确定如何解决这一问题。我们正在将Rails 5.0.0.1与Ruby 2.3.1一起运行

任何帮助,上下文或故障排除技巧将不胜感激!

最佳答案

编辑:我只是意识到这是一个老问题。不确定,为什么这会在我的供稿中弹出。无论如何,它可能会在将来对某人有所帮助。

我相信,当有人保持页面打开而不在 channel 上进行任何 Activity ,并且连接保持打开状态但闲置55秒钟时,Heroku会关闭连接,并显示Idle connection错误,就会发生这种情况。您必须通过实现某种ping系统来保持连接状态,该ping系统会定期向服务器发送消息,而服务器只是作为响应发送ok。一个简单的例子是:
app/assets/javascripts/channels/notifications.js:

App.notifications = App.cable.subscriptions.create('NotificationsChannel', {
  received: function(data) {
    // ignore the data when the type is 'pong' as it is just server's response to our 'ping'
    if(data.type !== 'pong'){
      return this.showMessage(data);
    }
  },
  showMessage: function(data) {
    showNotice(data.message);
  },
  ping: function() {
    return this.perform('ping', {
      message: {"event": "ping"}
    });
  }
});
document.addEventListener("DOMContentLoaded", function(event) {
  // this will send a ping event every 30 seconds
  setInterval(function(){
    App.notifications.ping()
  }, 30000);
});

在服务器端,您需要向“ping”事件发送响应消息,例如“pong”。您可以将该响应发送给同一用户,也可以广播给所有用户,具体取决于您的 channel 设置和要求。
class NotificationsChannel < ApplicationCable::Channel

  def subscribed
    stream_from "notifications_#{current_user.id}" if current_user
  end

  # data is not required, you can choose to ignore it or not send it at all from the client-side.
  def ping(data)
    NotificationsChannel.broadcast_to("notifications_#{current_user.id}", { message: 'pong' })
  end
end

即使用户空闲,这也应使连接保持 Activity 状态。

自从ActionCable首次发布以来,我还没有使用它。让我知道如果某事不起作用或任何语法错误,我将尝试修复。

关于ruby-on-rails - ActionCable超时-Heroku上的 "Idle Connection",我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40960920/

10-10 14:59