メニュー 閉じる

Python Django Channelsでチャネルレイヤーを有効化する

みなさん、こんにちは。

今回はDjango Channelsの由来となっていると思われるチャネルの設定について、
チュートリアルの記載を翻訳しながらなんとなく理解していこうと思います。

 

チャンネル/チャネル(Channel)とは?

 

そもそもですがDjango ChannelsはHTTPを拡張するプロジェクトとして発足しました。
WebSocketやチャット、IoTプロトコルを処理できる機能です。

この大本がASGIというPythonで共通して定められている仕様になります。

例えばチャットなど同時に複数の場から相互に通信をする必要がある場合、
Aさんの書いた文字をBさんも読める必要があります。

つまり、同じインスタンスを複数のインスタンスが相互に通信できるようにする必要があります。
チャネルは、この種の通信を可能にする
チャネルレイヤーを提供する機能です。

Django3以降ではネイティブASGIをサポートしています。
チャネルではHTTP以外の接続を同期または非同期のどちらでも処理することができます。

 

Django Channels
https://channels.readthedocs.io/en/stable/

 

チャンネルレイヤーを有効にする

 

Django Channelsチュートリアルパート2「チャネルレイヤーを有効にする」より。

 

チャンネル層は通信システムの一種です。
これにより、複数のコンシューマインスタンスがお互いに、そして Django の他の部分と会話することができます。

チャンネル層は以下のような抽象化を提供します。

  • チャンネルはメッセージを送ることができるメールボックスです。
    各チャンネルには名前があります。
    チャンネルの名前を知っている人は誰でもそのチャンネルにメッセージを送ることができます。
  • グループは関連するチャンネルのグループです。グループには名前があります。
    グループの名前を持っている人は誰でも名前でグループにチャンネルを追加/削除したり、
    グループ内の全てのチャンネルにメッセージを送信することができます。
    特定のグループにどのようなチャンネルがあるかを列挙することはできません。

すべてのコンシューマインスタンスは自動的に生成されたユニークなチャンネル名を持っており、
チャンネルレイヤーを介して通信することができます。

私たちのチャットアプリケーションでは、同じ部屋にある複数のChatConsumerのインスタンスをお互いに通信させたいと思います。
これを行うには、各ChatConsumerにそのチャンネルの部屋名に基づいた名前のグループに追加させます。
これにより、ChatConsumersは同じ部屋にいる他のすべてのChatConsumersにメッセージを送信することができます。

バッキングストアとして Redis を使用するチャンネルレイヤーを使用します。
ポート6379でRedisサーバーを起動するには、以下のコマンドを実行します。

 

ここで重要なのは「チャンネル」と「グループ」という2つの概念です。
チャットのチャンネルとほとんどイメージ的に一致すると思います。

グループはチャンネルのまとまりというイメージですが、
ここでのグループは「AグループにZ, Y,  Zのチャンネルがある」という意味というよりは、
「Aグループに属する3つのチャンネル」というイメージだと思いました。

(改めて考えるとちょっと違うような気もするが)

チュートリアルではチャットアプリケーションを作成します。
同じチャンネルにいる複数のChatConsumer(チャット参加者)を互いに通信させます。

そのため、それぞれのChatCousumerをチャンネル名に紐付けたグループに参加させ、
同じ部屋にいるすべてのChatConsumersにメッセージを送信させることができます。

 

突然出てきたRedisとは?

 

Redis(REmote DIctionary Server)はNoSQL型のデータベースです。

と言っても説明になっていないのですが、Not only SQLということで、
単純に言えばSQL文を書かなくて良いデータベースです。
逆に言えば普通のリレーショナル・データベース(RDBMS)はSQLを使うと言えます。

企業のERPパッケージなど部品や製品、販売価格など、
複雑に紐付けが必要なものはRDBMSが向いていると思いますが、
関係モデルを必要としないデータや大量のデータはNoSQLが適しています。

つまり、高頻度に書き込みや読み込みが必要だったり、
巨大なのだけれども書き込みはあまりないようなデータベースに向いています。

Rediaはキーバリュー型と呼ばれる最も単純な構造のNoSQLで、
鍵と値が一意に決まる性質があります。

001-青木さん
002-鈴木さん

・・・

こんな感じのとてもシンプルな構造です。

GoogleのFirebaseというツールではRealtime DatabaseというNoSQLが利用できます。
こちらのデータはJSONフォーマットで保存されるので使いやすいですね。

 

ちゃっかりdocker使ってルヤンゴサウルス!

 

話は戻ってチュートリアルの最後に以下の説明があったのを覚えてますか?

バッキングストアとして Redis を使用するチャンネルレイヤーを使用します。
ポート6379でRedisサーバーを起動するには、以下のコマンドを実行します。

実はこの文章の後このようなコマンドが用意されています。

$ docker run -p 6379:6379 -d redis:5

お気づきだろうか。dockerのコマンドに。
これまでdockerを一切使ってこなかったのに突然dockerを出すのは反則ですよね。

今一番イケてる仮想環境というべきか(詳しくはよく分かってないが)、
とにかくエンジニア界隈ではvagrantではなくdocker一択とまで言われているdockerです。
詳しい説明は今回はしません。

とりあえずまず、自分のマシンにdockerがインストールされているかどうかを判断するには、
単純に上記のコマンドを入力してみます。
もし、dockerがまだインストールされていなかったら公式からインストールしましょう。

昔、仮想環境を使って開発すると聞いた私は、
「どうやったらこのソフトを仮想環境上にインストールするのか」で何日も悩んだことがあります…
例えばAnacondaで開発環境を作っていたとして、これは確かにローカルの上に仮想の環境を作ってますが、
Dockerをどこにインストールするかというのは深く考えなくて良いということです。

(結構、こういうところで悩んだりしませんでしたか?)

結局、仮想の環境と言ってもそのインストールするもの達の動いているレベルがそれぞれ違うので、
確かに同じレベルのところで設定しないと使えないものもありますが、
今回のようなDockerはかなりOSに近いところで動いているものなので、
そのまま何も考えずローカルのPCにインストールしてしまって良いと考えて大丈夫です。

 

docker と docker-compose の初歩
https://qiita.com/hiyuzawa/items/81490020568417d85e86

 

dockerのインストールが終わるとdockerコマンドが使えます。
私は数年前までコマンドとは、説明通り打てばすべて使えると思っていました。

MacだとPython自体が初期設定で使えるために、大体のコマンドは使えていたし、
気づかないうちにインストールされていたモノがほとんどでしたから…

condaコマンドがAnacondaをインストールいていないと使えないとか、
dockerコマンドがDockerをインストールしていないと使えないとか、
わけも分からずやっている人たちもいるのでどのレベルに合わせて書くかというのは難しいですね。

今回のようなチュートリアルなら、
普通にdockerをインストールしていない人はすると記載するのが良いと思います。

ちなみに、うまくdockerがインストールされているとコマンドが使えます。
このとき使っているターミナルは一旦閉じてから再度開き直します。
一応、dockerのバージョンをチェックするコマンドを入力してみましょう。

$ docker version
Client: Docker Engine - Community
Cloud integration: 1.0.2
Version: 19.03.13
API version: 1.40
Go version: go1.13.15
Git commit: 4484c46d9d
Built: Wed Sep 16 16:58:31 2020
OS/Arch: darwin/amd64
Experimental: false

Server: Docker Engine - Community
Engine:
Version: 19.03.13
API version: 1.40 (minimum version 1.12)
Go version: go1.13.15
Git commit: 4484c46d9d
Built: Wed Sep 16 17:07:04 2020
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: v1.3.7
GitCommit: 8fba4e9a7d01810a393d5d25a3621dc101981175
runc:
Version: 1.0.0-rc10
GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd
docker-init:
Version: 0.18.0
GitCommit: fec3683

$ docker-compose version

docker-compose version 1.27.4, build 40524192
docker-py version: 4.3.1
CPython version: 3.7.7
OpenSSL version: OpenSSL 1.1.1g 21 Apr 2020

完璧です。これでようやく先程のコマンドを入力することができます。
今回はredisというデータベースを使うのでそれをDocker Hubから自動でダウンロードしてくれます。

$ docker run -p 6379:6379 -d redis:5

Unable to find image 'redis:5' locally
5: Pulling from library/redis
bb79b6b2107f: Pull complete
1ed3521a5dcb: Pull complete
5999b99cee8f: Pull complete
b15201312e30: Pull complete
8679a64eeaef: Pull complete
1a76a6f77c8a: Pull complete
Digest: sha256:feea0c960408fc8c010ce60519172612b9d3f844eb82dd84785e61b598de308b
Status: Downloaded newer image for redis:5
43919a07d5f12ee2d742c9f1a1965a0dd5dab5b6a4a8d544dc8a6db68874d95c

このコマンドでredisがインストール済みのDockerイメージをダウンロード、
取得したDockerイメージをコンテナ起動、
コンテナのなかでredisを起動してくれています。

今日はこの辺にしておきましょう!また次回も続きをやります。