WebRTC による P2P 型分散匿名掲示板 webrtc-bbs を公開しました
概要
WebRTC を利用した P2P ネットワーク上で動作する分散型匿名掲示板システム webrtc-bbs を開発しています。
また、テストとして現在 Heroku にデプロイしています。
詳細
WebRTC とはサーバーを介さず Web ブラウザー間でリアルタイム通信を行うための規格・API です。
今回この WebRTC による P2P 接続を多数のクライアント間で行い、Web ブラウザーによるオーバーレイネットワークを構築して、その上で動作する掲示板アプリケーションを実装しました。
内部的な仕組みについては別の記事で紹介します。
なお、まだ開発途中のため 匿名性に関する実装は不十分です 。これにより損害等被った場合は自己責任でお願いします。
このアプリケーションの目的
従来のようなクライアント/サーバー型の Web サービスを提供する場合,規模が大きくなるにつれてサーバー・ネットワーク設備への投資が大きくなってしまいがちでした。
そこで今回のようにサービスを P2P 型で実現できれば、サービス提供者側の負担を抑えられ、また設計次第では 学生のような経済力のない開発者でも世界中で利用されるような Web サービスを展開することができる のではと思います。
今回は掲示板という原始的なシステムですが、応用次第では Wiki や SNS のような CGM (Consumer Generated Media) と呼ばれるサービス、さらには CDN (Content Delivery Network) のようなサービスも実現可能です。またマルチメディアを扱える WebRTC の特性を活かして、サーバーレスな P2P ストリーミング配信を行うことも考えられます。
※ まだ夢は書き足りてないのですが長くなるので別記事にします
2014/07/19 追記: 夢の続きを書きました
まとめ
WebRTC で P2P 匿名掲示板作ってます
悪用しないでね
お金がなくても大規模サービスを展開できるインターネットを
参考
WebRTC でカメラからの映像を多段中継して配信するサンプル
概要
WebRTC を用い、カメラからの映像を多段中継して配信するサンプルを書いてみました。
tsujio / webrtc-relay.html - Gist
詳細
WebRTC はサーバーを介さない P2P 通信を Web ブラウザー間で行うことができます。
さらにカメラやマイクから取得したビデオ、オーディオといったマルチメディアをやり取りする機能を WebRTC は持っています。
これらのことから誰もがやりたくなるのが P2P ビデオストリーミング配信 です。
という訳でカメラから取得したビデオを多段中継するサンプルを公開してみました。
- 利用にあたっての注意
- WebRTC をサポートしているブラウザー でご覧ください
- Chrome では URL のスキームが
file://
の時はカメラ等のデバイスにアクセスできないようです
困ったこと
多段中継するに当たって、現状では映像は中継できるのですが音声は中継できないようです。
この問題についてはここに将来的にサポートするよと書いてある気がします。
まとめ
WebRTC でビデオの多段中継サンプル書いたよ
そのうちそれっぽいシステム作りたいよ
早く音声も中継できるようになりたいよ
Immutable Infrastructure はプロセスとして扱うインフラだった
概要
最近話題の Immutable Infrastructure ですが、一体何者だろうと考えたところ「インフラをプロセスのように扱う」ことだという結論に至りました。
Immutable Infrastructure
Immutable Infrastructure とは昨今話題となっているサーバーインフラについての概念で、サーバーを Immutable、つまり状態をなくすことによって主に管理・運用面で様々な恩恵に与ろうというものです。
与れる恩恵については以下のスライドが分かりやすいです。
Immutable Infrastructure #jawsdays by Naoya Ito
この Immutable Infrastructure について一家言持ってみようということで、その意味について考えてみました。
Infrastructure as Code
Infrastructure as Code とはインフラの構成等をプログラムコードの形で記述しておき、そのコードを実行することで目的のインフラを再現できるようにしておきましょうというものです (参考: Infrastructure as Code - naoyaのはてなダイアリー)。
このインフラの構成をプログラムコード化したものをここではレシピと呼ぶことにします。
Immutable Infrastructure のやり方ではこの Infrastructure as Code に倣ってインフラを構築するレシピを用意し、インフラを気軽に作ったり壊したりできるようにした上で、インフラの状態を更新する時はレシピを更新して再度新たなインスタンスを生成します。
Immutable Infrastructure はプロセスである
Infrastructure as Code によってインフラがレシピ化されました。そのレシピを実行するとサーバーというインスタンスが生成されます。
これは丁度プログラムを実行するとプロセスというインスタンスが生成されることのアナロジーとして見ることができます。
Immutable Infrastructure ではインフラに状態を持たせません。つまりインスタンスを破棄すると保持していたデータは消え、何度インスタンスを生成しても同じ状態のものが得られます。
一方プロセスについても、終了するとメモリは解放され、何度同じプログラムを実行しても同じ状態のプロセスが生成されます (環境変数や引数は外部の状態と見なします)。
また、Immutable Infrastructure ではログ等のインフラに状態を持たせる要素を外部 DB に保存するという対策が取られますが、これはプロセスがデータをハードディスクに保存することと同じことだと考えられます。
図にするとこんな感じになります。
この図では「レシピ <---> サーバー」の関係と「プログラム <---> プロセス」の関係を相似と見ることができると思います。対応関係としては次のようになります。
Immutable Infrastructure | プロセス | |
---|---|---|
生成元 | レシピ | プログラム |
外部記憶装置 | 外部 DB | HDD |
一時記憶 | メモリ、HDD | メモリ |
インスタンス間通信 | ネットワーク、DB | ネットワーク、ファイルシステム |
このような考えに立つと、昨今の流行であるレシピのバージョン管理、レビューや Serverspec によるインフラのテスト等、元々プログラム開発で行われていた技法がインフラ開発に取り入れられたのも納得できます。
また、GitHub や Travis CI、Docker Hub のようなサービスを連携させて複雑なシステムを組み上げるのも、プロセスをパイプラインで繋いで複雑な処理を行うようなイメージで捉えることができるかと思います。
まとめ
Immutable Infrastructure はプロセスだった
Immutable Infrastructure ではインスタンス内の HDD は揮発性のメモリと見なそう
Docker はまさしくプロセスで Immutable Infrastructure を実現してる
webrtc-chord のバージョン 1.0.0 をリリースしました
概要
以前公開した WebRTC による Chord の実装 webrtc-chord のバージョン 1.0.0 をリリースしました。
詳細
WebRTC で DHT の一種である Chord を実装した webrtc-chord を公開していましたが、この度めでたくバージョン 1.0.0 をリリースすることができました。
公開以来、様々な人からフィードバックを頂きました。特に Scholar Ninja 作者の Jure Triglav さんからは実世界で運用した上での重要なアドバイスを頂きました。
これまでフィードバックを頂いた皆様に感謝の気持ちを表しつつ、今後も多くの人に使っていただけるように改良を続けていきたいと思っています。
内部的な変更点
ノード探索プロトコルの変更
Chord は Finger Table を参照しながら二分探索でノードを探しますが、この探索を Recursive に行っていたのを Iterative に行うようにしました。
図で表すとこんな感じです。
- Recursive 版
- Iterative 版
Recursive 版では N_i が
- N_(i+1) に request を送った後、かつ
- N_(i-1) に response を送る前
に N_i が 離脱するとそのリクエスト全体が失敗し、しかも送信元である N_1 はそのことをタイムアウトでしか知ることはできませんでした。
これはノードが頻繁に離脱する P2P 環境には適した設計ではありませんでした。
そこで Iterative 版のように、一旦 N_i から応答を受信すればいつ N_i が離脱してもリクエストが失敗しないようにしました。
コネクションのクローズの通知
ノードがコネクションを使って相手にデータを送信すると同時に相手がそのコネクションを閉じてしまい、結果としてデータが相手に届かないという問題がありました (しかもそのことに送信元は気付けない)。
そこでコネクションを閉じる側はそれ以上データを送ってこないようにあらかじめ shutdown 要求を送信し、それから一定時間待ってコネクションを閉じるようにしました。
高速化
手元の Finger Table を定数時間でルックアップできるようにしたり (当たり前)、ノード ID の比較のアルゴリズムを改良したりしました。
またユーティリティーライブラリとして underscore.js を利用していましたが、高速化のために Lo-Dash を代わりに使うようにしました。
まとめ
webrtc-chord 1.0.0 をリリースしました
利用事例が増えるといいな
OSS を英語で公開するの大事
Node.js で WebRTC を試せる Docker イメージを公開しました
概要
ブラウザー間リアルタイムコミュニケーションを実現する WebRTC の機能を Node.js で使えるようにするプロジェクト node-webrtc をすぐに試せる Docker イメージを Docker Hub で公開しました。
tsujio/node-webrtc - Docker Hub
詳細
WebRTC はブラウザー間で P2P リアルタイムコミュニケーションを実現する規格・API ですが、この機能を Node.js で使えるようにするプロジェクトとして node-webrtc があります。
Node.js で WebRTC の機能が使えるとブラウザーと連携した P2P ネットワークを構築できて色々と夢が広がります。なので node-webrtc を試したくなるのですが、環境の構築に必要なライブラリをインストールするのに手間がかかるし、そもそもベースとなる環境によって必要なライブラリが違ったりして試行錯誤が必要になります。
そこでそれらの下準備を全て終えた Docker イメージを Docker Hub で公開し、誰でも手軽に node-webrtc を試せるようにしました。
以下のコマンドを実行すると node-webrtc のテストが走るようになっています。
docker pull tsujio/node-webrtc docker run tsujio/node-webrtc
また Dockerfile は以下の通りです。
# 自分自身も試行錯誤した結果なので必要最低限になっていない可能性大です。
# # Dockerfile for node-webrtc # FROM ubuntu:latest MAINTAINER tsujio WORKDIR /opt # Install required packages RUN apt-get update -y RUN apt-get install -y git RUN apt-get install -y python python-dev python-pip python-virtualenv RUN apt-get install -y subversion RUN apt-get install -y pkg-config RUN apt-get install -y g++ RUN apt-get install -y libnss3-dev RUN apt-get install -y libasound2-dev RUN apt-get install -y libpulse-dev RUN apt-get install -y libjpeg62-dev RUN apt-get install -y libxv-dev RUN apt-get install -y libgtk2.0-dev RUN apt-get install -y libexpat1-dev RUN apt-get install -y libcups2-dev RUN apt-get install -y libexif-dev RUN apt-get install -y libxss-dev RUN apt-get install -y libgnome-keyring-dev RUN apt-get install -y libudev-dev RUN apt-get install -y libdrm-dev RUN apt-get install -y libgconf2-dev RUN apt-get install -y libgcrypt11-dev RUN apt-get install -y libpci-dev RUN apt-get install -y libxtst-dev RUN apt-get install -y curl # Install Node.js and npm RUN curl http://nodejs.org/dist/v0.10.29/node-v0.10.29-linux-x64.tar.gz | tar xvz ENV PATH $PATH:/opt/node-v0.10.29-linux-x64/bin ENV NODE_PATH /opt/node-v0.10.29-linux-x64/lib/node_modules # Install node-webrtc RUN git clone https://github.com/js-platform/node-webrtc.git RUN cd node-webrtc && npm install -g RUN npm install -g tape node-pre-gyp ws node-static-alias minimist CMD cd $NODE_PATH/wrtc && npm test
まとめ
Node.js で WebRTC なら node-webrtc を
Docker なら作ったものを試してもらう環境を簡単に配布できて便利
インストーラー配布の代わりに Docker イメージ配布が流行ったりして
webrtc-chord を利用した分散型の学術論文検索エンジン Scholar Ninja の紹介
概要
以前公開した WebRTC を用いた Chord 実装である webrtc-chord を利用した分散型の学術論文検索エンジン Scholar Ninja を開発したという知らせを開発者の方から頂いたのでその紹介記事です。
An open distributed search engine for science
Scholar Ninja
※ 画像はブログより引用
WebRTC で分散ハッシュテーブルの一種である Chord を実装したものを GitHub で公開していたところ、Jure Triglav さんという方からそれを利用した学術論文検索エンジンである Scholar Ninja を開発したという知らせを頂きました。
ブログによると、開発の動機としては以下のようなものです。
- 世の中には様々な科学技術ソフトウェアがあるが、それらの中から真に「良い」もの (被リンク数、CI の実施等) を検索することは簡単ではない。
- それらを検索できるようにするためには例えばどのような論文からどんなソフトウェアが引用されているかに関する大量のデータが必要である
- Google Scholar のような論文検索サービスには API が用意されていないか、検索頻度の上限等の制限がある場合が多い
- そのような制限のない、 オープンでフリーな API を用意したい
Scholar Ninja は Web ブラウザーのエクステンションであり、Chrome ウェブストアで公開されています。
Scholar Ninja をインストールしたブラウザーはそれら自身によって構成される Chord ネットワークに参加し、学術論文を公開している Web サイト (PLOS や eLife, PeerJ, ScienceDirect 等) を訪れ論文を読むとその論文に関する情報が Chord ネットワークにインデックスされます。
なお、インデックスされる情報はタイトルやキーワード、アブストラクト等の情報のみで、フルテキストはインデックスされないとあります。
そして Scholar Ninja の検索枠にキーワードを入力すると、Chord ネットワークからそのキーワードに関連する論文の情報を取得し表示します。
まとめ
PeerServer の分散構成
概要
WebRTC の定番ライブラリの一つである PeerJS でシグナリングサーバーとして利用される PeerServer を分散構成に対応させました。
tsujio/peerjs-server at distributed-store - GitHub
詳細
WebRTC では相手と通信を始めるために SDP や ICE メッセージの交換を行う必要があり、PeerJS ではそれらのメッセージの中継を行う役割を PeerServer が担っています。
しかし、PeerServer は P2P ネットワークに存在する全てのピアと常時 WebSocket のコネクションを保持しており、ピア数が十分大きくなると破綻してしまうという問題がありました。
そこで WebRTC を利用した大規模な P2P ネットワークを構築できるようにするために、通常一台構成でしか運用できない PeerServer を複数台の分散構成に対応できるようにしました。
構成図
解説
memcached には「どの PeerServer がどのピアを管理しているか」といった情報が格納されており、PeerServer が新たなピアと接続を確立する度にその情報が登録されます。
各 PeerServer は自身の傘下のピアからメッセージを受け取ると、次のような動作をします。
if 宛先ピアが自身の傘下にいる then WebSocket でそのピアにメッセージを転送 else memcached に宛先ピアがどの PeerServer の傘下にいるか問い合わせる if 宛先ピアを管理している PeerServer が見つかる then その PeerServer にメッセージを転送 else 失敗 endif endif
この構成では、PeerServer が増えても転送にかかる時間は定数オーダーで済みます。また memcached のスケールが容易であることについては説明は不要かと思います。
クライアントの各 PeerServer への振り分けについては、DNS ラウンドロビンやロードバランサーの導入といった古典的な方法もありますが、PeerJS プロジェクト に複数 PeerServer を指定できるようにする修正を pull request として出すのもよいかもしれません。
まとめ
PeerServer を
分散構成に
対応した