You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rails应用中集成faye-websocket-ruby客户端监听WebSocket流?

嘿,我来帮你搞定把这段faye-websocket客户端代码集成到Rails应用里的事儿!你之前看到的是独立脚本,其实不用单独跑EventMachine,Rails本身的环境就能很好适配,下面分几种常用场景给你一步步说明:

集成faye-websocket-ruby到Rails应用的几种方式

1. 在后台任务里运行(最推荐)

WebSocket连接需要长期保持,直接在请求周期里跑会阻塞请求,所以用后台任务是最合适的选择,比如用Sidekiq或者Rails内置的Active Job。

操作步骤:

  • 先在Gemfile里添加依赖,然后执行bundle install:
# Gemfile
gem 'faye-websocket'
  • 创建一个后台任务文件,比如app/jobs/websocket_listener_job.rb:
class WebSocketListenerJob < ApplicationJob
  queue_as :default

  def perform
    require 'faye/websocket'
    require 'eventmachine'

    EM.run do
      ws = Faye::WebSocket::Client.new('ws://www.example.com/')

      ws.on :open do |event|
        Rails.logger.info [:websocket_open]
        ws.send('Hello from Rails!')
      end

      ws.on :message do |event|
        Rails.logger.info [:websocket_message, event.data]
        # 这里可以处理收到的消息,比如存到数据库或者触发其他业务逻辑
        # 示例:Notification.create(content: event.data)
      end

      ws.on :close do |event|
        Rails.logger.info [:websocket_close, event.code, event.reason]
        ws = nil
        # 如果需要断线重连,可以在这里重新调用任务或者设置定时器
        # EM.add_timer(5) { perform }
      end

      # 处理服务器重启信号,优雅关闭连接
      Signal.trap('INT') { EM.stop }
      Signal.trap('TERM') { EM.stop }
    end
  end
end
  • 启动后台任务:
    终端运行rails runner "WebSocketListenerJob.perform_now",如果用Sidekiq的话,启动Sidekiq服务后调用WebSocketListenerJob.perform_later即可。

2. 在Rails初始化时启动(适合常驻进程)

如果你希望Rails服务器启动时就自动建立WebSocket连接,可以把代码放到初始化文件里,但要注意用线程包裹避免阻塞Rails启动。

操作步骤:

  • 创建config/initializers/websocket_listener.rb:
if Rails.env.production? || Rails.env.development?
  Thread.new do
    require 'faye/websocket'
    require 'eventmachine'

    EM.run do
      ws = Faye::WebSocket::Client.new('ws://www.example.com/')

      ws.on :open do |event|
        Rails.logger.info [:websocket_open]
        ws.send('Hello from Rails initializer!')
      end

      ws.on :message do |event|
        Rails.logger.info [:websocket_message, event.data]
        # 这里添加你的业务逻辑处理
      end

      ws.on :close do |event|
        Rails.logger.info [:websocket_close, event.code, event.reason]
        ws = nil
        # 断线重连逻辑
        EM.add_timer(10) { Thread.new { self.class.connect } } # 可以把连接逻辑抽成方法复用
      end
    end
  end
end

注意:用Thread包裹是为了不阻塞Rails的启动流程,同时要确保线程安全,处理好资源释放。

3. 在控制器里临时使用(不推荐生产环境)

不建议在控制器里直接运行,因为HTTP请求是短连接,WebSocket是长连接,容易导致请求超时,但如果只是临时测试可以这么做:

class WebSocketTestController < ApplicationController
  def index
    require 'faye/websocket'
    require 'eventmachine'

    # 用EM.defer异步处理,避免阻塞当前请求
    EM.defer do
      EM.run do
        ws = Faye::WebSocket::Client.new('ws://www.example.com/')

        ws.on :open do |event|
          Rails.logger.info [:open]
          ws.send('Hello from controller!')
        end

        ws.on :message do |event|
          Rails.logger.info [:message, event.data]
          # 可以把消息存到数据库,但要注意线程安全
        end

        ws.on :close do |event|
          Rails.logger.info [:close, event.code, event.reason]
          ws = nil
          EM.stop
        end
      end
    end

    render plain: 'WebSocket客户端已启动,查看日志获取消息'
  end
end

警告:这种方式只适合测试,生产环境下每个请求都会创建新连接,还可能和Rails服务器(比如Puma)的EventLoop冲突。

关键注意事项

  • 断线重连:生产环境一定要加断线重连逻辑,避免连接断开后就停止监听。
  • 日志替代puts:用Rails.logger代替p,方便在Rails日志里统一查看WebSocket的状态和消息。
  • 线程安全:如果在多线程环境(比如Puma)下运行,要确保WebSocket的操作是线程安全的,避免资源竞争。
  • 环境隔离:可以根据Rails环境(开发/生产)调整连接逻辑,比如开发环境用测试WebSocket服务。

内容的提问来源于stack exchange,提问作者jeanbaptistebeck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:02:52