簡體   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