我们已经在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/