スポンサーリンク

2015年6月6日

続!Phoenixのルーティング(Router)について分かったこと

タイトル: 続!Phoenixのルーティング(Router)について分かったこと

目的: ルーティング(Router)のChannel Routesについて分かったことを記述する。

実施環境:
OS: Windows8.1
Erlang: Eshell V6.4
Elixir: v1.0.4
Phoenix Framework: v0.13.1
Node.js: v0.12.4

目次:

  1. 概要
  2. Channel Routesって何?
  3. Channel Routesを使ってみる
  4. おまけ

1.概要

1.1
注意!!
この記事は、Phoenix - Guides RoutingをGoogle翻訳を使い、
素人翻訳して分かったことを書いています。

原文を丸々翻訳しているわけではないので、
流れや説明がおかしいところ多々ありますが、その点注意して下さい。
英語が分かる方は、公式を見た方が確実です。

また、管理人の英語力は本人がドン引きするほど低いので、
間違った解釈及び理解している部分が多分にあると思います。

それでも構わないという方は見て頂けたら嬉しいです。

また、ご指摘等があれば受け付けておりますゆえ、遠慮なくお願いします。
特に間違えて習得している部分は教えて頂ければ、本当に助かります。

1.2
前回の記事: Phoenixのルーティング(Router)について分かったこと

1.3
あらかじめ、テスト用のプロジェクトは作成しておいて下さい。

管理人は、以下の内容で実施しております。
  • アプリケーション名: hello_phoenix
  • 設定は全てデフォルト
  • 作業は、hello_phoenixディレクトリ内で実施(コマンドプロンプトを含む)

1.4
Channelsに関してちょっと余談です。(書くところ違う気がしますが・・・)

Channels Guideの翻訳をするつもりがなくなりました。
今までの独り言とかに色々書いていてどの口が言うのか・・・この口ですorz
より正確に言えば、必要がなくなったですね。

理由は、v0.11.0の翻訳でしたが既に翻訳をされている方がいます。
そちらと原文を参考にした方が効率が良いため、する気がなくなりました。
その分の労力は他に使いたいと思います。

v0.11.0の日本語訳記事ですが、Channels Guide原文を軽く翻訳した感じ・・・
v0.13.1でも問題なく通用しますので、そちらをご参考に実施して下さい。

作者様に感謝を捧げ、記事を利用させて頂きましょう。

2.Channel Routesって何?

2.1
チャネルの詳しい説明は、Channels Guideに投げるとして・・・ここではざっくりと行きます。

チャネルとは、複数のコンポーネントによる階層構造により構成されています。
そして、ソフトリアルタイムの機能をアプリケーションに追加するのがチャネルです。

んで複数のコンポーネントの内の一つが"Channel Routes"と言うことですね。

何故、こいつだけ別記事を上げているのかと言いますと・・・

まず一つ目、この機能の詳細な内容はRouter Guideに出てきていること。
(Channels Guideでは、そちらに投げてますね・・・)

二つ目、Routerの記事を上げた時に理解できなかったか忘れていのか・・・
記事の内容に書いていなかったためです。

2.2
機能自体は簡単です。

チャネルのルーティングを行う機能です。
コントローラと同じように、router.exにルーティング先は記述します。

ルーティング先の定義例としてはこんな感じです。
----
socket "/ws", HelloPhoenix do
  channel "sample_topic:*", SampleTopicChannel
end
----

チャンネルは、特定のトピックのためのソケットを介し
メッセージの受信および送信メッセージを処理する。

チャネルルートは、適切なチャネルへディスパッチするため、
ソケットとトピック別の要求に一致する必要がある。

私達は、ブロック、ソケットのマウントポイントへのパス、
及び完全に私たちのチャネルモジュール名を修飾するために
アプリケーションの名前を持つルータのソケットを定義する。

ようは、前にRouterでやった内容と似たようなこと定義しないとだめよ!ってことですね。

3.Channel Routestを使ってみる

3.1
チャネルのマクロを使用して、
RoomChannelのチャネルモジュールと
rooms:*のトピックでルーティング先を作ってみましょう。

/web/router.exを開いて以下の定義を追加します。
----
socket "/ws", HelloPhoenix do
  channel "rooms:*", RoomChannel
end
----

Tips
トピックは単なる文字列の識別子です。
トピックは以下のような形になります。
トピック: "topic:subtopic"

今回の場合は、
roomsがtopicで、*がsubtopicですね。
(*はワイルドカードとして動作します)

3.2
以下のコマンドでルーティング先を見ます
コマンド: mix phoenix.routes

以下のような出力結果が得られますね。
----
 web_socket_path  GET      /ws                Phoenix.Transports.WebSocket.upgrade/2
 web_socket_path  POST     /ws                Phoenix.Transports.WebSocket.upgrade/2
long_poller_path  OPTIONS  /ws/poll           Phoenix.Transports.LongPoller.options/2
long_poller_path  GET      /ws/poll           Phoenix.Transports.LongPoller.poll/2
long_poller_path  POST     /ws/poll           Phoenix.Transports.LongPoller.publish/2
----

私の環境だと他のルーティング先が追加されていて見辛いので、
Channelの部分だけ抜粋しています。

私達のソケットの定義は、
4つルートと二つの別々のトランスポートメカニズム(WebSocketとLongPolling)を
含むパスに出て、拡張していることに注意して下さい。
(4つ?5つに変わったんだと思う)

3.3
チャネルがトランスポートの一種類のみによって処理されていることを確認したい場合、
このように、オプションを介して指定することができます。

/web/router.exを開いて以下の行を編集して下さい。
変更前: channel "rooms:*", RoomChannel
変更後: channel "rooms:*", RoomChannel, via: [WebSocket]

3.4
コマンド: mix phoenix.routes

