faye是一個(gè)實(shí)時(shí)推送Server,在繼續(xù)之前建議先了解一下faye瑰排∥粞ǎ可以單獨(dú)部署faye server也可以嵌入到rails部署,目前看來(lái)嵌入到rails中剧蚣,是一種能夠比較方便監(jiān)控subscribe支竹、publish、unsubscribe的方式鸠按。
首先在Gemfile
里增加:
gem 'faye-rails'
運(yùn)行
bundle install
打開(kāi)config/application.rb
礼搁,加入以下內(nèi)容
require File.expand_path('../../app/realtime/client_event.rb', __FILE__)
module MyApp
class Application < Rails::Application
...
# faye server
config.middleware.use FayeRails::Middleware, mount: '/faye', timeout: 25 do
map '/notify/**' => NotifyController
map default: NotifyController
add_extension(ClientEvent.new)
end
config.middleware.delete Rack::Lock
end
這里需要一些解釋
- 我在我的faye server上主要subscribe的channel是
/notify/**
,在實(shí)際使用中會(huì)有服務(wù)端生成每個(gè)用戶的channel目尖,以達(dá)到發(fā)送通知消息給用戶的目的馒吴。channel舉例:/notify/078f428a8fecea296480a3a25652bfd1
- 匹配到channel后使用
NotifyController
處理subscribe、unsubscribe瑟曲、publish饮戳。 - 與Github上README不同的地方,README的例子包括他的demo中洞拨,使用了
map default: :block
扯罐。在實(shí)際使用中無(wú)法使用,改成上面代碼塊中的內(nèi)容即可烦衣。 - 增加了extension歹河,在其他文件中定義了,下面會(huì)有說(shuō)明花吟。
- 最后去掉了默認(rèn)
rails s
的Rack
ClientEvent 類的內(nèi)容:
# app/realtime/client_event.rb
class ClientEvent
def incoming(message, callback)
if message['channel'] !~ %r{^/meta/}
if message['data']
if message['data']['token'] != Settings.faye_token
# Setting any 'error' against the message causes Faye to not accept it.
message['error'] = "403::Authentication required"
else
message['data'].delete('token')
end
end
end
callback.call(message)
end
end
對(duì)收到的消息启泣,從配置里讀取Settings.faye_token
匹配一下,做簡(jiǎn)單的驗(yàn)證示辈,避免其他人直接使用curl發(fā)起消息。
接下來(lái)看一下比較關(guān)鍵的NotifyController
類:
# app/realtime/notify_controller.rb
class NotifyController < FayeRails::Controller
channel '/notify/**' do
monitor :subscribe do
puts "Client #{client_id} subscribed to #{channel}"
end
monitor :unsubscribe do
puts "Client #{client_id} unsubscribed from #{channel}"
end
monitor :publish do
puts "Client #{client_id} published #{data.inspect} to #{channel}"
end
end
end
NotifyController
繼承于FayeRails提供的Controller遣蚀,匹配到channel后矾麻,目前只是輸出日志而已纱耻。可以在這里進(jìn)一步的做記錄數(shù)據(jù)庫(kù)等動(dòng)作险耀,監(jiān)控用戶的在線狀態(tài)以及發(fā)送消息數(shù)等功能弄喘。
除了monitor
方法來(lái)監(jiān)控訂閱發(fā)布動(dòng)作意外,F(xiàn)ayeRails還提供了observe
和filter
甩牺。observe
監(jiān)控模型的變化蘑志,filter
對(duì)消息進(jìn)入、發(fā)出進(jìn)行監(jiān)控贬派。詳細(xì)看官方README急但。
現(xiàn)在你就可以使用curl命令測(cè)試是否成功了(假設(shè)token為123456):
curl http://localhost:3000/faye -d 'message={"channel":"/notify/123456", "data": {"content": "hello", "token": "123456" } }'
然后在終端界面上會(huì)顯示:
Client published {"content"=>"hello"} to /notify/123456
如果是訂閱/notify/123456
channel的客戶端的話會(huì)有一個(gè)client_id顯示在Client
后面。這里因?yàn)槭怯胏url命令發(fā)送的搞乏,因此也沒(méi)有顯示波桩。
好了,在客戶端上请敦,或者在服務(wù)端上可以輕松地對(duì)post請(qǐng)求進(jìn)行簡(jiǎn)單的封裝镐躲,就可以發(fā)送實(shí)時(shí)推送消息給Web端了。