繁体   English   中英

混合redis actioncontroller :: live-Rails应用

[英]mixing redis actioncontroller::live - rails app

我使用的是第一次redis把聊天功能在我的Rails应用程序,以下

我的JavaScript中有`

$(document).ready ->
  source = new EventSource('/messages/events')
  source.addEventListener 'messages.create', (e) ->
    message = $.parseJSON(e.data).message
    console.log(message)
    $(".chat-messages").append "#some code"

在我的消息控制器中

def create
    response.headers["Content-Type"] = "text/javascript"
    attributes = params.require(:message).permit(:content, :sender_id, :sendee_id)
    @message = Message.create(attributes)
    respond_to do |format|
      format.js { render 'messages/create.js.erb' }
    end
    $redis.publish('messages.create', @message.to_json)
  end

  def events
    response.headers["Content-Type"] = "text/event-stream"
    redis = Redis.new
    redis.subscribe('messages.*') do |on|
      on.message do |pattern, event, data|
        response.stream.write("event: #{event}\n")
        response.stream.write("data: #{data}\n\n")
      end
    end
  rescue IOError
    logger.info "Stream closed"
  ensure
    redis.quit
    response.stream.close
  end

问题是,首先,控制台中未记录任何内容,其次,我得到了一些随机的ConnectionTimeoutError错误。 有人知道发生了什么事

先决条件:

  • Ruby 2.0.0+
  • Rails 4.0.0+
  • 雷迪斯
  • 彪马

初始化器:

config/initializers目录中创建redis.rb初始化程序文件,以全球化redis实例。 设置heartbeat线也是一个好主意(5秒到5分钟的时间都可以,取决于您的要求):

$redis = Redis.new

heartbeat_thread = Thread.new do
  while true
    $redis.publish("heartbeat","thump")
    sleep 15.seconds
  end
end

at_exit do
  # not sure this is needed, but just in case
  heartbeat_thread.kill
  $redis.quit
end

控制器:

您需要向ChatController添加pubsub两个方法。 pub的作用是将聊天事件和消息发布到redis ,并sub订阅这些事件。 它看起来应该像这样:

class ChatController < ApplicationController
    include ActionController::Live

    skip_before_filter  :verify_authenticity_token

    def index
    end

    def pub
        $redis.publish 'chat_event', params[:chat_data].to_json
        render json: {}, status: 200
    end

    def sub
        response.headers["Content-Type"] = "text/event-stream"

        redis = Redis.new
        redis.subscribe(['chat_event']) do |on|
            on.message do |event, data|
                response.stream.write "event: #{event}\ndata: #{data}\n\n"
            end
        end
    rescue IOError
        logger.info "Stream Closed"
    ensure
        redis.quit
        response.stream.close
    end
end

在您的routes ,将pub设为POST并将sub设为GET ,然后将路径匹配到/chat/publish/chat/subscribe


Coffeescript / Javascript:

假设聊天应用程序的实际网页位于/chat ,则需要编写一些Javascript才能实际发送和接收聊天消息。

为了便于理解,我们假设您的网页只有一个文本框和一个按钮。 点击按钮应将文本框的内容发布到聊天流,我们可以使用AJAX做到这一点:

$('button#send').click (e) ->
    e.preventDefault()
    $.ajax '/chat/publish',
        type: 'POST'
        data: {
            chat_data: {
                message: $("input#message").val(),
                timestamp: $.now()
            }
        }
        error: (jqXHR, textStatus, errorThrown) ->
            console.log "Failed: " + textStatus 
        success: (data, textStatus, jqXHR) ->
            console.log "Success: " + textStatus

现在,您还需要能够订阅和接收聊天消息。 您需要为此使用EventSource 使用EventSource ,为SSE打开一个通道,以便您可以接收事件,并使用该数据更新视图。 在此示例中,我们仅将它们记录到javascript控制台。

代码应如下所示:

$(document).ready ->
    source = new EventSource('/chat/subscribe')
    source.addEventListener 'chat_event', (e) ->
        console.log(e.data)

启用并行请求:

在开发环境中,您必须通过将这两行添加到config/environments/development.rb来启用并行请求:

config.preload_frameworks = true
config.allow_concurrency = true

现在启动您的浏览器,浏览至/chat并查看魔术。 当您键入一条消息并单击按钮时,该网页的所有实例都会收到该消息。


好的,这就是使用ActionController::LiveRedisrails创建基本聊天应用程序的方式。 最终的代码显然会根据您的要求而有很大不同,但这应该可以帮助您入门。

您应该查看更多资源:

尽管我没有以这种身份使用redis (“实时”数据的中介),但我设法使此功能与Pusher一起使用


雷迪斯

我不明白您如何保持应用程序和Redis之间的连接打开。 您需要适当的Web套接字或并发连接技术来处理更新-据我所知,Redis不会直接处理此问题。

如果查看此示例 ,它将使用一个名为Goliath的服务器来处理asynchronous连接:

当mini-chat连接到服务器时,它将向/ subscribe / everyone发送GET请求,每个人都是通道的名称,并且“ Accept”标头设置为text / event-stream。 流中间件(上方)接收此请求并订阅redis发布/订阅通道。 由于Goliath处于非阻塞状态,因此多个客户端可以监听事件而无需占用Heroku dyno。 服务器发送事件的有效负载如下所示:

这基本上是使用中间件将您连接到Redis服务器-允许您根据需要接收更新


尽管我无法精确指出任何错误,但可以为您提供一些我们正在使用的代码(使用Pusher ):

    #config/initializers/pusher.rb
    Pusher.url = ENV["PUSHER_URL"]

    Pusher.app_id = ENV["PUSHER_APP_ID"]
    Pusher.key = ENV["PUSHER_KEY"]
    Pusher.secret = ENV["PUSHER_SECRET"]

    #app/controllers/messages_controller.rb
    def send_message
        id = params[:id]
        message = Message.find(id).broadcast!
        public_key = self.user.public_key
        Pusher['private-user-' + public_key].trigger('message_sent', {
            message: "Message Sent"
        })
    end

    #app/views/layouts/application.html.erb
    <%= javascript_include_tag "http://js.pusher.com/2.1/pusher.min.js" %>

    #app/assets/javascripts/application.js
    $(document).ready(function(){
    #Pusher
    pusher = new Pusher("************",
        cluster: 'eu'
    )

    channel = pusher.subscribe("private-user-#{gon.user}")
    channel.bind "multi_destroy", (data) ->
        alert data.message

    channel.bind "message_sent", (data) ->
        alert data.message
    });

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM