ActionCable 超时 - Heroku 上的“空闲连接”

Posted

技术标签:

【中文标题】ActionCable 超时 - Heroku 上的“空闲连接”【英文标题】:ActionCable Timeout - "Idle Connection" on Heroku 【发布时间】:2017-04-19 01:25:00 【问题描述】:

我们在 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

我相信我们的设置非常标准,并且紧跟 Rails 的 ActionCable 文档:

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 和 WebSockets 还很陌生,所以我不确定如何解决这个问题。我们正在运行 Rails 5.0.0.1 和 Ruby 2.3.1

非常感谢任何帮助、上下文或故障排除提示!

【问题讨论】:

我有类似的 AC 设置,但我没有收到 H15 错误。你能显示初始化电缆连接的javascript吗? @EmilKampp 我刚刚编辑添加了一些我们的 JavaScript 代码。提前致谢! @JackCollins 我也遇到了同样的问题,你找到解决办法了吗? @SurgePedroza 不,不幸的是还没有解决这个问题 我刚遇到这个问题。所有错误都来自同一用户。否则,交流电工作正常。 ?????? 【参考方案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

即使用户处于空闲状态,这也应该保持连接处于活动状态。

自从 ActionCable 首次发布以来,我就没有使用过它。如果有问题或任何语法错误,请告诉我,我会尝试修复。

【讨论】:

【参考方案2】:

这可能是因为

    HTTP 连接没有“正常”结束,因为服务器返回 101 响应(Switching Protocols - 建立 websocket 连接)- 或 在某些时候,底层 TCP 连接中断(用户移动到新的 wifi,关闭笔记本电脑等)

务实 - 生成的 websocket 似乎在底层 TCP 连接上正常运行。 websocket 连接的任何问题都会触发浏览器中的重试逻辑,这会从用户的角度清理内容 - 因此,尽管有此日志消息,应用程序对我的用户来说仍能正常运行。

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

查看 Heroku 文档以供参考:

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

H15 - 空闲连接

测功机没有发送完整的响应,而是 由于 55 秒不活动而终止。例如,响应 表示 Content-Length 为 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

【讨论】:

【参考方案3】:

你使用哪种heroku计划?如果空闲 - 不要忘记它会在 30 分钟不活动后休眠,这可能会导致一些 H15 错误(空闲连接...)

【讨论】:

请检查计划规范,如果您找到解决方案,请告知我们

以上是关于ActionCable 超时 - Heroku 上的“空闲连接”的主要内容,如果未能解决你的问题,请参考以下文章

在 Heroku 上使用 ActionCable 部署 Rails5 beta3 应用程序时 Redis 密码无效

Heroku 上的 ActionCable 服务器响应时间

部署到heroku后actioncable不起作用

动作电缆在本地订阅,但不在 heroku 上

Heroku Websocket到自定义域

Heroku上NodeJs应用程序中的H12请求超时错误?