在 Rails 上使用 Event Machine Websocket 进行聊天,在开发中运行精简,但在生产中没有

Posted

技术标签:

【中文标题】在 Rails 上使用 Event Machine Websocket 进行聊天,在开发中运行精简,但在生产中没有【英文标题】:Chat made with Event Machine Websocket on rails, running thin worked in development but not production 【发布时间】:2015-04-06 18:04:32 【问题描述】:

我在 Rails 应用程序上创建了一个实时聊天,并使用 EventMachine 运行 Websocket 进行实时聊天。实时聊天在多台机器上的 localhost 上运行。

它还可以在 ubuntu 上开发中的 Amazon EC2 实例上运行,但是当我尝试将其移至生产环境时,实时聊天不再起作用。没有数据来回发送。

这是我的控制器:

@clients = []
  EM.run do
    EM::WebSocket.start(host: "0.0.0.0", port: 3060) do |ws|
      crypt = ActiveSupport::MessageEncryptor.new(ENV['SECRET_KEY_BASE'])
      ws.onopen do |handshake|
        conversation_data = crypt.decrypt_and_verify(handshake.query_string)
        @clients << socket: ws, conv_info: conversation_data
      end

      ws.onclose do
        ws.send "Closed."
        @clients.delete ws
      end

      ws.onmessage do |data|
        data = data.split('L56HTY9999')
        body = data[0]
        key = data[-1]
        conversation = crypt.decrypt_and_verify(key)
        new_message = Message.new(body: body, user_id: conversation[:user_id], conversation_id: conversation[:conversation_id])
        if new_message.save
          @clients.each do |socket|
            if socket[:conv_info][:conversation_id] == conversation[:conversation_id]
              socket[:socket].send new_message.chat_show
            end
          end
        else
          if socket[:conv_info][:user_id] == conversation[:user_id]
            socket[:socket].send new_message.errors.to_json
          end
        end
      end
    end
  end

这是我在页面上的javascript

function addMessage(msg) 
    var content = JSON.parse(msg);
    var context = 
      userImage: content.image,
      author: content.username,
      convoText: content.body,
      time: content.created_at
    ;

    var source = $('#add-newest-comment').html();
    var template = Handlebars.compile(source);


    var newComment = template(context);

    $('#container').append(newComment);
  

  var key = '<%= @conv_id %>';
  var socket, host;
  host = "ws://0.0.0.0:3060?"+ key;

  function onErrors(msg)
    $("#chat-log .error").text( msg);
    setTimeout(function() 
      $( "#chat-log .error" ).text("");
    , 3000);

  
  function socketHealth(msg)
    console.log(msg);
  

  function connect() 
    try 
      socket = new WebSocket(host);

      socketHealth("Socket State: " + socket.readyState);

      socket.onopen = function() 
        socketHealth("Socket Status: " + socket.readyState + " (open)");
      

      socket.onclose = function() 
        socketHealth("Socket Status: " + socket.readyState + " (closed)");
      

      socket.onmessage = function(msg) 
        addMessage(msg.data);
      
     catch(exception) 
      onErrors("Error: " + exception);
    
  

  $(function() 
    connect();
  );


  function send() 
    var text = $("#message").val();
    if (text == '') 

      onErrors("Please Enter a Message");
      return;
    

    try 
      socket.send(text + 'L56HTY9999' + key);
     catch(exception) 
      onErrors("Failed To Send")
    

    $("#message").val('');
  

  $('#message').keypress(function(event) 
    if (event.keyCode == '13')  send(); 
  );

  $("#disconnect").click(function() 
    socket.close()
  );

我正在使用以下命令运行我的服务器:

bundle exec thin start -p 80 -d -l thin.log -P thin.pid

我的网站位于http://puppyplaydate.co/

控制台记录这个

Socket State: 0

messages:153 WebSocket connection to 'ws://0.0.0.0:3060/?aVI0OFVHS2VET3d4OTQ4M2s4Rk5VMld1eVlXOUFoVUFxT1JMSm5LWDJOUEhScU50MzFub2JMQ3Y4NG1uekl3TS0tYnlBU1ZRclErK3QxWERHN0taSTVzUT09--01ec4a49ce0aeef59bee5d5b8e13d7916abc20e1' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED

messages:148 Socket Status: 3 (closed)

我使用 netstat 检查服务器是否正在侦听该端口并将其返回:

tcp        0      0 *:3060                  *:*               LISTEN    

我在网上进行了研究,有人说他们使用“守护进程”gem 在生产环境中运行 websocket?我不确定这是否是我需要的。

我真的卡住了,提前感谢您的帮助!

【问题讨论】:

【参考方案1】:

问题是我运行的是 Thin 服务器而不是 Rails,而不是运行设置为启动 Thin 的 Rails 服务器。

【讨论】:

以上是关于在 Rails 上使用 Event Machine Websocket 进行聊天,在开发中运行精简,但在生产中没有的主要内容,如果未能解决你的问题,请参考以下文章

使用 Capistrano 将 Rails 应用程序部署到多个服务器 - 最佳实践

在移动设备上禁用 Bootstrap 日期选择器的键盘弹出窗口(Rails 4,Jquery)

使用 lambda 或 proc 和 rails-money

Rails视图中的嵌套模型

Rails 5.2 不呈现新视图

使用嵌套资源干燥 Rails 视图