研究会

機械学習、データベース、分散システム、その他技術的なことを書く研究会です

WebRTC による P2P 型分散匿名掲示板 webrtc-bbs を公開しました

概要

WebRTC を利用した P2P ネットワーク上で動作する分散型匿名掲示板システム webrtc-bbs を開発しています。

tsujio/webrtc-bbs - GitHub

また、テストとして現在 Heroku にデプロイしています。

webrtc-bbs.herokuapp.com

f:id:ntsujio:20140706163006p:plain

詳細

WebRTC とはサーバーを介さず Web ブラウザー間でリアルタイム通信を行うための規格・API です。

今回この WebRTC による P2P 接続を多数のクライアント間で行い、Web ブラウザーによるオーバーレイネットワークを構築して、その上で動作する掲示板アプリケーションを実装しました。

内部的な仕組みについては別の記事で紹介します。

なお、まだ開発途中のため 匿名性に関する実装は不十分です 。これにより損害等被った場合は自己責任でお願いします。

このアプリケーションの目的

従来のようなクライアント/サーバー型の Web サービスを提供する場合,規模が大きくなるにつれてサーバー・ネットワーク設備への投資が大きくなってしまいがちでした。

そこで今回のようにサービスを P2P 型で実現できれば、サービス提供者側の負担を抑えられ、また設計次第では 学生のような経済力のない開発者でも世界中で利用されるような Web サービスを展開することができる のではと思います。

今回は掲示板という原始的なシステムですが、応用次第では WikiSNS のような 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 でビデオの多段中継サンプル書いたよ

  • そのうちそれっぽいシステム作りたいよ

  • 早く音声も中継できるようになりたいよ

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 に保存するという対策が取られますが、これはプロセスがデータをハードディスクに保存することと同じことだと考えられます。

図にするとこんな感じになります。

f:id:ntsujio:20140707141736p:plain

この図では「レシピ <---> サーバー」の関係と「プログラム <---> プロセス」の関係を相似と見ることができると思います。対応関係としては次のようになります。

Immutable Infrastructure プロセス
生成元 レシピ プログラム
外部記憶装置 外部 DB HDD
一時記憶 メモリ、HDD メモリ
インスタンス間通信 ネットワーク、DB ネットワーク、ファイルシステム

このような考えに立つと、昨今の流行であるレシピのバージョン管理、レビューや Serverspec によるインフラのテスト等、元々プログラム開発で行われていた技法がインフラ開発に取り入れられたのも納得できます。

また、GitHubTravis CIDocker Hub のようなサービスを連携させて複雑なシステムを組み上げるのも、プロセスをパイプラインで繋いで複雑な処理を行うようなイメージで捉えることができるかと思います。

まとめ

  • Immutable Infrastructure はプロセスだった

  • Immutable Infrastructure ではインスタンス内の HDD は揮発性のメモリと見なそう

  • Docker はまさしくプロセスで Immutable Infrastructure を実現してる

webrtc-chord のバージョン 1.0.0 をリリースしました

概要

以前公開した WebRTC による Chord の実装 webrtc-chord のバージョン 1.0.0 をリリースしました。

tsujio/webrtc-chord - GitHub

詳細

WebRTC で DHT の一種である Chord を実装した webrtc-chord を公開していましたが、この度めでたくバージョン 1.0.0 をリリースすることができました。

公開以来、様々な人からフィードバックを頂きました。特に Scholar Ninja 作者の Jure Triglav さんからは実世界で運用した上での重要なアドバイスを頂きました。

これまでフィードバックを頂いた皆様に感謝の気持ちを表しつつ、今後も多くの人に使っていただけるように改良を続けていきたいと思っています。

内部的な変更点

ノード探索プロトコルの変更

Chord は Finger Table を参照しながら二分探索でノードを探しますが、この探索を Recursive に行っていたのを Iterative に行うようにしました。

図で表すとこんな感じです。

  • Recursive 版

f:id:ntsujio:20140705160459p:plain

  • Iterative 版

f:id:ntsujio:20140705160559p:plain

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

Scholar Ninja ※ 画像はブログより引用

WebRTC で分散ハッシュテーブルの一種である Chord を実装したものを GitHub公開していたところ、Jure Triglav さんという方からそれを利用した学術論文検索エンジンである Scholar Ninja を開発したという知らせを頂きました。

ブログによると、開発の動機としては以下のようなものです。

  1. 世の中には様々な科学技術ソフトウェアがあるが、それらの中から真に「良い」もの (被リンク数、CI の実施等) を検索することは簡単ではない。
  2. それらを検索できるようにするためには例えばどのような論文からどんなソフトウェアが引用されているかに関する大量のデータが必要である
  3. Google Scholar のような論文検索サービスには API が用意されていないか、検索頻度の上限等の制限がある場合が多い
  4. そのような制限のない、 オープンでフリーな API を用意したい

Scholar Ninja は Web ブラウザーのエクステンションであり、Chrome ウェブストアで公開されています

Scholar Ninja をインストールしたブラウザーはそれら自身によって構成される Chord ネットワークに参加し、学術論文を公開している Web サイト (PLOS や eLife, PeerJ, ScienceDirect 等) を訪れ論文を読むとその論文に関する情報が Chord ネットワークにインデックスされます。

なお、インデックスされる情報はタイトルやキーワード、アブストラクト等の情報のみで、フルテキストはインデックスされないとあります。

そして Scholar Ninja の検索枠にキーワードを入力すると、Chord ネットワークからそのキーワードに関連する論文の情報を取得し表示します。

開発は GitHub行われています

まとめ

PeerServer の分散構成

概要

WebRTC の定番ライブラリの一つである PeerJSシグナリングサーバーとして利用される PeerServer を分散構成に対応させました。

tsujio/peerjs-server at distributed-store - GitHub

詳細

WebRTC では相手と通信を始めるために SDP や ICE メッセージの交換を行う必要があり、PeerJS ではそれらのメッセージの中継を行う役割を PeerServer が担っています。

しかし、PeerServer は P2P ネットワークに存在する全てのピアと常時 WebSocket のコネクションを保持しており、ピア数が十分大きくなると破綻してしまうという問題がありました。

そこで WebRTC を利用した大規模な P2P ネットワークを構築できるようにするために、通常一台構成でしか運用できない PeerServer を複数台の分散構成に対応できるようにしました。

構成図

f:id:ntsujio:20140704180134p:plain

解説

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 を

  • 分散構成に

  • 対応した