------------------------------------------------------------------
              第 348 回 PTT のお知らせ

     ---  Programming Tools and Techniques  ---
------------------------------------------------------------------
■日時: 2008年10月23日(木) 18時30分から
■場所: 情報理工学科会議室
   (早稲田大学大久保キャンパス63号館5階05−06号室)

行き方は

  http://www.ueda.info.waseda.ac.jp/location_j.html

に書いておきました。

■話者:檜山正幸(檜山正幸事務所)
■題名:Erlangを用いたウェブ交換機(仮)
■概要:
Erlangの簡単な紹介とErlangを用いたウェブ上でのメッセージ交換
システムについて述べる。Erlangは1980年代末にエリクソンで開発
された関数型プログラミング言語である。Erlangは軽量な並行プロ
セスの概念を備え、並行処理を簡潔に記述するとともに、マルチコ
アPCあるいは複数PC上での並列・分散処理を容易に可能にする点を
特徴とする。このErlangを用い、ウェブブラウザ間で双方向リアル
タイム通信を行うシステムを開発している。複数ブラウザの間にジ
ャンクチャと呼ばれる中継サーバーを介した通信路を張り、任意の
ブラウザ間で通信したり、同報通信を行ったりすることができる。
ジャンクチャはErlangにより実装されており、サーバー・ブラウザ
間のComet技術を利用した非同期通信と、Erlangのプロセス間通信
を透過的に扱うように設計した。

第 348 回 PTT report

参加者:25名+α
笹田, 立木, 田中, 丸山, 三好, 高橋 (東大), 並木 (農工大), 田
村, 稲津, 石橋, 多田, 鵜川, 佐藤, 岩崎, 寺田 (電通大), 伊知
地 (ラムダ数研), 川本 (フィックスターズ), 日比野 (朝日ネット), 
光林 (GXP), 長 (一橋), 上田, 廣瀬 (早大), 今井, 遠藤 (東芝), 
三廻部 (日本IBM)

質疑応答:
----------------------------------------
Q. リンクする,されるというのはどうするのか?

2つの方法があります。

まず、すでに存在するプロセスにリンクしたいときは、リンクした
い相手のPID(プロセス識別子)を指定して、link/1 という組み込
み関数を呼びます。リンクを解除したいときは unlink/1 です。

2つ目は、新しくプロセスを生成すると同時に親プロセスとのリン
クも作る方法です。spawn_link(アリティは1,2,3,4がある)を使
います。

----------------------------------------
Q. 死んだらデバッグはできるのか?

ランタイムエラーではスタックトレースが生成されるので、これを
目安に検死はできます。が、注意すべき点があります。

1つは、せっかく生成されたスタックトレースを(例外の中継のと
きなど)プログラマが捨ててしまうことです。例外やシグナルの処
理のとき、スタックトレースを保存するようにプログラミングしな
いといけません。

2つめの注意は、末尾呼び出し最適化が働くと、呼び出し履歴がス
タックに残らないことです。スタックトレースをみても、クラッシ
ュの直前の状況が不明なときがあります。

----------------------------------------
Q. プログラムで明示的に処理しないタームを使うことがあるのか

※ これは当日どう答えたか忘れてしまいました。
※ タームはメッセージデータの意味と解釈して、応答を書きます。

プロセスがメッセージキューからメッセージを取り出さない限り、
メッセージは単に貯まるだけです。ランタイムシステムがプロセス
に代わってメッセージ処理をすることはありません。

ライブラリ/フレームワークが、一部のメッセージを処理してくれ
ることはあります。そのようなライブラリ/フレームワークを利用
しているときは、アプリケーションレベルのプログラムで明示的に
書かなくてもメッセージ処理がされることになります。

----------------------------------------
Q. メッセージがたまった状態で main の処理を変えることはできるのか

できます。ただし、できるようにプログラミングしておかないと無
理です。

自前でそのように書くこともできますが、Erlang配布に付属してい
るOTPライブラリを使うほうがいいと思います。OTPの規約に従うだ
けで、コードチェンジをサポートできます。

----------------------------------------
Q. 実行中にプログラムを変更することができるのか

できます。それができることは、Erlangの大きな設計目標ですから。
エリクャ唐フ交換機は、5年、10年単位で止まらずに動いているとの
ことです。

※ 当日言わなかったけど追加します

ここでのプログラム変更は、バグフィックスやリファクタリングで
あり、当然ながら、他のプログラムに影響するような仕様変更は困
難です。メッセージにアプリケーションやプロトコルのバージョン
を埋め込み、新旧のバージョンを同時に動かしながら徐々に移行す
るような手順を実行できるかも知れませんが、なかなかに大変だと
卵zします。

----------------------------------------
Q. 関数を送ることは可狽ゥ

可狽ナす。ラムダ式が送られると考えればいいでしょう。ただし、
途中まで評価された状態(継続のようなもの)を送るわけではなく
て、関数定義を字面で送ると考えてください。

