4-2 什麼是WebSocket; Action Cable的使用。Rails guide-6.3視頻教學,沒有看!

WebSocket

WebSocket是一種在單個TCP鏈接上進行全雙工通信的協議。WebSocket通訊協議於2011年被IETF定爲標準RFC 6455,並由RFC7936補充規範。WebSocket API也被W3C定爲標準。javascript

WebSocket使得客戶端和服務器之間的數據交換變得更加簡單,容許服務端主動向客戶端推送數據。在WebSocket API中,瀏覽器和服務器只須要完成一次握手,二者之間就直接能夠建立持久性的鏈接,並進行雙向數據傳輸。html

背景:java

如今,不少網站爲了實現推送技術,所用的技術都是輪詢。輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對服務器發出HTTP請求,而後由服務器返回最新的數據給客戶端的瀏覽器。這種傳統的模式帶來很明顯的缺點,即瀏覽器須要不斷的向服務器發出請求,然而HTTP請求可能包含較長的頭部,其中真正有效的數據可能只是很小的一部分,顯然這樣會浪費不少的帶寬等資源。git

在這種狀況下,HTML5定義了WebSocket協議,能更好的節省服務器資源和帶寬,而且可以更實時地進行通信。github

優勢:web

  • 較少的控制開銷。在鏈接建立後,服務器和客戶端之間交換數據時,用於協議控制的數據包頭部相對較小
  • 更強的實時性。因爲協議是全雙工的,因此服務器能夠隨時主動給客戶端下發數據。相對於HTTP請求須要等待客戶端發起請求服務端才能響應,延遲明顯更少
  • 保持鏈接狀態。於HTTP不一樣的是,Websocket須要先建立鏈接,這就使得其成爲一種有狀態的協議,以後通訊時能夠省略部分狀態信息。而HTTP請求可能須要在每一個請求都攜帶狀態信息(如身份認證等)。

 https://zh.wikipedia.org/wiki/WebSocketredis

 


 

Action Cable數據庫

1. a thick strong metal rope used on ships, to support bridges etcapi

經過提供Client Javascript框架和Server端Ruby框架把 WebSocket協議和Rails應用集成起來。數組

 

2. Publish-Subscribe功能

指定好發佈者和訂閱者,以後發佈者自動發送新數據給訂閱者。比傳統方式高效。 

3 Server-Side Components

3.1 Connections 第一步鏈接設置。

 

Connections are instances of ApplicationCable::Connection.對鏈接的受權就是在這個類中完成的,對可以識別的用戶會創建 consumer-connection pair.

module ApplicationCable
  class Connection < ActionCable::Connection::Base
    # 聲明鏈接標誌索引,用於以後查找指定鏈接
    identified_by :current_user
 
    def connect
      # 嘗試鏈接,把cookie發送給鏈接實例self。
      # 設置current_user,以後就能檢索指定用戶打開的全部鏈接。
      self.current_user = find_verified_user
      logger.add_tags 'ActionCable', current_user.name
    end
 
    protected
      def find_verified_user
        if verified_user = User.find_by(id: cookies.signed[:user_id])
          verified_user
        else
          #模塊自帶方法, 若是找不到,就關閉鏈接,返回404提示,就是下面2句話。
          # logger.error "An unauthorized connection attempt was rejected"
          # raise UnauthorizedError
          reject_unauthorized_connection
        end
      end
  end
end

identified_by(*identifiers)中的核心語法是:attr_accessor identifier, 就是創建一個存取宏, 產生一個實例名字和存取它的方法。而後把它放入這個數組集合中。

def identified_by(*identifiers) Array(identifiers).each { |identifier| attr_accessor identifier } self.identifiers += identifiers end
 

 

3.2 Channels

相似controller作的標準MVC步驟。 

http://api.rubyonrails.org/classes/ActionCable/Channel/Base.html  (api)

Rails creates ApplicationCable::Channel class 封裝共享的邏輯在你的各channels.

3.21 Parent Channel Setup 

你本身建立本身的channel類,繼承它。 命令:rails generate channel products。

pasting

在類中定義訂閱subscribed

 

,取消訂閱,拒絕訂閱reject(資質審覈)等10多個方法。

# app/channels/chat_channel.rb

class ChatChannel < ApplicationCable::Channel # 當用戶成爲此頻道的訂閱者時調用
  def subscribed

    。 

  end

end 

 

4 Client-Side Components 

4.1 Connections

Consumers require an instance of the connection on their side. This can be established using the folling JavaScript, which is generated by default by Rails :

4.11 Connect Consumer

identical  app/assets/javascripts/cable.js 

// Action Cable provides the framework to deal with WebSockets in Rails.
// You can generate new channels where WebSocket features live using the `rails generate channel` command.
//
//= require action_cable
//= require_self
//= require_tree ./channels
 
(function() {
  this.App || (this.App = {});
 
  App.cable = ActionCable.createConsumer();
 
}).call(this);

4.12 Subscriber

A consumer becomes a subscriber by creating a subscription to a given channel:

 create  app/assets/javascripts/channels/products.coffee

