UbuntuにRabbitMQをインストールして動かしてみる

調べて見たら、なんだかAMQPの中では、最近(?)は、ActiveMQよりもRabbitMQの方が流行っているっぽい。
メッセージングサービスをちょっと試してみるだけなので、Active MQでもRabbitMQでも違いはないが、ついでのRabbitMQも試してみることにした。

2017年時点で10周年らしく、サイトがActiveMQに比べてずっと近代的な感じだ。

## 環境
Ubuntu 16.04.3 LTS

## インストール

公式サイトのインストールガイドにしたがって進めていく。
https://www.rabbitmq.com/install-debian.html

### 前提条件

新しめのErlang/OTPを入れとけと書いてある。

### アップデートと作業に必要なコマンドをインストールしておく

```bash
root@1047d42606da:/# apt-get update -y && apt-get upgrade -y
root@1047d42606da:/# apt-get install wget -y
```

### Earlangのインストール

```bash
root@1047d42606da:/# erl +V
bash: erl: command not found

# レポジトリ追加
root@1047d42606da:/# wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb
root@1047d42606da:/# dpkg -i erlang-solutions_1.0_all.deb

# Earlangインストール
root@1047d42606da:/# apt-get update -y
root@1047d42606da:/# apt-get install erlang -y

# バージョン確認
root@1047d42606da:/# erl +V
Erlang (SMP,ASYNC_THREADS) (BEAM) emulator version 9.1
root@1047d42606da:/# erl
Erlang/OTP 20 [erts-9.1] [source] [64-bit] [smp:1:1] [ds:1:1:10] [async-threads:10] [kernel-poll:false]
```
### RabbitMQのインストール

```bash
# レポジトル登録
root@1047d42606da:/# echo "deb https://dl.bintray.com/rabbitmq/debian xenial main" | tee /etc/apt/sources.list.d/bintray.rabbitmq.list
# Public key追加
root@1047d42606da:/# wget -O- https://www.rabbitmq.com/rabbitmq-release-signing-key.asc |apt-key add -
root@1047d42606da:/# apt-get update -y
# RabbitMQのインストール
root@1047d42606da:/# apt-get install rabbitmq-server -y

```
## RabbitMQ を動かす

### RabbitMQ起動

```bash:Console1
root@1047d42606da:/# rabbitmq-server start 

              RabbitMQ 3.5.7. Copyright (C) 2007-2015 Pivotal Software, Inc.
  ##  ##      Licensed under the MPL.  See http://www.rabbitmq.com/
  ##  ##
  ##########  Logs: /var/log/rabbitmq/rabbit@1047d42606da.log
  ######  ##        /var/log/rabbitmq/rabbit@1047d42606da-sasl.log
  ##########
              Starting broker... completed with 0 plugins.

```