ラムダ式(Erlang用語ではfun)が生成されたときの変数環境(束
縛の状態)も一緒に詰め込まれるとも言えますが(最後にサンプル
コードあり)、Erlangの変数は事実上定数なので、最初から定数で
書いたラムダ式が送られるのと同じことです。

----------------------------------------
Q. IOみたいなものを送ると変なことは起こらないか

IOとはいっても、Erlangの場合はプロセスでラップしてます。例え
ば、Erlangからみたファイルはファイルとして振る舞うプロセスで、
ストリームもメッセージで模倣されます。

「プロセスとしてのIO」なら送っても問題ないと思います。しかし、
より低水準のポート(ポートの先はOSプロセスなど)を他のマシン
に送って操作すると、なにか具合が悪いことが起こるかも知れませ
ん。使ったことも試したこともありませんが、やらないほうがいい
でしょう(プロセスでラップすべき)。

----------------------------------------
Q. supervisor がバグってたらどうなるのか

すべてが台無しです。OTP付属のスーパーバイザーはバグってない
と信じてますし、信じるしかないでしょう。自分でスーパーバイザ
ーを書くのはお勧めできません。

----------------------------------------
Q. データベース用のライブラリはあるのか

エムネジア(MNESIA)と呼ばれる分散データベースが付属してます。

これは、通常のRDBやらSQLと比較すべきものではありません。機箔
Iには、任意のタームをキーに使えるハッシュマップといったとこ
ろです。複雑なことはできません。

しかし、分散環境(クラスター告ャ)では、自動的にレプリケーシ
ョンが行われるので、特定目的(そもそもが交換機用)では安全で
信頼できるストレージとして便利だと思います。

MySQLなどの既存RDBの利用法は、他のプログラミング言語と大差あ
りません。

----------------------------------------
Q. ローミングはできるのか

実行中のプロセスを他のノードへとマイグレーションさせるという
意味のローミングはできません。

あるプロセスが死んだとき、同じ役割りのプロセスを他のノードや
他のマシンで生成して「仕事」を引き継ぐことはできます。しかし
これは、仕事が引き継がれるのであって、プロセスが移動したこと
にはなりません。

----------------------------------------
Q. プロセスのGCはあるのか

誰からも相手にされないでくすぶっているプロセスを殺すようなこ
とですね。あると便利だと思うし、現実に欲しいのですが、ありま
せん。

現状では、自前でPIDをテーブルに登録して管理するような方法し
かありません。そもそも、どのプロセスが不要か/無意味かの判断
が難しいと思います。アプリケーションロジックの観点からでない
と、殺してもいいプロセスの判断ができない気もします。

----------------------------------------
Q. マークすればなんとかなったりしないか

ポインタにあたるものが実体としてありません。メッセージング・
グラフは概念的なもので、実行時に取れる情報からメッセージング・
グラフを描く手段はありません(少なくとも私は知りません)。し
たがって、メッセージング・グラフの孤立ノードや離れ小島を検出
できません。

ただし、上でも言ったように、アプリケーションレベルでグラフの
辺に相当する実体を準備すればハナシは別ですが。

----------------------------------------
Q. 仕事で使っているのか.使っているならどこで使われているのか

私は趣味で使ってます。いまだ仕事とはいえません。

本家エリクャ唐フ交換機以外の利用はあまり知りません。Webアプリ
ケーションのバックエンドには向いていると思います。

すごく著名なものを挙げておきます。

- http://wings.sourceforge.net/ 3Dモデラー
- http://www.ejabberd.im/ インスタントメッセージング・サーバー
- http://www.vendetta-online.com/ マルチプレイヤー・オンラインゲーム

----------------------------------------
Q. メッセージがたまったらどうなるか

どんどんたまるだけです。いずれは悪いことが起きるでしょう。

----------------------------------------
Q. ハードウェアが落ちたらどうなるか

もうどうにもなりません。

ノード(1つのランタイムシステム)が生きていることはハートビ
ートで監視できます。ノードが死んだとは判断できますが、それが
Erlangプログラムのせいか、OSが落ちたのか、ハードウェアが壊れ
たのかは分かりません。

前もって、ノードが落ちたらどうすべきかの対策がなされていれば、
1つのハードウェアが壊れても、クラスター全体としての機狽ロ持
することはできるでしょう。

----------------------------------------
%% qa.erl -*- coding:utf-8 -*-

-module(qa).
-compile(export_all).

start() ->
  spawn(fun main/0).

main() ->
  receive
    Fun when is_function(Fun) ->
      % Funは整数1引数だと仮定する
      io:format("Fun(1) = ~p~n", [Fun(1)]),
      main();
    _Other ->
      % メッセージを捨てる
      main()
  end.

send(Pid, Y) ->
  Pid ! (fun(X)-> X + Y end).

%% 実行例
%%
%% > c(qa).
%% > f(). % 念のため
%% > P = qa:start().
%% > P! fun(X)->X+10 end.
%% > qa:send(P, 3).
----------------------------------------