App.products = App.cable.subscriptions.create "ProductsChannel",

 

  connected: ->
    # Called when the subscription is ready for use on the server
  disconnected: ->
    # Called when the subscription has been terminated by the server
  received: (data) ->
    # Called when there's incoming data on the websocket for this channel

 

 

5. Client-Server Interactions 交互

 

 create  app/channels/products_channel.rb

5.1 Streams

Streams provide the mechanism by which channels route published content (broadcasts) to their subscribers. 

 

若是和模型關聯的流,用stream_for
class CommentsChannel < ApplicationCable::Channel       
  def subscribed 
    post = Post.find(params[:id]) 
stream_for post 

   end

end 

向評論頻道發送廣播的方式以下:

CommentsChannel.broadcast_to(@post, @comment

 

發生命名的廣播用stream_from ,見api 

流的方法:

 

5.2 Broadcasting

A broadcasting is a pub/sub link 

 CommentsChannel.broadcast_to(@post, @comment)

 

5.3 Subscriptions

This Connection is called a subscription. Incoming messages are then routed to these channel subscriptions based on an identifier sent by the cable consumer.

 

5.4 Passing Parameters to Channels

You can pass para from the client side to the server side when creating a subscriptin. For example:

  def subscribed
     stream_from "chat_#{params[:room]}"
   end

 

5.5 Rebroadcasting a Message

 A common use case is to rebroadcast a message sent by one client to any other connected clients.

   def receive(data)
   ActionCable.server.broadcast( "chat_#{params[:room]}" , data)
   end

 

The rebroadcast will be received by all connected clients, including the client that sent the message. Note that params are the same as they were when you subscribed to the channel.

 

 


一個基礎功能演示的案例(不包含connection.rb)

https://www.cnblogs.com/chentianwei/p/9296887.html 

使用broadcast功能渲染首頁部分頁面:

3步驟:第一創建頻道,第二發送這個頻道的信息,第三選擇接收信息的位置。

⚠️本案例沒有涉及到用戶對平淡的訂閱和鏈接。即在assets/channels/XXX_channel.rb 中設置鏈接。

 


 

 https://github.com/rails/actioncable-examples

 徹底的案例:

須要按照redis數據庫。簡介:Redis 是徹底開源免費的,遵照BSD協議,是一個高性能的key-value數據庫。菜鳥教程(redis)

  下載的進程截圖:
 

 

==> Downloading https://homebrew.bintray.com/bottles/redis-4.0.9.sierra.bottle.tar.gz

 

######################################################################## 100.0%
==> Pouring redis-4.0.9.sierra.bottle.tar.gz
==> Caveats
To have launchd start redis now and restart at login:
  brew services start redis
Or, if you don't want/need a background service you can just run:
  redis-server /usr/local/etc/redis.conf
==> Summary
🍺  /usr/local/Cellar/redis/4.0.9: 13 files, 2.8MB

 

 brew services start redis
==> Successfully started `redis` (label: homebrew.mxcl.redis)

 

啓動:

$ redis-server

 查看是否啓動 redis-cli ,這個命令打開終端。ping一下,pong就是成功安裝了。

 


一個gem 'puma'一直安裝不上,提示❌?怎麼辦?

後來查了不少資料,獲得提示安裝更高級的版本。

成功了,可是卻要求低版本配置。

而後直接在gemfile.lock文件中找到puma修改版本到3.10.而後bundle install成功。

《Rails5敏捷開發》第406頁,24.3:

bundle install以Gemfile.lock爲準,安裝指定的gem版本。哈哈哈哈哈。!!我居然一直忽略了。 

 


 

看guide上的聊天窗口案例:fork下來後,看不懂:

 

  •  coffee.script不是很懂。javescript也會。
  •  明天再試試,已經看了一半了。對比着中文guide看。
4-9上午學完案例結構,下午學習頻道模塊的用法。

 

缺陷:不懂coffee.scripte.jiavascripte語法。 

對數據庫的部署也不熟悉,看案例的很困難,這個action cable比較難。設計多個模塊。 


 

6 案例

7 configuration

rails guide的沒有更新須要配合git上的相同內容。

包括3個required configurations:

  1. a subscription adapter
  2. allowed request origins
  3. the cabel server URL(在client side 可選擇的設置)

 

7.1 Subscription Adapter

什麼是adapter?(9 Dependencies)

Action Cable提供了一個訂閱adapter interface來處理它的內部發布和訂閱。默認是async adapter(可用於開發和測試)。
adapter可使用: Async, Redis, PostgreSQL adapter

 

 

默認ActionCable 會尋找配置文件config/cable.yml。這個文件必須指定an adapter爲每一個Rails環境。

development:
  adapter: redis
  url: redis://localhost:6379/1

test:
  adapter: async

production:
  adapter: redis
  url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>  #指向Redis server
  channel_prefix: Wechat_production    #用於避免頻道名字重複,當使用相同的餓Redis server爲多個applications時。

 

 

Allowed Request Origins

Action Cable將只接受那些指定源頭specific origins的請求 。

具體見ActionCable的部署: https://www.cnblogs.com/chentianwei/p/9900012.html

 

Consumer Configuration

具體見ActionCable的部署: https://www.cnblogs.com/chentianwei/p/9900012.html

https://github.com/rails/rails/tree/master/actioncable

相關文章
相關標籤/搜索