[RabbitMQ Tutorials](https://www.rabbitmq.com/getstarted.html)を元に動かしてみる。

### 単純なMessage Queuingを試してみる

[Tutorial](https://www.rabbitmq.com/tutorials/tutorial-one-python.html)をもとに進めてみる。
動かすだけならばサンプルコードをcloneして使うだけで十分なのでとりあえずは動かしてみてから、[Tutorial](https://www.rabbitmq.com/tutorials/tutorial-one-python.html)の解説を確認してみる。

別のコンソールを立ち上げる。

#### サンプルコードを動かす環境を整える

##### Pythonのインストール

```bash:Console2
root@1047d42606da:/tmp# python3 -V
Python 3.5.2
root@1047d42606da:/tmp/sender# apt-get install python3-venv -y
```

##### gitのインストールとサンプルコードのclone

```bash:Console2
root@1047d42606da:/tmp# apt-get install git -y
root@1047d42606da:/tmp# git clone https://github.com/rabbitmq/rabbitmq-tutorials.git
root@1047d42606da:/tmp# ls -l
drwxr-xr-x 25 root root 4096 Dec  3 14:12 rabbitmq-tutorials
```

##### サンプルコードを実行環境にコピー

```bash:Console2
root@1047d42606da:/tmp# mkdir hello-world && cd hello-world
root@1047d42606da:/tmp/hello-world# cp ../rabbitmq-tutorials/python/send.py ../rabbitmq-tutorials/python/receive.py .
root@1047d42606da:/tmp/hello-world# ls -l
-rwxr-xr-x 1 root root  467 Dec  3 14:17 receive.py
-rwxr-xr-x 1 root root  371 Dec  3 14:17 send.py
```

#### 送信 (Producer)

別コンソールを立ち上げsend.pyを実行する。

```bash:Console3
root@1047d42606da:/tmp# cd hello-world/
root@1047d42606da:/tmp/hello-world# python3 -m venv .
root@1047d42606da:/tmp/hello-world# source bin/activate
(hello-world) root@1047d42606da:/tmp/hello-world# pip install pika
(hello-world) root@1047d42606da:/tmp/hello-world# python send.py 
(hello-world) root@1047d42606da:/tmp/hello-world# python send.py 
 [x] Sent 'Hello World!'
```
メッセージが送信された。

別コンソールを立ち上げをQueueに入ったメッセージ数を確認する。

```bash:Console4
(hello-world) root@1047d42606da:/tmp/hello-world# rabbitmqctl list_queues
Listing queues ...
hello	1
```

#### 受信 (Consumer)

別コンソールを立ち上げrecive.pyを実行する。

```bash:Console5
root@1047d42606da:/tmp# cd hello-world/
root@1047d42606da:/tmp/hello-world# source bin/activate
(hello-world) root@1047d42606da:/tmp/hello-world# python receive.py 
 [*] Waiting for messages. To exit press CTRL+C
 [x] Received b'Hello World!'
```
別コンソールで送信していたメッセージが受信されている。

別コンソールを立ち上げをQueueに入ったメッセージ数を確認する。

```bash:Console4
(hello-world) root@1047d42606da:/tmp/hello-world# rabbitmqctl list_queues
Listing queues ...
hello	0
```
hello Queueからメッセージが取り出されていることが確認できる。

#### Producer (send.py)の中身を見てみる

```python:send.py
import pika
```
[Pypi](https://pypi.python.org/pypi/pika)の説明をみると、
PikaはRabbitMQのPython用Clientライブラリらしい。
PikaはRabbitMQのExtensionを含んだAMQPプロトコルのPurePython実装らしい。
PikaはいくつかのAdapter(Connection)を提供しているが、今回のサンプルではBlockingConnectionを使用している。

* BlockingConnection - 単純な用途に使う同期的なブロッキング処理を可能にする


localhostのBrokerに接続する。

```python:send.py
connection = pika.BlockingConnection(pika.ConnectionParameters(
        host='localhost'))
channel = connection.channel()
```

使用するQueueを宣言する。 (hello)

```python:send.py
channel.queue_declare(queue='hello')
```

'hello' Queueに 'Hello World!' というメッセージを送信して、コネクションをクローズする。

```python:send.py
channel.basic_publish(exchange='',
                      routing_key='hello',
                      body='Hello World!')
print(" [x] Sent 'Hello World!'")
connection.close()
```
#### Consumer (recieve.py)の中身を見てみる

localhostのBrokerに接続する。

```python:recieve.py
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(
        host='localhost'))
channel = connection.channel()
```

使用するQueueを宣言する。 (hello)

```python:recieve.py
channel.queue_declare(queue='hello')
```
メッセージ受信時にPikaに呼ばれるコールバックを作成する。
ここでは単純に受信したメッセージをプリントするだけ。

```python:recieve.py
def callback(ch, method, properties, body):
    print(" [x] Received %r" % body)
```

RabbitMQにcallbackに'hello' Queueからのメッセージを受け取ることを教える。

```python:recieve.py
channel.basic_consume(callback,
                      queue='hello',
                      no_ack=True)
```

データを待ち受けコールバックを実行する無限ループに入る。

```python:recieve.py
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()
```