如何找出谁连接到 ActionCable?
Posted
技术标签:
【中文标题】如何找出谁连接到 ActionCable?【英文标题】:How do I find out who is connected to ActionCable? 【发布时间】:2016-07-06 12:22:52 【问题描述】:我见过ActionCable.server.open_connections_statistics
、ActionCable.server.connections.length
、ActionCable.server.connections.map(&:statistics)
、ActionCable.server.connections.select(&:beat).count
等,但这只是“每个进程”(服务器、控制台、服务器工作者等)。我如何找出目前订阅 ActionCable 的每个人?这应该在每个环境(开发、登台、生产)中的任何 Rails 进程上返回相同的值。例如,在开发控制台中,您还可以看到开发服务器上的连接,因为理论上它们使用相同的订阅适配器(redis、async、postgres)。
Rails 5.0.0.beta3、Ruby 2.3.0
相关ActionCable - how to display number of connected users?
【问题讨论】:
【参考方案1】:如果使用redis
,您可以看到所有的 pubsub 频道。
[2] pry(main)> Redis.new.pubsub("channels", "action_cable/*")
[
[0] "action_cable/Z2lkOi8vbWFvY290LXByb2plL3QvUmVzcG9uXGVyLzEx",
[1] "action_cable/Z2lkOi8vbWFvY290LXByb2plL3QvUmVzcG9uXGVyLzI"
]
这将显示所有 Puma 工作人员的所有 websocket 连接。如果您有多个服务器,它可能也会在此处显示这些服务器。
【讨论】:
有没有办法区分它们,比如按房间或其他? @LoaiGhoraba 我在下面看不到答案。你在其他地方有答案吗? 您知道:您可以对字符串进行 decode64(当然是在斜线之后)并得到如下内容:gid://myproject/User/250581
这个字符串取决于您使用的 identify_by
我猜。跨度>
Redis.new(url: 'redis://:auth_code@ip:port/db_number').pubsub('channels', 'action_cable/*').map |c| Base64.decode64(c.split('/').last)
使用ActionCable.server.pubsub.send(:redis_connection)
获取ActionCable
的Redis连接(而不是自己创建),使用ActionCable.server.pubsub.send(:channel_with_prefix, "action_cable/*")
获取正确的通道名称【参考方案2】:
更具体的ActionCable
(和 Redis)...
假设这个频道:
class RoomChannel < ApplicationCable::Channel
end
从 ActionCable 获取 Redis 适配器,而不是自己创建
(否则您需要提供来自 config/cable.yml
的 URL):
pubsub = ActionCable.server.pubsub
获取频道名称,包括您可能指定的频道前缀
在config/cable.yml
:
channel_with_prefix = pubsub.send(:channel_with_prefix, RoomChannel.channel_name)
从RoomChannel
获取所有连接的频道:
# pubsub.send(:redis_connection) actually returns the Redis instance ActionCable uses
channels = pubsub.send(:redis_connection).
pubsub('channels', "#channel_with_prefix:*")
解码订阅名称:
subscriptions = channels.map do |channel|
Base64.decode64(channel.match(/^#Regexp.escape(channel_with_prefix):(.*)$/)[1])
end
如果您订阅了ActiveRecord
对象,假设为Room
(使用stream_for
),
您可以提取 ID:
# the GID URI looks like that: gid://<app-name>/<ActiveRecordName>/<id>
gid_uri_pattern = /^gid:\/\/.*\/#Regexp.escape(Room.name)\/(\d+)$/
chat_ids = subscriptions.map do |subscription|
subscription.match(gid_uri_pattern)
# compacting because 'subscriptions' include all subscriptions made from RoomChannel,
# not just subscriptions to Room records
end.compact.map |match| match[1]
【讨论】:
NoMethodError(#<:subscriptionadapter::async:0x00007f2b20a45d88> 的未定义方法 `channel_with_prefix') @FavouriteOnwuemene 你在使用 Redis 吗?我写这个答案是专门为 Redis 写的。我可以看到这个方法在 Rails 5.2.3 (github.com/rails/rails/blob/v5.2.3/actioncable/lib/action_cable/…) 中仍然存在,但是 ChannelPrefix 包含在 redis.rb 中而不是 async.rb 或 postgresql.rb 中。以上是关于如何找出谁连接到 ActionCable?的主要内容,如果未能解决你的问题,请参考以下文章
无法连接到 Elastic Beanstalk 上的 ActionCable