ActionCable 超时 - "Idle Connection" on Heroku



我们已经在Heroku上使用ActionCtictcous已有一段时间了,总体而言,它运行良好。但是,我们每天看到多次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

我相信我们的设置非常标准,并紧随铁轨文档以进行操作:

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

我们有三个这样的简单频道:

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和Websocket的新手很新,因此我不确定如何对此进行故障排除。我们正在运行Ruby 2.3.1

的Rails 5.0.0.1

任何帮助,上下文或故障排除提示都将不胜感激!

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

我相信,当某人保持页面打开而没有任何活动上的任何活动,并且连接保持打开但空转55秒时,Heroku与错误Idle connection关闭了连接时,这会发生这种情况。您必须通过实现某种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'。您可以根据您的频道设置和要求将该响应发送给同一用户或向所有用户广播。

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

即使用户闲置,这也应该使连接保持活力。

自第一个版本以来,我就一直没有使用ActionCatclable工作。让我知道某些内容不起作用或任何语法错误,我将尝试修复。

您使用哪个Heroku计划?如果免费 - 不要忘记它在30分钟的不活动后睡觉,可能会导致某些H15错误(空闲连接...)

这可能是因为

  1. HTTP连接未"正常"结束,因为服务器返回101响应(Switching Protocols-建立WebSocket连接) - 或
  2. 在某个时候,基础TCP连接分解(用户移至新WiFi,关闭笔记本电脑等)

是务实的 - 最终的Websocket似乎在基础TCP连接上正常运行。WebSocket连接的任何问题触发了浏览器中的重试逻辑,该逻辑从用户的角度清除了内容 - 因此,尽管此日志消息,该应用程序仍适用于我的用户。

对于我的应用程序,我觉得只忽略Heroku的H15错误代码是安全的,但是如果您有其他情况可能会挂起HTTP请求的其他情况,那对您来说可能是不安全的。

查看Heroku文档以获取参考:

https://devcenter.heroku.com/articles/error-codes#h15-idle-connection

H15-空闲连接

dyno没有发送完整的答复,是 由于不活动的55秒而终止。例如,响应 指示未及时发送的内容长度为50个字节。

2010-10-06T21:51:37-07:00 heroku[router]: at=error code=H15 desc="Idle connection" method=GET path="/" host=myapp.herokuapp.com fwd=17.17.17.17 dyno=web.1 connect=1ms service=55449ms status=503 bytes=18

最新更新