phoenixとvernemqを連携させる

# はじめに


　世間ではM2MとかIoTとか流行しています。兎にも角にもモノでインターネットしてくれよこのやろう、みたいな案件があちらこちらに飛びかっており、ms単位での応答を求められる顧客からの要求に担当者が絶叫する世界です。

　こと速度を優先するならmqttかwebsocketな世の中。

　尚且つエンプラで頑張るというのであれば、時代のmqttに。

　ということで、今流行のmqttブローカーvernemqをインストールして、phoenixが行っているコンポーネント間のメッセージングをvernemq経由とするまでやってみようと思います。

　mqtt界隈のサイヤ人と呼ばれるvの人お墨付きなので、将来性抜群のブローカーです。

　例によって動作確認はcentos6となります。恐らくcentos7でも動作すると思います（init.d周りを除く）。デビアンマンの方は、適宜読み替えて下さい。やはりOSは枯れていないといけませんね。ロリババァとワインは古いほうが良いのです。

　また、以下の記事でevmとkiex、erlang/OTPとexlirをインストールしていることが前提となります。

　[Elixir/Phoenixを実行してみる](http://qiita.com/yokaigundan/items/0e8da4938bd91fab400b)

# 手順

## install vernemq

<pre>
$ curl https://packagecloud.io/install/repositories/erlio/vernemq/script.rpm.sh | sudo bash
$ sudo yum install vernemq
$ sudo /etc/init.d/vernemq start
</pre>

<pre>
$ sudo vmq-passwd -c /etc/vernemq/vmq.passwd admin
Password:
Reenter password:
$ sudo chown vernemq.vernemq /etc/vernemq/vmq.passwd
</pre>

※1　ここでユーザを作成していないと、後でサーバを起動した際に以下の様なエラーが出ます。
<pre>
[warn] MQTT connection error: :not_authorized
[error] bridge disconnected due to connection error {:connect_error, 5}
[error] ** State machine HelloWorld.PubSub.EMQTT terminating
</pre>

　なお、現在のvernemqはパスワードによるユーザ認証と、トピック単位でのACLに対応しています。これらを制御するUIの類は今のところありません。

※2　ulimitは必要に応じて変更して下さい
<pre>
$ vi /etc/security/limits.conf 
</pre>

## install phoenix_pubsub_vernemq

<pre>
$ vi mix.exs
</pre>

```lang:mix.exs
  defp deps do
    [{:phoenix, "~> 0.14"},
     {:phoenix_ecto, "~> 0.5"},
     {:postgrex, ">= 0.0.0"},
     {:phoenix_html, "~> 1.1"},
     {:phoenix_live_reload, "~> 0.4", only: :dev},
     {:cowboy, "~> 1.0"},
     {:vmq_commons, git: "https://github.com/erlio/vmq_commons.git", compile: "rebar compile"}, # ADD!
     {:phoenix_pubsub_vernemq, "~> 0.0.3"}]                                                     # ADD!
  end
```

<pre>
$ mix deps.get
</pre>

<pre>
$ vi config/config.exs
</pre>

```lang:config.exs
# Configures the endpoint
config :hello_world, HelloWorld.Endpoint,
  url: [host: "localhost"],
  root: Path.dirname(__DIR__),
  secret_key_base: "6Ky0SUdGkrhd6Iri1r76FhDDwDCoq2gTN19U28Lfp/bFfQflixkFCrp4WqodgLUY",
  render_errors: [default_format: "html"],
#  pubsub: [name: HelloWorld.PubSub,           # comment out
#           adapter: Phoenix.PubSub.PG2]       # comnent out
  pubsub: [name: HelloWorld.PubSub,            # ADD!
           adapter: Phoenix.PubSub.VerneMQ,    # ADD!
           host: "localhost",                  # ADD!
           port: 1883,                         # ADD!
           username: "admin",                  # ADD! （上で入力したユーザ名です）
           password: "password",               # ADD! （上で入力したパスワードです）
           client_id: "test_client"]           # ADD!
```

# 確認

　サーバを起動して見ましょう。

<pre>
$ mix phoenix.server
Compiled lib/hello_world.ex
Compiled lib/hello_world/repo.ex
Compiled web/web.ex
Compiled web/router.ex
Compiled web/controllers/page_controller.e
Compiled web/views/error_view.ex
Compiled lib/hello_world/endpoint.ex
Compiled web/views/page_view.ex
Compiled web/views/layout_view.ex
Generated hello_world app

... 略 ...

[info] Running HelloWorld.Endpoint with Cowboy on http://localhost:4000
[info] MQTT connection established
16 Jul 20:23:47 - info: compiled 3 files into 2 files, copied 3 in 1920ms
</pre>

　無事にMQTTブローカーに接続できていることがログから判断できます。また、この状態でサーバにブラウザからアクセスしてみます。

<pre>
[info] GET /
[debug] Processing by HelloWorld.PageController.index/2
  Parameters: %{"format" => "html"}
  Pipelines: [:browser]
[info] Sent 200 in 2ms
[debug] MQTT server subscribed: [{'phoenix:live_reload', 0}]
</pre>

　develop環境で動くphoenixデフォルトのlive_reloadが、MQTTブローカー経由で動作していることが確認できます。

　このような形でphoenixはアプリケーション内で用いられるメッセージングのアダプタを、自由に変更することが可能となっております。公式からは現在、デフォルトであるPhoenix.PubSub.PG2の他に、redis用のアダプタが公開されています。

　我々もこれくらい簡単に夜のお相手を取っ替え引っ替えできたら最高ですね。