あれ?出力変わってないですね・・・
----
 web_socket_path  GET      /ws                Phoenix.Transports.WebSocket.upgrade/2
 web_socket_path  POST     /ws                Phoenix.Transports.WebSocket.upgrade/2
long_poller_path  OPTIONS  /ws/poll           Phoenix.Transports.LongPoller.options/2
long_poller_path  GET      /ws/poll           Phoenix.Transports.LongPoller.poll/2
long_poller_path  POST     /ws/poll           Phoenix.Transports.LongPoller.publish/2
----

原文読んでみましょう・・・
引用
----
If we do this, $ mix phoenix.routes will still show the same four paths, because they are related to the socket, not the channel. Messages for the "rooms:*" topic, however, would all be handled exclusively over WebSockets.
----

これを行う場合、出力結果はまだ、同じ4つのパスが表示されます。
それらはソケットではなく、チャネルに関連しているから。
しかし、メッセージ rooms:*のトピックは、全てWebSocketの上で排他的に処理されます。

多分、こんなこと言ってると思う。
出力が4つ?5つに変わったんだろうけど、問題ないみたいね。
何れにせよ、動かす段になってみないことには分からないね。これは・・・

次行こう!

3.5
各ソケットは、複数のチャネルの要求を処理することができます。

/web/router.exにルーティング先を追加して下さい。
----
socket "/ws", HelloPhoenix do
  channel "rooms:*", RoomChannel, via: [WebSocket]
  channel "foods:*", FoodChannel
end
----

コマンド: mix phoenix.routes

出力変わりませんね。
ソケットの上でチャネルが複数流れるから、
それぞれのチャネルの定義は出てこないと言うことでしょう。

3.6
複数のソケットを定義も定義できるとのこと。
やってみましょう~そうしましょう~。

/web/router.exにルーティング先を追加して下さい。
----
socket "/ws", HelloPhoenix do
  channel "rooms:*", RoomChannel, via: [WebSocket]
  channel "foods:*", FoodChannel
end

socket "/another_ws", HelloPhoenix do
  channel "news:*", NewsChannel
end
----

コマンド: mix phoenix.routes

出力結果
----
 web_socket_path  GET      /ws                Phoenix.Transports.WebSocket.upgrade/2
 web_socket_path  POST     /ws                Phoenix.Transports.WebSocket.upgrade/2
long_poller_path  OPTIONS  /ws/poll           Phoenix.Transports.LongPoller.options/2
long_poller_path  GET      /ws/poll           Phoenix.Transports.LongPoller.poll/2
long_poller_path  POST     /ws/poll           Phoenix.Transports.LongPoller.publish/2
 web_socket_path  GET      /another_ws        Phoenix.Transports.WebSocket.upgrade/2
 web_socket_path  POST     /another_ws        Phoenix.Transports.WebSocket.upgrade/2
long_poller_path  OPTIONS  /another_ws/poll   Phoenix.Transports.LongPoller.options/2
long_poller_path  GET      /another_ws/poll   Phoenix.Transports.LongPoller.poll/2
long_poller_path  POST     /another_ws/poll   Phoenix.Transports.LongPoller.publish/2
----

another_wsのソケットが増えましたね。
各ソケットは、5パスになる。(WebSocket: 2、LongPoller: 3)

4.おまけ

4.1
全てのチャネルを単一のソケット上で処理したい場合・・・
以下のように定義する。
----
socket "/another_ws", HelloPhoenix, via: [WebSocket] do
  channel "news:*", NewsChannel
  channel "pets:*", PetChannel
end
----

これでWebSocket単一で、このチャネルが全て流れる。

4.2
さらに、単一で流しているソケットの中で別のソケットで流したい時は・・・
以下のように定義する。
----
socket "/another_ws", HelloPhoenix, via: [WebSocket] do
  channel "news:*", NewsChannel
  channel "pets:*", PetChannel
  channel "conversations:*", ConversationChannel, via: [LongPoller]
end
----

viaのviaっと。

4.3
Channels Guideに書いてある。
チャットシステムのアプリケーション例がGithub上にある。
また、実際に動作させているものがheroku上で動作している。
参考にすると習得が速い・・・かもしれない。

Heroku Demo: http://phoenixchat.herokuapp.com/

追記(2015/06/06-17:46)
上記のソース一式をクローンして、
ローカルで実行しようとしたんですけど、
何か動かなかったので、私の環境で動かすまでにしたこと書いときます。

まず、普通に動かそうとした。
>mix phoenix.server

ライブラリがないから入れてよって言われた。
ライブラリをダウンロードするため以下のコマンド実行~
>mix deps.get

再度、実行~
>mix phoenix.server

node_modulesがないようなことを言い始めた。
えっ!?mix phoenix.newする時に作ってくれてるんじゃないの?
npm関連を調べてみた。

>npm -v
バージョン表示

入ってるな・・・
じゃあ、node_modulesだけ別のPhoenixアプリケーションからコピーしてきたらどうなるか?

というわけで、適当にPhoenixのアプリケーションを作成した後、
node_modulesのディレクトリごとコピーして対象のアプリケーションにペーストした。

もう一回実行~
>mix phoenix.server

あっ!?動いた!!
よっし、じゃあブラウザでアクセスしてみよう。

うん、heroku上で動作しているサンプルと同じ動きをしている。
おk、これで終わり~

以上!!

以下、参考とさせて頂いたサイト様

管理人の独り言~
Channelsをやりながら、Routingの記事見直してたら・・・
あれ?Channel Routes書いて無くね?っと気づきました。

そして今回の記事を書くこととなったわけですね。
相変わらずの無計画進行~

しかし、高々一項目しかやってないのに・・・
いつも並にページ量あるな・・・
やっぱりRouting Guide長いよ。

人気の投稿